summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2020-08-04 19:34:33 -0400
committerGitHub <noreply@github.com>2020-08-04 16:34:33 -0700
commit092337a67e7ef8ec108cab9cb6679e59bb2ff791 (patch)
tree9effc33e878c022f8b63bf883f68bb32aff26edc
parentde309d939199ec3fef1dacf23b502b7f209e37a1 (diff)
Sampler Feedback improvements (#1475)
* Add the Feedback texture types. Depreciate SLANG_RESOURCE_EXT_SHAPE_MASK. * Starting point to test sampler feedback. * WIP on FeedbackSampler. * Use __target_intrinsic to override the output of sampler feedback types. * Use newer generic syntax for FeedbackTexture. * Reflects Feedback type. * SLANG_TYPE_KIND_TEXTURE_FEEDBACK -> SLANG_TYPE_KIND_FEEDBACK * Added reflection test. * Reneable issue with generics in sampler-feedback-basic.slang * Add methods to FeedbackTexture2D/Array. Make test cover test cases. * Sampler feedback produces DXC code. * Disabled Sampler feedback test - as requires newer version of DXC. * Fix bug in reflection tool output. * Fix problem with direct-spirv-emit.slang.expected due to update to glslang. * Fix direct-spirv-emit.slang * Use SLANG_RESOURCE_EXT_SHAPE_MASK again * Make Feedback be emitted as a textue type prefix. * Add support for GetDimensions to FeedbackTexture2D * WIP on CPU sampler feedback. Update of target compatibility. * Fix some bugs in C++ feedback sampler. Fix GetDimensions for FeedbackTextures. Run 'Compile' test for CPU compute feedback texture test. Update target-compatability.md * Fix GetDimensions call on feedback sampler. * Small documentation improvements. Co-authored-by: Tim Foley <tfoleyNV@users.noreply.github.com>
-rw-r--r--docs/target-compatibility.md10
-rw-r--r--prelude/slang-cpp-types.h141
-rw-r--r--source/slang/hlsl.meta.slang21
-rw-r--r--tests/hlsl-intrinsic/sampler-feedback/compute-sampler-feedback.slang43
-rw-r--r--tests/hlsl-intrinsic/sampler-feedback/sampler-feedback-basic.slang5
5 files changed, 220 insertions, 0 deletions
diff --git a/docs/target-compatibility.md b/docs/target-compatibility.md
index 898a59fd3..e4c4a8496 100644
--- a/docs/target-compatibility.md
+++ b/docs/target-compatibility.md
@@ -39,6 +39,7 @@ Items with ^ means there is some discussion about support later in the document
| `[unroll]` | Yes | Yes | Yes ^ | Yes | Limited +
| Atomics | Yes | Yes | Yes | Yes | No +
| Atomics on RWBuffer | Yes | Yes | Yes | No | No +
+| Sampler Feedback | No | Yes | No + | No | Yes ^
## Half Type
@@ -169,3 +170,12 @@ For VK the GLSL output from Slang seems plausible, but VK binding fails in tests
On CUDA RWBuffer becomes CUsurfObject, which is a 'texture' type and does not support atomics.
On the CPU atomics are not supported, but will be in the future.
+
+## Sampler Feedback
+
+The HLSL [sampler feedback feature](https://microsoft.github.io/DirectX-Specs/d3d/SamplerFeedback.html) is available for DirectX12. The features requires shader model 6.5 and therefore a version of [DXC](https://github.com/Microsoft/DirectXShaderCompiler) that supports that model or higher. The Shader Model 6.5 requirement also means only DXIL binary format is supported.
+
+There doesn't not appear to be a similar feature available in Vulkan yet, but when it is available support should be addeed.
+
+For CPU targets there is the IFeedbackTexture interface that requires an implemention for use. Slang does not currently include CPU implementations for texture types.
+
diff --git a/prelude/slang-cpp-types.h b/prelude/slang-cpp-types.h
index 42af9fe61..fd5a9a813 100644
--- a/prelude/slang-cpp-types.h
+++ b/prelude/slang-cpp-types.h
@@ -377,6 +377,10 @@ struct TextureDimensions
uint32_t arrayElementCount; ///< For array types, 0 otherwise
};
+
+
+
+
// Texture
struct ITexture
@@ -814,6 +818,143 @@ struct RWTexture2DArray
IRWTexture* texture;
};
+// FeedbackTexture
+
+struct FeedbackType {};
+struct SAMPLER_FEEDBACK_MIN_MIP : FeedbackType {};
+struct SAMPLER_FEEDBACK_MIP_REGION_USED : FeedbackType {};
+
+struct IFeedbackTexture
+{
+ virtual TextureDimensions GetDimensions(int mipLevel = -1) = 0;
+
+ // Note here we pass the optional clamp parameter as a pointer. Passing nullptr means no clamp.
+ // This was preferred over having two function definitions, and having to differentiate their names
+ virtual void WriteSamplerFeedback(ITexture* tex, SamplerState samp, const float* location, const float* clamp = nullptr) = 0;
+ virtual void WriteSamplerFeedbackBias(ITexture* tex, SamplerState samp, const float* location, float bias, const float* clamp = nullptr) = 0;
+ virtual void WriteSamplerFeedbackGrad(ITexture* tex, SamplerState samp, const float* location, const float* ddx, const float* ddy, const float* clamp = nullptr) = 0;
+
+ virtual void WriteSamplerFeedbackLevel(ITexture* tex, SamplerState samp, const float* location, float lod) = 0;
+};
+
+template <typename T>
+struct FeedbackTexture2D
+{
+ void GetDimensions(uint32_t* outWidth, uint32_t* outHeight)
+ {
+ const auto dims = texture->GetDimensions();
+ *outWidth = dims.width;
+ *outHeight = dims.height;
+ }
+ void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outNumberOfLevels)
+ {
+ const auto dims = texture->GetDimensions(mipLevel);
+ *outWidth = dims.width;
+ *outHeight = dims.height;
+ *outNumberOfLevels = dims.numberOfLevels;
+ }
+ void GetDimensions(float* outWidth, float* outHeight)
+ {
+ const auto dims = texture->GetDimensions();
+ *outWidth = dims.width;
+ *outHeight = dims.height;
+ }
+ void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outNumberOfLevels)
+ {
+ const auto dims = texture->GetDimensions(mipLevel);
+ *outWidth = dims.width;
+ *outHeight = dims.height;
+ *outNumberOfLevels = dims.numberOfLevels;
+ }
+
+ template <typename S>
+ void WriteSamplerFeedback(Texture2D<S> tex, SamplerState samp, float2 location, float clamp) { texture->WriteSamplerFeedback(tex.texture, samp, &location.x, &clamp); }
+
+ template <typename S>
+ void WriteSamplerFeedbackBias(Texture2D<S> tex, SamplerState samp, float2 location, float bias, float clamp) { texture->WriteSamplerFeedbackBias(tex.texture, samp, &location.x, bias, &clamp); }
+
+ template <typename S>
+ void WriteSamplerFeedbackGrad(Texture2D<S> tex, SamplerState samp, float2 location, float2 ddx, float2 ddy, float clamp) { texture->WriteSamplerFeedbackGrad(tex.texture, samp, &location.x, &ddx.x, &ddy.x, &clamp); }
+
+ // Level
+
+ template <typename S>
+ void WriteSamplerFeedbackLevel(Texture2D<S> tex, SamplerState samp, float2 location, float lod) { texture->WriteSamplerFeedbackLevel(tex.texture, samp, &location.x, lod); }
+
+ // Without Clamp
+ template <typename S>
+ void WriteSamplerFeedback(Texture2D<S> tex, SamplerState samp, float2 location) { texture->WriteSamplerFeedback(tex.texture, samp, &location.x); }
+
+ template <typename S>
+ void WriteSamplerFeedbackBias(Texture2D<S> tex, SamplerState samp, float2 location, float bias) { texture->WriteSamplerFeedbackBias(tex.texture, samp, &location.x, bias); }
+
+ template <typename S>
+ void WriteSamplerFeedbackGrad(Texture2D<S> tex, SamplerState samp, float2 location, float2 ddx, float2 ddy) { texture->WriteSamplerFeedbackGrad(tex.texture, samp, &location.x, &ddx.x, &ddy.x); }
+
+ IFeedbackTexture* texture;
+};
+
+template <typename T>
+struct FeedbackTexture2DArray
+{
+ void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements)
+ {
+ auto dims = texture->GetDimensions();
+ *outWidth = dims.width;
+ *outHeight = dims.height;
+ *outElements = dims.arrayElementCount;
+ }
+ void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements, uint32_t* outNumberOfLevels)
+ {
+ const auto dims = texture->GetDimensions(mipLevel);
+ *outWidth = dims.width;
+ *outHeight = dims.height;
+ *outElements = dims.arrayElementCount;
+ *outNumberOfLevels = dims.numberOfLevels;
+ }
+ void GetDimensions(float* outWidth, float* outHeight, float* outElements)
+ {
+ auto dims = texture->GetDimensions();
+ *outWidth = dims.width;
+ *outHeight = dims.height;
+ *outElements = dims.arrayElementCount;
+ }
+ void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outElements, float* outNumberOfLevels)
+ {
+ const auto dims = texture->GetDimensions(mipLevel);
+ *outWidth = dims.width;
+ *outHeight = dims.height;
+ *outElements = dims.arrayElementCount;
+ *outNumberOfLevels = dims.numberOfLevels;
+ }
+
+ template <typename S>
+ void WriteSamplerFeedback(Texture2DArray<S> texArray, SamplerState samp, float3 location, float clamp) { texture->WriteSamplerFeedback(texArray.texture, samp, &location.x, &clamp); }
+
+ template <typename S>
+ void WriteSamplerFeedbackBias(Texture2DArray<S> texArray, SamplerState samp, float3 location, float bias, float clamp) { texture->WriteSamplerFeedbackBias(texArray.texture, samp, &location.x, bias, &clamp); }
+
+ template <typename S>
+ void WriteSamplerFeedbackGrad(Texture2DArray<S> texArray, SamplerState samp, float3 location, float3 ddx, float3 ddy, float clamp) { texture->WriteSamplerFeedbackGrad(texArray.texture, samp, &location.x, &ddx.x, &ddy.x, &clamp); }
+
+ // Level
+ template <typename S>
+ void WriteSamplerFeedbackLevel(Texture2DArray<S> texArray, SamplerState samp, float3 location, float lod) { texture->WriteSamplerFeedbackLevel(texArray.texture, samp, &location.x, lod); }
+
+ // Without Clamp
+
+ template <typename S>
+ void WriteSamplerFeedback(Texture2DArray<S> texArray, SamplerState samp, float3 location) { texture->WriteSamplerFeedback(texArray.texture, samp, &location.x); }
+
+ template <typename S>
+ void WriteSamplerFeedbackBias(Texture2DArray<S> texArray, SamplerState samp, float3 location, float bias) { texture->WriteSamplerFeedbackBias(texArray.texture, samp, &location.x, bias); }
+
+ template <typename S>
+ void WriteSamplerFeedbackGrad(Texture2DArray<S> texArray, SamplerState samp, float3 location, float3 ddx, float3 ddy) { texture->WriteSamplerFeedbackGrad(texArray.texture, samp, &location.x, &ddx.x, &ddy.x); }
+
+ IFeedbackTexture* texture;
+};
+
/* Varying input for Compute */
/* Used when running a single thread */
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
index b2748c50d..01fb17851 100644
--- a/source/slang/hlsl.meta.slang
+++ b/source/slang/hlsl.meta.slang
@@ -4024,6 +4024,18 @@ __magic_type(Texture, $(feedbackTexture2DFlavor))
__intrinsic_type($(kIROp_TextureType + (feedbackTexture2DFlavor << kIROpMeta_OtherShift)))
struct FeedbackTexture2D<T : __BuiltinSamplerFeedbackType>
{
+ __target_intrinsic(hlsl)
+ void GetDimensions(out uint width, out uint height);
+
+ __target_intrinsic(hlsl)
+ void GetDimensions(uint mipLevel, out uint width, out uint height, out uint numberOfLevels);
+
+ __target_intrinsic(hlsl)
+ void GetDimensions(out float width,out float height);
+
+ __target_intrinsic(hlsl)
+ void GetDimensions(uint mipLevel, out float width,out float height, out float numberOfLevels);
+
// With Clamp
__target_intrinsic(hlsl, "($0).WriteSamplerFeedback($1, $2, $3, $4)")
@@ -4058,6 +4070,15 @@ __magic_type(Texture, $(feedbackTexture2DArrayFlavor))
__intrinsic_type($(kIROp_TextureType + (feedbackTexture2DArrayFlavor << kIROpMeta_OtherShift)))
struct FeedbackTexture2DArray<T : __BuiltinSamplerFeedbackType>
{
+ __target_intrinsic(hlsl)
+ void GetDimensions(out uint width,out uint height, out uint elements);
+ __target_intrinsic(hlsl)
+ void GetDimensions(uint mipLevel, out uint width,out uint height, out uint elements, out uint numberOfLevels);
+ __target_intrinsic(hlsl)
+ void GetDimensions(out float width,out float height, out float elements);
+ __target_intrinsic(hlsl)
+ void GetDimensions(uint mipLevel, out float width,out float height, out float elements, out float numberOfLevels);
+
// With Clamp
__target_intrinsic(hlsl, "($0).WriteSamplerFeedback($1, $2, $3, $4)")
diff --git a/tests/hlsl-intrinsic/sampler-feedback/compute-sampler-feedback.slang b/tests/hlsl-intrinsic/sampler-feedback/compute-sampler-feedback.slang
new file mode 100644
index 000000000..c5fd93ca4
--- /dev/null
+++ b/tests/hlsl-intrinsic/sampler-feedback/compute-sampler-feedback.slang
@@ -0,0 +1,43 @@
+//TEST:COMPILE: -entry computeMain -stage compute -target dll tests/hlsl-intrinsic/sampler-feedback/compute-sampler-feedback.slang
+
+// Not available on non PS shader
+// dx.op.writeSamplerFeedback WriteSamplerFeedback
+// dx.op.writeSamplerFeedbackBias WriteSamplerFeedbackBias
+
+FeedbackTexture2D<SAMPLER_FEEDBACK_MIN_MIP> feedbackMinMip;
+FeedbackTexture2D<SAMPLER_FEEDBACK_MIP_REGION_USED> feedbackMipRegionUsed;
+FeedbackTexture2DArray<SAMPLER_FEEDBACK_MIN_MIP> feedbackMinMipArray;
+FeedbackTexture2DArray<SAMPLER_FEEDBACK_MIP_REGION_USED> feebackMipRegionUsedArray;
+
+Texture2D<float> tex2D;
+Texture2DArray<float> tex2DArray;
+SamplerState samp;
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ float2 coords2D = float2(1, 2) * dispatchThreadID.x;
+ float3 coords2DArray = float3(1, 2, 3) * dispatchThreadID.x;
+
+ float clamp = 4;
+ float bias = 0.5F;
+ float lod = 6;
+ float2 ddx = float2(1.0F / 32, 2.0F / 32);
+ float2 ddy = float2(3.0F / 32, 4.0F / 32);
+
+ uint width, height, elements, mipLevels;
+ feedbackMinMip.GetDimensions(width, height);
+ feedbackMinMipArray.GetDimensions(width, height, elements);
+
+ feedbackMinMip.GetDimensions(0, width, height, mipLevels);
+ feedbackMinMipArray.GetDimensions(0, width, height, elements, mipLevels);
+
+
+ feedbackMinMip.WriteSamplerFeedbackGrad(tex2D, samp, coords2D, ddx, ddy, clamp);
+
+ // Level
+ feedbackMinMip.WriteSamplerFeedbackLevel(tex2D, samp, coords2D, lod);
+
+ // No Clamp
+ feedbackMinMip.WriteSamplerFeedbackGrad(tex2D, samp, coords2D, ddx, ddy);
+}
diff --git a/tests/hlsl-intrinsic/sampler-feedback/sampler-feedback-basic.slang b/tests/hlsl-intrinsic/sampler-feedback/sampler-feedback-basic.slang
index 9e707b229..3b9497e5e 100644
--- a/tests/hlsl-intrinsic/sampler-feedback/sampler-feedback-basic.slang
+++ b/tests/hlsl-intrinsic/sampler-feedback/sampler-feedback-basic.slang
@@ -20,6 +20,11 @@ float4 main() : SV_Target
float lod = 6;
float2 ddx = float2(1.0F / 32, 2.0F / 32);
float2 ddy = float2(3.0F / 32, 4.0F / 32);
+
+ uint width, height, elements;
+ feedbackMinMip.GetDimensions(width, height);
+
+ feedbackMinMipArray.GetDimensions(width, height, elements);
// Clamped
feedbackMinMip.WriteSamplerFeedback(tex2D, samp, coords2D, clamp);