diff --git a/include/API/Device.h b/include/API/Device.h index 089416ed3..f5beb4a9f 100644 --- a/include/API/Device.h +++ b/include/API/Device.h @@ -20,6 +20,7 @@ #include "API/Capabilities.h" #include "API/CommandBuffer.h" #include "API/RenderPass.h" +#include "API/Sampler.h" #include "API/ShaderBindingTable.h" #include "API/Texture.h" @@ -346,6 +347,9 @@ class Device { virtual llvm::Expected> createTexture(std::string Name, const TextureCreateDesc &Desc) = 0; + virtual llvm::Expected> + createSampler(std::string Name, const SamplerCreateDesc &Desc) = 0; + virtual llvm::Expected> createMemoryHeap(std::string Name, size_t SizeInBytes) = 0; diff --git a/include/API/Sampler.h b/include/API/Sampler.h new file mode 100644 index 000000000..121c3470c --- /dev/null +++ b/include/API/Sampler.h @@ -0,0 +1,67 @@ +//===- Sampler.h - Offload API Texture ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +#ifndef OFFLOADTEST_API_SAMPLER_H +#define OFFLOADTEST_API_SAMPLER_H + +#include "API/API.h" +#include "API/Resources.h" + +namespace offloadtest { + +enum class FilterMode { Nearest, Linear }; + +enum class AddressMode { Clamp, Repeat, Mirror, Border, MirrorOnce }; + +enum class CompareFunction { + Never, + Less, + Equal, + LessEqual, + Greater, + NotEqual, + GreaterEqual, + Always +}; + +enum class SamplerKind { Sampler, SamplerComparison }; + +struct SamplerCreateDesc { + FilterMode MinFilter = FilterMode::Linear; + FilterMode MagFilter = FilterMode::Linear; + AddressMode Address = AddressMode::Clamp; + float MinLOD = 0.0f; + float MaxLOD = std::numeric_limits::max(); + float MipLODBias = 0.0f; + CompareFunction ComparisonOp = CompareFunction::Never; + SamplerKind Kind = SamplerKind::Sampler; +}; + +class Sampler { + GPUAPI API; + +public: + virtual ~Sampler(); + Sampler(const Sampler &) = delete; + // Sampler(Sampler &&) = delete; + Sampler &operator=(const Sampler &) = delete; + // Sampler &operator=(Sampler &&) = delete; + + GPUAPI getAPI() const { return API; } + virtual const SamplerCreateDesc &getDesc() const = 0; + +protected: + explicit Sampler(GPUAPI API) : API(API) {} +}; + +} // namespace offloadtest + +#endif // OFFLOADTEST_API_SAMPLER_H diff --git a/include/API/Texture.h b/include/API/Texture.h index 1b851393b..0c80f9903 100644 --- a/include/API/Texture.h +++ b/include/API/Texture.h @@ -105,12 +105,6 @@ inline llvm::Error validateTextureCreateDesc(const TextureCreateDesc &Desc) { std::errc::not_supported, "DepthStencil combined with Storage is not yet supported."); - // Depth formats require DepthStencil usage; non-depth formats forbid it. - if (IsDepth && !IsDS) - return llvm::createStringError( - std::errc::invalid_argument, - "Depth format '%s' requires DepthStencil usage.", - getFormatName(Desc.Fmt).data()); if (!IsDepth && IsDS) return llvm::createStringError( std::errc::invalid_argument, diff --git a/include/Support/Pipeline.h b/include/Support/Pipeline.h index f8dc1785d..e62681f46 100644 --- a/include/Support/Pipeline.h +++ b/include/Support/Pipeline.h @@ -16,6 +16,7 @@ #include "API/AccelerationStructure.h" #include "API/Enums.h" #include "API/Resources.h" +#include "API/Sampler.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -140,24 +141,7 @@ static inline DescriptorKind getDescriptorKind(ResourceKind RK) { llvm_unreachable("All cases handled"); } -enum class FilterMode { Nearest, Linear }; - -enum class AddressMode { Clamp, Repeat, Mirror, Border, MirrorOnce }; - -enum class CompareFunction { - Never, - Less, - Equal, - LessEqual, - Greater, - NotEqual, - GreaterEqual, - Always -}; - -enum class SamplerKind { Sampler, SamplerComparison }; - -struct Sampler { +struct YAMLSampler { std::string Name; FilterMode MinFilter = FilterMode::Linear; FilterMode MagFilter = FilterMode::Linear; @@ -270,7 +254,7 @@ struct Resource { DirectXBinding DXBinding; std::optional VKBinding; CPUBuffer *BufferPtr = nullptr; - Sampler *SamplerPtr = nullptr; + YAMLSampler *SamplerPtr = nullptr; bool HasCounter = false; std::optional TilesMapped; bool IsReserved = false; @@ -630,7 +614,7 @@ struct Pipeline { IOBindings Bindings; llvm::SmallVector PushConstants; llvm::SmallVector Buffers; - llvm::SmallVector Samplers; + llvm::SmallVector Samplers; llvm::SmallVector Results; llvm::SmallVector Sets; DispatchParametersSet DispatchParameters; @@ -671,7 +655,7 @@ struct Pipeline { return nullptr; } - Sampler *getSampler(llvm::StringRef Name) { + YAMLSampler *getSampler(llvm::StringRef Name) { for (auto &S : Samplers) if (Name == S.Name) return &S; @@ -712,7 +696,7 @@ struct Pipeline { LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::DescriptorSet) LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::Resource) LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::CPUBuffer) -LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::Sampler) +LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::YAMLSampler) LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::Shader) LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::dx::RootParameter) LLVM_YAML_IS_SEQUENCE_VECTOR(offloadtest::Result) @@ -744,8 +728,8 @@ template <> struct MappingTraits { static void mapping(IO &I, offloadtest::CPUBuffer &R); }; -template <> struct MappingTraits { - static void mapping(IO &I, offloadtest::Sampler &S); +template <> struct MappingTraits { + static void mapping(IO &I, offloadtest::YAMLSampler &S); }; template <> struct MappingTraits { diff --git a/lib/API/DX/Device.cpp b/lib/API/DX/Device.cpp index 60949a287..5c6f0ff67 100644 --- a/lib/API/DX/Device.cpp +++ b/lib/API/DX/Device.cpp @@ -141,6 +141,66 @@ getDXPrimitiveTopology(PrimitiveTopology Topology, llvm_unreachable("All PrimitiveTopology cases handled"); } +static D3D12_FILTER getDXFilterMode(FilterMode MinFilter, FilterMode MagFilter, + bool IsComparison) { + if (IsComparison) { + if (MinFilter == FilterMode::Nearest) + return MagFilter == FilterMode::Nearest + ? D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT + : D3D12_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT; + + return MagFilter == FilterMode::Nearest + ? D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT + : D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT; + } + if (MinFilter == FilterMode::Nearest) + return MagFilter == FilterMode::Nearest + ? D3D12_FILTER_MIN_MAG_MIP_POINT + : D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; + + return MagFilter == FilterMode::Nearest + ? D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT + : D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; +} + +static D3D12_TEXTURE_ADDRESS_MODE getDXTextureAddressMode(AddressMode Mode) { + switch (Mode) { + case AddressMode::Clamp: + return D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + case AddressMode::Repeat: + return D3D12_TEXTURE_ADDRESS_MODE_WRAP; + case AddressMode::Mirror: + return D3D12_TEXTURE_ADDRESS_MODE_MIRROR; + case AddressMode::Border: + return D3D12_TEXTURE_ADDRESS_MODE_BORDER; + case AddressMode::MirrorOnce: + return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; + } + llvm_unreachable("All cases handled."); +} + +static D3D12_COMPARISON_FUNC getDXComparisonFunc(CompareFunction ComparisonOp) { + switch (ComparisonOp) { + case CompareFunction::Never: + return D3D12_COMPARISON_FUNC_NEVER; + case CompareFunction::Less: + return D3D12_COMPARISON_FUNC_LESS; + case CompareFunction::Equal: + return D3D12_COMPARISON_FUNC_EQUAL; + case CompareFunction::LessEqual: + return D3D12_COMPARISON_FUNC_LESS_EQUAL; + case CompareFunction::Greater: + return D3D12_COMPARISON_FUNC_GREATER; + case CompareFunction::NotEqual: + return D3D12_COMPARISON_FUNC_NOT_EQUAL; + case CompareFunction::GreaterEqual: + return D3D12_COMPARISON_FUNC_GREATER_EQUAL; + case CompareFunction::Always: + return D3D12_COMPARISON_FUNC_ALWAYS; + } + llvm_unreachable("All cases handled."); +} + namespace { class DXDevice; @@ -243,10 +303,47 @@ class DXTexture : public offloadtest::Texture { } }; +class DXSampler : public offloadtest::Sampler { +public: + D3D12_CPU_DESCRIPTOR_HANDLE Handle = {}; + std::string Name; + SamplerCreateDesc Desc; + + DXSampler(llvm::StringRef Name, SamplerCreateDesc Desc, + D3D12_CPU_DESCRIPTOR_HANDLE Handle) + : offloadtest::Sampler(GPUAPI::DirectX), Handle(Handle), Name(Name), + Desc(Desc) {} + + const SamplerCreateDesc &getDesc() const override { return Desc; } + + static bool classof(const offloadtest::Sampler *S) { + return S->getAPI() == GPUAPI::DirectX; + } +}; + +enum class RootParameterType : uint32_t { + DescriptorTable = 0, + SamplerTable, + Constant, + CBV, + SRV, + UAV, +}; + +struct RoogtSignatureLayout { + RootParameterType ParameterType : 3; + uint32_t Count : 29; + + RoogtSignatureLayout(RootParameterType ParameterType, uint32_t Count) + : ParameterType(ParameterType), Count(Count) {} + RoogtSignatureLayout() = delete; +}; + class DXPipelineState : public offloadtest::PipelineState { public: std::string Name; ComPtr RootSig; + llvm::SmallVector Layout; ComPtr PSO; // Only set for graphics pipelines. std::optional Topology; @@ -256,11 +353,13 @@ class DXPipelineState : public offloadtest::PipelineState { bool IsRayTracing = false; DXPipelineState(llvm::StringRef Name, ComPtr RootSig, + llvm::SmallVector Layout, ComPtr PSO, std::optional Topology, bool IsRT = false) : offloadtest::PipelineState(GPUAPI::DirectX), Name(Name), - RootSig(RootSig), PSO(PSO), Topology(Topology), IsRayTracing(IsRT) {} + RootSig(RootSig), Layout(std::move(Layout)), PSO(PSO), + Topology(Topology), IsRayTracing(IsRT) {} static bool classof(const offloadtest::PipelineState *B) { return B->getAPI() == GPUAPI::DirectX; @@ -279,9 +378,11 @@ class DXRayTracingPipelineState : public DXPipelineState { DXRayTracingPipelineState(llvm::StringRef Name, ComPtr RootSig, + llvm::SmallVector Layout, ComPtr SO, ComPtr Props) - : DXPipelineState(Name, RootSig, /*PSO=*/nullptr, std::nullopt, + : DXPipelineState(Name, RootSig, std::move(Layout), /*PSO=*/nullptr, + std::nullopt, /*IsRT=*/true), StateObject(SO), Properties(Props) {} @@ -1166,15 +1267,18 @@ class DXDevice : public offloadtest::Device { DescriptorAllocator RTVAllocator; DescriptorAllocator DSVAllocator; DescriptorAllocator CSUAllocator; + DescriptorAllocator SamplerAllocator; DXDevice(ComPtr A, ComPtr D, DXQueue Q, DescriptorAllocator RTVAllocator, DescriptorAllocator DSVAllocator, - DescriptorAllocator CSUAllocator, std::string Desc, + DescriptorAllocator CSUAllocator, + DescriptorAllocator SamplerAllocator, std::string Desc, std::string DriverVer) : Adapter(A), Device(D), GraphicsQueue(std::move(Q)), RTVAllocator(std::move(RTVAllocator)), DSVAllocator(std::move(DSVAllocator)), - CSUAllocator(std::move(CSUAllocator)) { + CSUAllocator(std::move(CSUAllocator)), + SamplerAllocator(std::move(SamplerAllocator)) { Description = std::move(Desc); DriverVersion = std::move(DriverVer); DriverName = "DirectX"; @@ -1216,9 +1320,10 @@ class DXDevice : public offloadtest::Device { Queue &getGraphicsQueue() override { return GraphicsQueue; } - llvm::Error - createRootSignatureFromShader(llvm::StringRef, const ShaderContainer &Shader, - ComPtr &OutRootSignature) { + llvm::Error createRootSignatureFromShader( + llvm::StringRef Name, const ShaderContainer &Shader, + ComPtr &OutRootSignature, + llvm::SmallVectorImpl &Layout) { // Try pulling a root signature from the DXIL first auto ExContainer = llvm::object::DXContainer::create(Shader.Shader->getMemBufferRef()); @@ -1238,14 +1343,71 @@ class DXDevice : public offloadtest::Device { IID_PPV_ARGS(&OutRootSignature)), "Failed to create root signature.")) return Err; + + const std::wstring WStr(Name.begin(), Name.end()); + OutRootSignature->SetName(WStr.c_str()); + + // Deserialize the root signature to determine how we need to bind + // descriptor tables + ComPtr Deserializer; + if (auto Err = HR::toError( + D3D12CreateVersionedRootSignatureDeserializer( + Binary.data(), Binary.size(), IID_PPV_ARGS(&Deserializer)), + "Failed to create Root Signature Deserializer")) + return Err; + + const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *RootSigDesc = nullptr; + if (auto Err = + HR::toError(Deserializer->GetRootSignatureDescAtVersion( + D3D_ROOT_SIGNATURE_VERSION_1, &RootSigDesc), + "Failed to deseralize root signature")) + return Err; + + for (uint32_t I = 0; I < RootSigDesc->Desc_1_0.NumParameters; ++I) { + const D3D12_ROOT_PARAMETER &Parameter = + RootSigDesc->Desc_1_0.pParameters[I]; + switch (Parameter.ParameterType) { + case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: { + uint32_t DescriptorCount = 0; + for (uint32_t I = 0; + I < Parameter.DescriptorTable.NumDescriptorRanges; ++I) + DescriptorCount += + Parameter.DescriptorTable.pDescriptorRanges[I].NumDescriptors; + + if (Parameter.DescriptorTable.NumDescriptorRanges > 0 && + Parameter.DescriptorTable.pDescriptorRanges[0].RangeType == + D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER) + Layout.push_back(RoogtSignatureLayout( + RootParameterType::SamplerTable, DescriptorCount)); + else + Layout.push_back(RoogtSignatureLayout( + RootParameterType::DescriptorTable, DescriptorCount)); + break; + } + case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: + Layout.push_back(RoogtSignatureLayout( + RootParameterType::Constant, Parameter.Constants.Num32BitValues)); + break; + case D3D12_ROOT_PARAMETER_TYPE_CBV: + Layout.push_back(RoogtSignatureLayout(RootParameterType::CBV, 1)); + break; + case D3D12_ROOT_PARAMETER_TYPE_SRV: + Layout.push_back(RoogtSignatureLayout(RootParameterType::SRV, 1)); + break; + case D3D12_ROOT_PARAMETER_TYPE_UAV: + Layout.push_back(RoogtSignatureLayout(RootParameterType::UAV, 1)); + break; + } + } } return llvm::Error::success(); } llvm::Error createRootSignatureFromBindingsDesc( - llvm::StringRef, const BindingsDesc &BndDesc, bool IsGraphics, - ComPtr &OutRootSignature) { + llvm::StringRef Name, const BindingsDesc &BndDesc, bool IsGraphics, + ComPtr &OutRootSignature, + llvm::SmallVectorImpl &Layout) { uint32_t DescriptorCount = 0; for (auto &D : BndDesc.DescriptorSetDescs) DescriptorCount += D.ResourceBindings.size(); @@ -1258,7 +1420,11 @@ class DXDevice : public offloadtest::Device { uint32_t DescriptorIdx = 0; const uint32_t StartRangeIdx = RangeIdx; for (const auto &Binding : Set.ResourceBindings) { - switch (getDescriptorKind(Binding.Kind)) { + const DescriptorKind Kind = getDescriptorKind(Binding.Kind); + if (Kind == DescriptorKind::SAMPLER) + continue; + + switch (Kind) { case DescriptorKind::SRV: Ranges.get()[RangeIdx].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; break; @@ -1269,7 +1435,8 @@ class DXDevice : public offloadtest::Device { Ranges.get()[RangeIdx].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; break; case DescriptorKind::SAMPLER: - llvm_unreachable("Not implemented yet."); // Requires a separate heap + llvm_unreachable("Sampler should have been filtered out."); + break; } Ranges.get()[RangeIdx].NumDescriptors = Binding.DescriptorCount; Ranges.get()[RangeIdx].BaseShaderRegister = Binding.DXBinding.Register; @@ -1279,12 +1446,49 @@ class DXDevice : public offloadtest::Device { RangeIdx++; DescriptorIdx += Binding.DescriptorCount; } - RootParams.push_back(D3D12_ROOT_PARAMETER{ - D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, - {D3D12_ROOT_DESCRIPTOR_TABLE{ - static_cast(Set.ResourceBindings.size()), - &Ranges.get()[StartRangeIdx]}}, - D3D12_SHADER_VISIBILITY_ALL}); + const uint32_t RangeCount = + static_cast(RangeIdx - StartRangeIdx); + if (RangeCount > 0) { + RootParams.push_back( + D3D12_ROOT_PARAMETER{D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, + {D3D12_ROOT_DESCRIPTOR_TABLE{ + RangeCount, &Ranges.get()[StartRangeIdx]}}, + D3D12_SHADER_VISIBILITY_ALL}); + Layout.push_back(RoogtSignatureLayout( + RootParameterType::DescriptorTable, DescriptorIdx)); + } + + uint32_t SamplerDescriptorIdx = 0; + const uint32_t SamplerStartRangeIdx = RangeIdx; + for (const auto &Binding : Set.ResourceBindings) { + const DescriptorKind Kind = getDescriptorKind(Binding.Kind); + if (Kind != DescriptorKind::SAMPLER) + continue; + + Ranges.get()[RangeIdx].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; + Ranges.get()[RangeIdx].NumDescriptors = Binding.DescriptorCount; + Ranges.get()[RangeIdx].BaseShaderRegister = Binding.DXBinding.Register; + Ranges.get()[RangeIdx].RegisterSpace = Binding.DXBinding.Space; + Ranges.get()[RangeIdx].OffsetInDescriptorsFromTableStart = + SamplerDescriptorIdx; + + assert(Binding.DescriptorCount == 1 && "Manon expected this to be 1."); + RangeIdx++; + SamplerDescriptorIdx += Binding.DescriptorCount; + } + + const uint32_t SamplerRangeCount = + static_cast(RangeIdx - SamplerStartRangeIdx); + if (SamplerRangeCount > 0) { + RootParams.push_back(D3D12_ROOT_PARAMETER{ + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, + {D3D12_ROOT_DESCRIPTOR_TABLE{ + static_cast(RangeIdx - SamplerStartRangeIdx), + &Ranges.get()[SamplerStartRangeIdx]}}, + D3D12_SHADER_VISIBILITY_ALL}); + Layout.push_back(RoogtSignatureLayout(RootParameterType::SamplerTable, + SamplerDescriptorIdx)); + } } CD3DX12_ROOT_SIGNATURE_DESC Desc; @@ -1315,32 +1519,37 @@ class DXDevice : public offloadtest::Device { "Failed to create root signature.")) return Err; + const std::wstring WStr(Name.begin(), Name.end()); + OutRootSignature->SetName(WStr.c_str()); + return llvm::Error::success(); } llvm::Error createRootSignature(llvm::StringRef Name, const BindingsDesc &BndDesc, const ShaderContainer &Shader, bool IsGraphics, - ComPtr &OutRootSignature) { + ComPtr &OutRootSignature, + llvm::SmallVectorImpl &Layout) { assert(OutRootSignature.Get() == nullptr); - if (auto Err = - createRootSignatureFromShader(Name, Shader, OutRootSignature)) + if (auto Err = createRootSignatureFromShader(Name, Shader, OutRootSignature, + Layout)) return Err; if (OutRootSignature.Get() != nullptr) return llvm::Error::success(); return createRootSignatureFromBindingsDesc(Name, BndDesc, IsGraphics, - OutRootSignature); + OutRootSignature, Layout); } llvm::Expected> createPipelineCs(llvm::StringRef Name, const BindingsDesc &BndDesc, ShaderContainer CS) override { ComPtr RootSig; + llvm::SmallVector Layout; if (auto Err = createRootSignature(Name, BndDesc, CS, - /*IsGraphics=*/false, RootSig)) + /*IsGraphics=*/false, RootSig, Layout)) return Err; auto DXIL = CS.Shader->getBuffer(); @@ -1360,7 +1569,8 @@ class DXDevice : public offloadtest::Device { "Failed to create PSO.")) return Err; - return std::make_unique(Name, RootSig, PSO, std::nullopt); + return std::make_unique(Name, RootSig, std::move(Layout), + PSO, std::nullopt); } llvm::Expected> @@ -1370,8 +1580,9 @@ class DXDevice : public offloadtest::Device { assert(Desc.RTFormats.size() <= 8); ComPtr RootSig; + llvm::SmallVector Layout; if (auto Err = createRootSignature(Name, BndDesc, Desc.VS, - /*IsGraphics=*/true, RootSig)) + /*IsGraphics=*/true, RootSig, Layout)) return Err; std::vector DXInputLayout; @@ -1435,7 +1646,7 @@ class DXDevice : public offloadtest::Device { return Err; return std::make_unique( - Name, RootSig, PSO, + Name, RootSig, std::move(Layout), PSO, getDXPrimitiveTopology(Desc.Topology, Desc.PatchControlPoints)); } @@ -1445,8 +1656,9 @@ class DXDevice : public offloadtest::Device { assert(Desc.RTFormats.size() <= 8); ComPtr RootSig; + llvm::SmallVector Layout; if (auto Err = createRootSignature(Name, BindingsDesc, Desc.MS, - /*IsGraphics=*/true, RootSig)) + /*IsGraphics=*/true, RootSig, Layout)) return Err; const D3D12_SHADER_BYTECODE MSBytecode = { @@ -1512,7 +1724,8 @@ class DXDevice : public offloadtest::Device { "Failed to create mesh shader PSO.")) return Err; - return std::make_unique(Name, RootSig, PSO, std::nullopt); + return std::make_unique(Name, RootSig, std::move(Layout), + PSO, std::nullopt); } static std::wstring widen(llvm::StringRef S) { @@ -1544,8 +1757,9 @@ class DXDevice : public offloadtest::Device { ShaderContainer LibContainer = {}; LibContainer.Shader = Desc.Library; ComPtr RootSig; + llvm::SmallVector Layout; if (auto Err = createRootSignature(Name, BndDesc, LibContainer, - /*IsGraphics=*/false, RootSig)) + /*IsGraphics=*/false, RootSig, Layout)) return Err; CD3DX12_STATE_OBJECT_DESC SODesc( @@ -1612,7 +1826,7 @@ class DXDevice : public offloadtest::Device { return Err; auto State = std::make_unique( - Name, RootSig, StateObject, Properties); + Name, RootSig, Layout, StateObject, Properties); // Cache identifiers up-front. The driver-owned blobs are alive for // Properties' lifetime, which lives on the PSO. // @@ -2044,6 +2258,42 @@ class DXDevice : public offloadtest::Device { return Tex; } + llvm::Expected> + createSampler(std::string Name, const SamplerCreateDesc &Desc) override { + + auto HandleOrErr = SamplerAllocator.allocate(); + if (!HandleOrErr) + return HandleOrErr.takeError(); + const D3D12_CPU_DESCRIPTOR_HANDLE Handle = *HandleOrErr; + + const D3D12_TEXTURE_ADDRESS_MODE AddressMode = + getDXTextureAddressMode(Desc.Address); + + bool IsComparison = false; + D3D12_COMPARISON_FUNC ComparisonFunc = D3D12_COMPARISON_FUNC_NONE; + if (Desc.Kind == SamplerKind::SamplerComparison) { + IsComparison = true; + ComparisonFunc = getDXComparisonFunc(Desc.ComparisonOp); + } + + const D3D12_SAMPLER_DESC SamplerDesc = { + getDXFilterMode(Desc.MinFilter, Desc.MagFilter, IsComparison), + AddressMode, // U + AddressMode, // V + AddressMode, // W + Desc.MipLODBias, + 0, // MaxAnisotropy + ComparisonFunc, + {0.0f, 0.0f, 0.0f, 0.0f}, // BorderColor + Desc.MinLOD, + Desc.MaxLOD, + }; + + Device->CreateSampler(&SamplerDesc, Handle); + + return std::make_unique(Name, Desc, Handle); + } + uint32_t getTextureUploadRowStrideInBytes( const TextureCreateDesc &Desc) const override { return getAlignedTexturePitch(Desc.Width, getFormatSizeInBytes(Desc.Fmt)); @@ -2114,11 +2364,16 @@ class DXDevice : public offloadtest::Device { if (!CSUHeapOrErr) return CSUHeapOrErr.takeError(); + auto SamplerHeapOrErr = DescriptorAllocator::create( + Device.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 256); + if (!SamplerHeapOrErr) + return SamplerHeapOrErr.takeError(); + return std::make_unique( Adapter, Device, std::move(*GraphicsQueueOrErr), std::move(*RTVHeapOrErr), std::move(*DSVHeapOrErr), - std::move(*CSUHeapOrErr), std::string(DescVec.data()), - std::move(DriverVer)); + std::move(*CSUHeapOrErr), std::move(*SamplerHeapOrErr), + std::string(DescVec.data()), std::move(DriverVer)); } const Capabilities &getCapabilities() override { @@ -2160,18 +2415,44 @@ class DXDevice : public offloadtest::Device { return llvm::Error::success(); } - llvm::Error createDescriptorHeap(Pipeline &P, - ComPtr &DescHeap) { + llvm::Error createDescriptorHeaps(Pipeline &P, + ComPtr &DescHeap, + ComPtr &SamplerHeap) { if (P.getDescriptorCount() == 0) return llvm::Error::success(); + + uint32_t DescriptorCount = 0; + uint32_t SamplerCount = 0; + for (auto &D : P.Sets) + for (auto &R : D.Resources) + if (R.isSampler()) + SamplerCount += 1; + else + DescriptorCount += R.getArraySize(); + + // prevent empty heaps + if (DescriptorCount == 0) + DescriptorCount = 1; + if (SamplerCount == 0) + SamplerCount = 1; + const D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = { - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - P.getDescriptorCountWithFlattenedArrays(), + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, DescriptorCount, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 0}; if (auto Err = HR::toError( Device->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&DescHeap)), "Failed to create descriptor heap.")) return Err; + + const D3D12_DESCRIPTOR_HEAP_DESC SamplerHeapDesc = { + D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, SamplerCount, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 0}; + if (auto Err = + HR::toError(Device->CreateDescriptorHeap( + &SamplerHeapDesc, IID_PPV_ARGS(&SamplerHeap)), + "Failed to create sampler descriptor heap.")) + return Err; + return llvm::Error::success(); } @@ -2331,15 +2612,26 @@ class DXDevice : public offloadtest::Device { } void buildDescriptorTables(llvm::ArrayRef DescTables, - const ComPtr &DescHeap) { + const ComPtr &DescHeap, + const ComPtr &SamplerHeap) { // Bind descriptors in descriptor tables. - if (!DescHeap) + if (!DescHeap && !SamplerHeap) return; + uint32_t HeapIndex = 0; + uint32_t SamplerHeapIndex = 0; + const D3D12_CPU_DESCRIPTOR_HANDLE HeapStart = DescHeap->GetCPUDescriptorHandleForHeapStart(); + const D3D12_CPU_DESCRIPTOR_HANDLE SamplerHeapStart = + SamplerHeap->GetCPUDescriptorHandleForHeapStart(); + const uint32_t DescHandleIncSize = Device->GetDescriptorHandleIncrementSize( D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + const uint32_t SamplerHandleIncSize = + Device->GetDescriptorHandleIncrementSize( + D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + for (auto &T : DescTables) { for (auto &R : T.Resources) { for (const auto &Set : R.second) { @@ -2388,6 +2680,9 @@ class DXDevice : public offloadtest::Device { const DXAccelerationStructure &AccelerationStructureDX = llvm::cast(*Set.AS); DescriptorHandle = AccelerationStructureDX.SRVHandle; + } else if (Set.Sampler != nullptr) { + const DXSampler &SamplerDX = llvm::cast(*Set.Sampler); + DescriptorHandle = SamplerDX.Handle; } else { llvm_unreachable("Resource was a texture nor buffer. Samplers " "are unsupported"); @@ -2395,10 +2690,20 @@ class DXDevice : public offloadtest::Device { assert(DescriptorHandle.ptr != 0 && "Somehow got a null descriptor :("); - Device->CopyDescriptorsSimple( - 1, {HeapStart.ptr + HeapIndex * DescHandleIncSize}, - DescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - HeapIndex += 1; + + if (Set.Sampler != nullptr) { + Device->CopyDescriptorsSimple( + 1, + {SamplerHeapStart.ptr + + SamplerHeapIndex * SamplerHandleIncSize}, + DescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + SamplerHeapIndex += 1; + } else { + Device->CopyDescriptorsSimple( + 1, {HeapStart.ptr + HeapIndex * DescHandleIncSize}, + DescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + HeapIndex += 1; + } } } } @@ -2406,14 +2711,16 @@ class DXDevice : public offloadtest::Device { llvm::Error createComputeCommands(Pipeline &P, SharedInvocationState &IS, - const ComPtr &DescHeap) { + const ComPtr &DescHeap, + const ComPtr &SamplerHeap) { const DXCommandBuffer &DXCB = llvm::cast(*IS.CB); - CD3DX12_GPU_DESCRIPTOR_HANDLE Handle; + CD3DX12_GPU_DESCRIPTOR_HANDLE Handle, SamplerHandle; if (DescHeap) { - ID3D12DescriptorHeap *const Heaps[] = {DescHeap.Get()}; - DXCB.CmdList->SetDescriptorHeaps(1, Heaps); + ID3D12DescriptorHeap *const Heaps[] = {DescHeap.Get(), SamplerHeap.Get()}; + DXCB.CmdList->SetDescriptorHeaps(2, Heaps); Handle = DescHeap->GetGPUDescriptorHandleForHeapStart(); + SamplerHandle = SamplerHeap->GetGPUDescriptorHandleForHeapStart(); } const DXPipelineState &DXPipeline = llvm::cast(*IS.Pipeline.get()); @@ -2421,6 +2728,8 @@ class DXDevice : public offloadtest::Device { const uint32_t Inc = Device->GetDescriptorHandleIncrementSize( D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + const uint32_t SamplerInc = Device->GetDescriptorHandleIncrementSize( + D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); if (P.Settings.DX.RootParams.size() > 0) { uint32_t ConstantOffset = 0u; @@ -2444,6 +2753,7 @@ class DXDevice : public offloadtest::Device { break; } case dx::RootParamKind::DescriptorTable: + // TODO(manon): Add support for descriptor tables containing samplers DXCB.CmdList->SetComputeRootDescriptorTable(RootParamIndex++, Handle); Handle.Offset(P.Sets[DescriptorTableIndex++].Resources.size(), Inc); break; @@ -2478,7 +2788,8 @@ class DXDevice : public offloadtest::Device { VirtualAddress); break; case DescriptorKind::SAMPLER: - llvm_unreachable("Not implemented yet."); + llvm_unreachable( + "Samplers cannot be written directly into the Root Signature."); } ++RootDescIt; break; @@ -2488,9 +2799,22 @@ class DXDevice : public offloadtest::Device { // If no explicit root parameters are provided, fall back to using the // descriptor set layout. This is to make it easier to write tests that // don't need complicated root signatures. - for (uint32_t Idx = 0u; Idx < P.Sets.size(); ++Idx) { - DXCB.CmdList->SetComputeRootDescriptorTable(Idx, Handle); - Handle.Offset(P.Sets[Idx].Resources.size(), Inc); + for (uint32_t I = 0, N = DXPipeline.Layout.size(); I < N; ++I) { + const auto &Layout = DXPipeline.Layout[I]; + switch (Layout.ParameterType) { + case RootParameterType::DescriptorTable: + DXCB.CmdList->SetComputeRootDescriptorTable(I, Handle); + Handle.Offset(Layout.Count, Inc); + break; + case RootParameterType::SamplerTable: + DXCB.CmdList->SetComputeRootDescriptorTable(I, SamplerHandle); + SamplerHandle.Offset(Layout.Count, SamplerInc); + break; + default: + return llvm::createStringError( + "Root Signatures that contain constants and inline descriptors " + "require custom RootParamters to be defined."); + } } } @@ -2537,17 +2861,43 @@ class DXDevice : public offloadtest::Device { llvm::Error createGraphicsCommands(Pipeline &P, SharedInvocationState &IS, - const ComPtr &DescHeap) { + const ComPtr &DescHeap, + const ComPtr &SamplerHeap) { const DXPipelineState &DXPipeline = llvm::cast(*IS.Pipeline.get()); const DXCommandBuffer &DXCB = llvm::cast(*IS.CB); - DXCB.CmdList->SetGraphicsRootSignature(DXPipeline.RootSig.Get()); + if (DescHeap) { - ID3D12DescriptorHeap *const Heaps[] = {DescHeap.Get()}; - DXCB.CmdList->SetDescriptorHeaps(1, Heaps); - DXCB.CmdList->SetGraphicsRootDescriptorTable( - 0, DescHeap->GetGPUDescriptorHandleForHeapStart()); + ID3D12DescriptorHeap *const Heaps[] = {DescHeap.Get(), SamplerHeap.Get()}; + DXCB.CmdList->SetDescriptorHeaps(2, Heaps); + CD3DX12_GPU_DESCRIPTOR_HANDLE Handle( + DescHeap->GetGPUDescriptorHandleForHeapStart()); + CD3DX12_GPU_DESCRIPTOR_HANDLE SamplerHandle( + SamplerHeap->GetGPUDescriptorHandleForHeapStart()); + + const uint32_t Inc = Device->GetDescriptorHandleIncrementSize( + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + const uint32_t SamplerInc = Device->GetDescriptorHandleIncrementSize( + D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + + for (uint32_t I = 0, N = DXPipeline.Layout.size(); I < N; ++I) { + const auto &Layout = DXPipeline.Layout[I]; + switch (Layout.ParameterType) { + case RootParameterType::DescriptorTable: + DXCB.CmdList->SetGraphicsRootDescriptorTable(I, Handle); + Handle.Offset(Layout.Count, Inc); + break; + case RootParameterType::SamplerTable: + DXCB.CmdList->SetGraphicsRootDescriptorTable(I, SamplerHandle); + SamplerHandle.Offset(Layout.Count, SamplerInc); + break; + default: + return llvm::createStringError( + "Root Signatures that contain constants and inline descriptors " + "require custom RootParamters to be defined."); + } + } } RenderPassBeginDesc BeginDesc = {}; @@ -2617,8 +2967,8 @@ class DXDevice : public offloadtest::Device { llvm::Error executeProgram(Pipeline &P) override { llvm::outs() << "Configuring execution on device: " << Description << "\n"; - ComPtr DescHeap; - if (auto Err = createDescriptorHeap(P, DescHeap)) + ComPtr DescHeap, SamplerHeap; + if (auto Err = createDescriptorHeaps(P, DescHeap, SamplerHeap)) return Err; llvm::outs() << "Descriptor heap created.\n"; @@ -2633,7 +2983,7 @@ class DXDevice : public offloadtest::Device { return Err; llvm::outs() << "Buffers created.\n"; - buildDescriptorTables(State.DescTables, DescHeap); + buildDescriptorTables(State.DescTables, DescHeap, SamplerHeap); if (!P.AccelStructs.BLAS.empty() || !P.AccelStructs.TLAS.empty()) { auto EncOrErr = State.CB->createComputeEncoder(); @@ -2680,7 +3030,7 @@ class DXDevice : public offloadtest::Device { return PipelineStateOrErr.takeError(); State.Pipeline = std::move(*PipelineStateOrErr); llvm::outs() << "Compute Pipeline created.\n"; - if (auto Err = createComputeCommands(P, State, DescHeap)) + if (auto Err = createComputeCommands(P, State, DescHeap, SamplerHeap)) return Err; llvm::outs() << "Compute command list created.\n"; @@ -2786,7 +3136,7 @@ class DXDevice : public offloadtest::Device { llvm::outs() << "Mesh Shader Pipeline created.\n"; } - if (auto Err = createGraphicsCommands(P, State, DescHeap)) + if (auto Err = createGraphicsCommands(P, State, DescHeap, SamplerHeap)) return Err; llvm::outs() << "Graphics command list created complete.\n"; } else if (P.isRayTracing()) { @@ -2817,7 +3167,7 @@ class DXDevice : public offloadtest::Device { State.SBT = std::move(*SBTOrErr); llvm::outs() << "Shader Binding Table created.\n"; - if (auto Err = createComputeCommands(P, State, DescHeap)) + if (auto Err = createComputeCommands(P, State, DescHeap, SamplerHeap)) return Err; llvm::outs() << "RayTracing command list created.\n"; } else { diff --git a/lib/API/Device.cpp b/lib/API/Device.cpp index 33260a6cf..59cb10345 100644 --- a/lib/API/Device.cpp +++ b/lib/API/Device.cpp @@ -36,6 +36,8 @@ Queue::~Queue() {} Texture::~Texture() {} +Sampler::~Sampler() {} + MemoryHeap::~MemoryHeap() {} RenderPass::~RenderPass() {} diff --git a/lib/API/MTL/MTLDevice.cpp b/lib/API/MTL/MTLDevice.cpp index bf3554bb2..28003749a 100644 --- a/lib/API/MTL/MTLDevice.cpp +++ b/lib/API/MTL/MTLDevice.cpp @@ -498,6 +498,17 @@ class MTLTexture : public offloadtest::Texture { } }; +class MTLSampler : public offloadtest::Sampler { +public: + SamplerCreateDesc Desc; + + const SamplerCreateDesc &getDesc() const override { return Desc; } + + static bool classof(const offloadtest::Sampler *S) { + return S->getAPI() == GPUAPI::Metal; + } +}; + /// Metal has no standalone render-pass object: render pass info lives on /// MTLRenderPassDescriptor and is consumed when a render command encoder /// is created. We therefore just stash the descriptor for the encoder to @@ -2397,6 +2408,11 @@ class MTLDevice : public offloadtest::Device { return std::make_unique(Tex, Name, Desc); } + llvm::Expected> + createSampler(std::string, const SamplerCreateDesc &) override { + return llvm::createStringError("createSampler is unimplemented on Metal."); + } + uint32_t getTextureUploadRowStrideInBytes( const TextureCreateDesc &Desc) const override { return Desc.Width * getFormatSizeInBytes(Desc.Fmt); diff --git a/lib/API/VK/Device.cpp b/lib/API/VK/Device.cpp index 5e5f5c9f7..bd2ef3507 100644 --- a/lib/API/VK/Device.cpp +++ b/lib/API/VK/Device.cpp @@ -570,6 +570,17 @@ class VulkanTexture : public offloadtest::Texture { } }; +class VulkanSampler : public offloadtest::Sampler { +public: + SamplerCreateDesc Desc; + + const SamplerCreateDesc &getDesc() const override { return Desc; } + + static bool classof(const offloadtest::Sampler *S) { + return S->getAPI() == GPUAPI::Vulkan; + } +}; + class VulkanAccelerationStructure : public offloadtest::AccelerationStructure { public: VkDevice Dev; @@ -2920,6 +2931,11 @@ class VulkanDevice : public offloadtest::Device { return Tex; } + llvm::Expected> + createSampler(std::string, const SamplerCreateDesc &) override { + return llvm::createStringError("createSampler is unimplemented on Vulkan."); + } + uint32_t getTextureUploadRowStrideInBytes( const TextureCreateDesc &Desc) const override { const uint64_t TightRow = @@ -3446,7 +3462,7 @@ class VulkanDevice : public offloadtest::Device { llvm::Expected createSampler(Resource &R, BufferRef &Host) { VkSamplerCreateInfo SamplerInfo = {}; SamplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - const Sampler &S = *R.SamplerPtr; + const YAMLSampler &S = *R.SamplerPtr; SamplerInfo.magFilter = getVKFilter(S.MagFilter); SamplerInfo.minFilter = getVKFilter(S.MinFilter); SamplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; diff --git a/lib/Support/OffloadMigration.cpp b/lib/Support/OffloadMigration.cpp index 008009d80..c7f29e003 100644 --- a/lib/Support/OffloadMigration.cpp +++ b/lib/Support/OffloadMigration.cpp @@ -324,9 +324,23 @@ llvm::Error createResources(Device &Dev, Pipeline &P, IS.TLASes.try_emplace(R.TLASPtr->Name, std::move(*ASOrErr)); assert(Inserted.second && "TLAS bound to multiple resources NYI"); (void)Inserted; + } else if (R.isSampler()) { + const SamplerCreateDesc Desc = { + R.SamplerPtr->MinFilter, R.SamplerPtr->MagFilter, + R.SamplerPtr->Address, R.SamplerPtr->MinLOD, + R.SamplerPtr->MaxLOD, R.SamplerPtr->MipLODBias, + R.SamplerPtr->ComparisonOp, R.SamplerPtr->Kind, + }; + + auto SamplerOrErr = Dev.createSampler(R.SamplerPtr->Name, Desc); + if (!SamplerOrErr) + return SamplerOrErr.takeError(); + + ResourceSet RSet(std::move(*SamplerOrErr)); + ResBundle.push_back(std::move(RSet)); } else { return llvm::createStringError(std::errc::not_supported, - "Samplers are not yet implemented."); + "Unrecognized resource type."); } Resources.push_back(std::make_pair(&R, std::move(ResBundle))); diff --git a/lib/Support/OffloadMigration.h b/lib/Support/OffloadMigration.h index 0fba65e4a..ef56c0d6c 100644 --- a/lib/Support/OffloadMigration.h +++ b/lib/Support/OffloadMigration.h @@ -36,6 +36,7 @@ struct ResourceSet { std::unique_ptr BackingMemory; std::unique_ptr Buffer; std::unique_ptr Texture; + std::unique_ptr Sampler; std::unique_ptr Readback; std::unique_ptr CounterReadback; @@ -54,6 +55,8 @@ struct ResourceSet { std::unique_ptr Readback) : BackingMemory(std::move(BackingMemory)), Texture(std::move(Texture)), Readback(std::move(Readback)) {} + ResourceSet(std::unique_ptr Sampler) + : Sampler(std::move(Sampler)) {} explicit ResourceSet(AccelerationStructure *AS) : AS(AS) {} ResourceSet(const ResourceSet &) = delete; @@ -61,12 +64,14 @@ struct ResourceSet { ResourceSet(ResourceSet &&A) : BackingMemory(std::move(A.BackingMemory)), Buffer(std::move(A.Buffer)), - Texture(std::move(A.Texture)), Readback(std::move(A.Readback)), + Texture(std::move(A.Texture)), Sampler(std::move(A.Sampler)), + Readback(std::move(A.Readback)), CounterReadback(std::move(A.CounterReadback)), AS(A.AS) {} ResourceSet &operator=(ResourceSet &&A) { BackingMemory = std::move(A.BackingMemory); Buffer = std::move(A.Buffer); Texture = std::move(A.Texture); + Sampler = std::move(A.Sampler); Readback = std::move(A.Readback); CounterReadback = std::move(A.CounterReadback); AS = A.AS; diff --git a/lib/Support/Pipeline.cpp b/lib/Support/Pipeline.cpp index 41fa3f7d6..19552cc47 100644 --- a/lib/Support/Pipeline.cpp +++ b/lib/Support/Pipeline.cpp @@ -331,8 +331,8 @@ static void setCounters(IO &I, offloadtest::CPUBuffer &B) { } } -void MappingTraits::mapping(IO &I, - offloadtest::Sampler &S) { +void MappingTraits::mapping( + IO &I, offloadtest::YAMLSampler &S) { I.mapRequired("Name", S.Name); I.mapOptional("Kind", S.Kind); I.mapOptional("MinFilter", S.MinFilter); diff --git a/test/Feature/Textures/Texture2D.Gather.test.yaml b/test/Feature/Textures/Texture2D.Gather.test.yaml index 538471766..7bf8bf2c2 100644 --- a/test/Feature/Textures/Texture2D.Gather.test.yaml +++ b/test/Feature/Textures/Texture2D.Gather.test.yaml @@ -117,8 +117,8 @@ Results: ... #--- end -# Unimplemented: Clang + DX: https://github.com/llvm/llvm-project/issues/101558 -# XFAIL: DirectX || Metal +# Unimplemented: Clang: https://github.com/llvm/llvm-project/issues/101558 +# XFAIL: Metal # RUN: split-file %s %t # RUN: %dxc_target -T cs_6_0 -Fo %t.o %t/source.hlsl diff --git a/test/Feature/Textures/Texture2D.GatherCmp.test.yaml b/test/Feature/Textures/Texture2D.GatherCmp.test.yaml index 9a950a6c8..ffd15395f 100644 --- a/test/Feature/Textures/Texture2D.GatherCmp.test.yaml +++ b/test/Feature/Textures/Texture2D.GatherCmp.test.yaml @@ -138,8 +138,8 @@ Results: ... #--- end -# Unimplemented: Clang + DX: https://github.com/llvm/llvm-project/issues/101558 -# XFAIL: DirectX || Metal +# Unimplemented: Clang: https://github.com/llvm/llvm-project/issues/101558 +# XFAIL: Metal # RUN: split-file %s %t # RUN: %dxc_target -T cs_6_0 -Fo %t.o %t/source.hlsl diff --git a/test/Feature/Textures/Texture2D.SampleCmp.test.yaml b/test/Feature/Textures/Texture2D.SampleCmp.test.yaml index 52a06c512..2efcb2b56 100644 --- a/test/Feature/Textures/Texture2D.SampleCmp.test.yaml +++ b/test/Feature/Textures/Texture2D.SampleCmp.test.yaml @@ -193,7 +193,7 @@ Results: #--- end # Unimplemented: https://github.com/llvm/offload-test-suite/issues/664 -# XFAIL: DirectX || Metal || Vulkan && Darwin +# XFAIL: Metal || Vulkan && Darwin # RUN: split-file %s %t # RUN: %dxc_target -T vs_6_0 -E mainVS -Fo %t-vs.o %t/vertex.hlsl diff --git a/test/Feature/Textures/Texture2D.Sampler.address.test.yaml b/test/Feature/Textures/Texture2D.Sampler.address.test.yaml index 844b8f5e7..ec67a3d5d 100644 --- a/test/Feature/Textures/Texture2D.Sampler.address.test.yaml +++ b/test/Feature/Textures/Texture2D.Sampler.address.test.yaml @@ -160,7 +160,7 @@ Results: #--- end # Unimplemented: https://github.com/llvm/offload-test-suite/issues/664 -# XFAIL: DirectX || Metal +# XFAIL: Metal # RUN: split-file %s %t # RUN: %dxc_target -T vs_6_0 -E mainVS -Fo %t-vs.o %t/vertex.hlsl diff --git a/test/Feature/Textures/Texture2D.Sampler.filter.test.yaml b/test/Feature/Textures/Texture2D.Sampler.filter.test.yaml index 5dfd8255b..b7b1ed5a3 100644 --- a/test/Feature/Textures/Texture2D.Sampler.filter.test.yaml +++ b/test/Feature/Textures/Texture2D.Sampler.filter.test.yaml @@ -131,7 +131,7 @@ Results: #--- end # Unimplemented: https://github.com/llvm/offload-test-suite/issues/664 -# XFAIL: DirectX || Metal +# XFAIL: Metal # RUN: split-file %s %t # RUN: %dxc_target -T vs_6_0 -E mainVS -Fo %t-vs.o %t/vertex.hlsl