summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/cuda-target.md2
-rw-r--r--prelude/slang-cpp-types.h414
-rw-r--r--source/slang/core.meta.slang7
-rw-r--r--tests/compute/texture-get-dimensions.slang106
-rw-r--r--tests/compute/texture-get-dimensions.slang.expected.txt8
-rw-r--r--tests/diagnostics/bad-operator-call.slang.expected76
-rw-r--r--tools/render-test/cpu-compute-util.cpp103
7 files changed, 650 insertions, 66 deletions
diff --git a/docs/cuda-target.md b/docs/cuda-target.md
index f79bf14c3..c41858bd4 100644
--- a/docs/cuda-target.md
+++ b/docs/cuda-target.md
@@ -219,6 +219,8 @@ Some features are not available because they cannot be mapped with appropriate b
* Not all Wave intrinsics are supported
* There is not complete support for all methods on 'objects' like textures etc.
* Does not currently support combined 'TextureSampler'. A Texture behaves equivalently to a TextureSampler and Samplers are ignored.
+* Half type is not currently supported
+* GetDimensions is not available on any Texture type currently - as there doesn't appear to be a CUDA equivalent
Language aspects
================
diff --git a/prelude/slang-cpp-types.h b/prelude/slang-cpp-types.h
index c7421bc0b..415d7f941 100644
--- a/prelude/slang-cpp-types.h
+++ b/prelude/slang-cpp-types.h
@@ -226,10 +226,116 @@ struct SamplerComparisonState
ISamplerComparisonState* state;
};
+//
+struct TextureDimensions
+{
+ void reset()
+ {
+ shape = 0;
+ width = height = depth = 0;
+ numberOfLevels = 0;
+ arrayElementCount = 0;
+ }
+ int getDimSizes(uint32_t outDims[4]) const
+ {
+ const auto baseShape = (shape & SLANG_RESOURCE_BASE_SHAPE_MASK);
+ int count = 0;
+ switch (baseShape)
+ {
+ case SLANG_TEXTURE_1D:
+ {
+ outDims[count++] = width;
+ break;
+ }
+ case SLANG_TEXTURE_2D:
+ {
+ outDims[count++] = width;
+ outDims[count++] = height;
+ break;
+ }
+ case SLANG_TEXTURE_3D:
+ {
+ outDims[count++] = width;
+ outDims[count++] = height;
+ outDims[count++] = depth;
+ break;
+ }
+ case SLANG_TEXTURE_CUBE:
+ {
+ outDims[count++] = width;
+ outDims[count++] = height;
+ outDims[count++] = 6;
+ break;
+ }
+ }
+
+ if (shape & SLANG_TEXTURE_ARRAY_FLAG)
+ {
+ outDims[count++] = arrayElementCount;
+ }
+ return count;
+ }
+ int getMIPDims(int outDims[3]) const
+ {
+ const auto baseShape = (shape & SLANG_RESOURCE_BASE_SHAPE_MASK);
+ int count = 0;
+ switch (baseShape)
+ {
+ case SLANG_TEXTURE_1D:
+ {
+ outDims[count++] = width;
+ break;
+ }
+ case SLANG_TEXTURE_CUBE:
+ case SLANG_TEXTURE_2D:
+ {
+ outDims[count++] = width;
+ outDims[count++] = height;
+ break;
+ }
+ case SLANG_TEXTURE_3D:
+ {
+ outDims[count++] = width;
+ outDims[count++] = height;
+ outDims[count++] = depth;
+ break;
+ }
+ }
+ return count;
+ }
+ int calcMaxMIPLevels() const
+ {
+ int dims[3];
+ const int dimCount = getMIPDims(dims);
+ for (int count = 1; true; count++)
+ {
+ bool allOne = true;
+ for (int i = 0; i < dimCount; ++i)
+ {
+ if (dims[i] > 1)
+ {
+ allOne = false;
+ dims[i] >>= 1;
+ }
+ }
+ if (allOne)
+ {
+ return count;
+ }
+ }
+ }
+
+ SlangResourceShape shape;
+ uint32_t width, height, depth;
+ uint32_t numberOfLevels;
+ uint32_t arrayElementCount; ///< For array types, 0 otherwise
+};
+
// Texture
struct ITexture
{
+ virtual TextureDimensions GetDimensions(int mipLevel = -1) = 0;
virtual void Load(const int* v, void* out) = 0;
virtual void Sample(SamplerState samplerState, const float* loc, void* out) = 0;
virtual void SampleLevel(SamplerState samplerState, const float* loc, float level, void* out) = 0;
@@ -238,6 +344,22 @@ struct ITexture
template <typename T>
struct Texture1D
{
+ void GetDimensions(uint32_t& outWidth) { outWidth = texture->GetDimensions().width; }
+ void GetDimensions(uint32_t mipLevel, uint32_t& outWidth, uint32_t& outNumberOfLevels)
+ {
+ auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outNumberOfLevels = dims.numberOfLevels;
+ }
+
+ void GetDimensions(float& outWidth) { outWidth = texture->GetDimensions().width; }
+ void GetDimensions(uint32_t mipLevel, float& outWidth, float& outNumberOfLevels)
+ {
+ auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outNumberOfLevels = dims.numberOfLevels;
+ }
+
T Load(const int2& loc) const { T out; texture->Load(&loc.x, &out); return out; }
T Sample(SamplerState samplerState, float loc) const { T out; texture->Sample(samplerState, &loc, &out); return out; }
T SampleLevel(SamplerState samplerState, float loc, float level) { T out; texture->SampleLevel(samplerState, &loc, level, &out); return out; }
@@ -248,6 +370,33 @@ struct Texture1D
template <typename T>
struct Texture2D
{
+ 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;
+ }
+
T Load(const int3& loc) const { T out; texture->Load(&loc.x, &out); return out; }
T Sample(SamplerState samplerState, const float2& loc) const { T out; texture->Sample(samplerState, &loc.x, &out); return out; }
T SampleLevel(SamplerState samplerState, const float2& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out); return out; }
@@ -258,6 +407,37 @@ struct Texture2D
template <typename T>
struct Texture3D
{
+ void GetDimensions(uint32_t& outWidth, uint32_t& outHeight, uint32_t& outDepth)
+ {
+ const auto dims = texture->GetDimensions();
+ outWidth = dims.width;
+ outHeight = dims.height;
+ outDepth = dims.depth;
+ }
+ void GetDimensions(uint32_t mipLevel, uint32_t& outWidth, uint32_t& outHeight, uint32_t& outDepth, uint32_t& outNumberOfLevels)
+ {
+ const auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outHeight = dims.height;
+ outDepth = dims.depth;
+ outNumberOfLevels = dims.numberOfLevels;
+ }
+ void GetDimensions(float& outWidth, float& outHeight, float& outDepth)
+ {
+ const auto dims = texture->GetDimensions();
+ outWidth = dims.width;
+ outHeight = dims.height;
+ outDepth = dims.depth;
+ }
+ void GetDimensions(uint32_t mipLevel, float& outWidth, float& outHeight, float& outDepth, float& outNumberOfLevels)
+ {
+ const auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outHeight = dims.height;
+ outDepth = dims.depth;
+ outNumberOfLevels = dims.numberOfLevels;
+ }
+
T Load(const int4& loc) const { T out; texture->Load(&loc.x, &out); return out; }
T Sample(SamplerState samplerState, const float3& loc) const { T out; texture->Sample(samplerState, &loc.x, &out); return out; }
T SampleLevel(SamplerState samplerState, const float3& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out); return out; }
@@ -268,6 +448,33 @@ struct Texture3D
template <typename T>
struct TextureCube
{
+ 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;
+ }
+
T Sample(SamplerState samplerState, const float3& loc) const { T out; texture->Sample(samplerState, &loc.x, &out); return out; }
T SampleLevel(SamplerState samplerState, const float3& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out); return out; }
@@ -277,6 +484,23 @@ struct TextureCube
template <typename T>
struct Texture1DArray
{
+ void GetDimensions(uint32_t& outWidth, uint32_t& outElements) { auto dims = texture->GetDimensions(); outWidth = dims.width; outElements = dims.arrayElementCount; }
+ void GetDimensions(uint32_t mipLevel, uint32_t& outWidth, uint32_t& outElements, uint32_t& outNumberOfLevels)
+ {
+ auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outNumberOfLevels = dims.numberOfLevels;
+ outElements = dims.arrayElementCount;
+ }
+ void GetDimensions(float& outWidth, float& outElements) { auto dims = texture->GetDimensions(); outWidth = dims.width; outElements = dims.arrayElementCount; }
+ void GetDimensions(uint32_t mipLevel, float& outWidth, float& outElements, float& outNumberOfLevels)
+ {
+ auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outNumberOfLevels = dims.numberOfLevels;
+ outElements = dims.arrayElementCount;
+ }
+
T Load(const int3& loc) const { T out; texture->Load(&loc.x, &out); return out; }
T Sample(SamplerState samplerState, const float2& loc) const { T out; texture->Sample(samplerState, &loc.x, &out); return out; }
T SampleLevel(SamplerState samplerState, const float2& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out); return out; }
@@ -287,6 +511,38 @@ struct Texture1DArray
template <typename T>
struct Texture2DArray
{
+ 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)
+ {
+ auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outHeight = dims.height;
+ outElements = dims.arrayElementCount;
+ outNumberOfLevels = dims.numberOfLevels;
+ }
+
+ void GetDimensions(uint32_t& 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)
+ {
+ auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outHeight = dims.height;
+ outElements = dims.arrayElementCount;
+ outNumberOfLevels = dims.numberOfLevels;
+ }
+
T Load(const int4& loc) const { T out; texture->Load(&loc.x, &out); return out; }
T Sample(SamplerState samplerState, const float3& loc) const { T out; texture->Sample(samplerState, &loc.x, &out); return out; }
T SampleLevel(SamplerState samplerState, const float3& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out); return out; }
@@ -297,6 +553,38 @@ struct Texture2DArray
template <typename T>
struct TextureCubeArray
{
+ 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)
+ {
+ auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outHeight = dims.height;
+ outElements = dims.arrayElementCount;
+ outNumberOfLevels = dims.numberOfLevels;
+ }
+
+ void GetDimensions(uint32_t& 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)
+ {
+ auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outHeight = dims.height;
+ outElements = dims.arrayElementCount;
+ outNumberOfLevels = dims.numberOfLevels;
+ }
+
T Sample(SamplerState samplerState, const float4& loc) const { T out; texture->Sample(samplerState, &loc.x, &out); return out; }
T SampleLevel(SamplerState samplerState, const float4& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out); return out; }
@@ -307,6 +595,8 @@ struct TextureCubeArray
struct IRWTexture
{
+ virtual TextureDimensions GetDimensions(int mipLevel = -1) = 0;
+
/// Load at specified location.
virtual void Load(const int32_t* loc, void* out) = 0;
/// Get the reference to the element at loc.
@@ -316,6 +606,12 @@ struct IRWTexture
template <typename T>
struct RWTexture1D
{
+ void GetDimensions(uint32_t& outWidth) { outWidth = texture->GetDimensions().width; }
+ void GetDimensions(uint32_t mipLevel, uint32_t& outWidth, uint32_t& outNumberOfLevels) { auto dims = texture->GetDimensions(mipLevel); outWidth = dims.width; outNumberOfLevels = dims.numberOfLevels; }
+
+ void GetDimensions(float& outWidth) { outWidth = texture->GetDimensions().width; }
+ void GetDimensions(uint32_t mipLevel, float& outWidth, float& outNumberOfLevels) { auto dims = texture->GetDimensions(mipLevel); outWidth = dims.width; outNumberOfLevels = dims.numberOfLevels; }
+
T Load(int32_t loc) const { T out; texture->Load(&loc, &out); return out; }
T& operator[](uint32_t loc) { return *(T*)texture->refAt(&loc); }
IRWTexture* texture;
@@ -324,6 +620,33 @@ struct RWTexture1D
template <typename T>
struct RWTexture2D
{
+ 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;
+ }
+
T Load(const int2& loc) const { T out; texture->Load(&loc.x, &out); return out; }
T& operator[](const uint2& loc) { return *(T*)texture->refAt(&loc.x); }
IRWTexture* texture;
@@ -332,14 +655,73 @@ struct RWTexture2D
template <typename T>
struct RWTexture3D
{
+ void GetDimensions(uint32_t& outWidth, uint32_t& outHeight, uint32_t& outDepth)
+ {
+ const auto dims = texture->GetDimensions();
+ outWidth = dims.width;
+ outHeight = dims.height;
+ outDepth = dims.depth;
+ }
+ void GetDimensions(uint32_t mipLevel, uint32_t& outWidth, uint32_t& outHeight, uint32_t& outDepth, uint32_t& outNumberOfLevels)
+ {
+ const auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outHeight = dims.height;
+ outDepth = dims.depth;
+ outNumberOfLevels = dims.numberOfLevels;
+ }
+ void GetDimensions(float& outWidth, float& outHeight, float& outDepth)
+ {
+ const auto dims = texture->GetDimensions();
+ outWidth = dims.width;
+ outHeight = dims.height;
+ outDepth = dims.depth;
+ }
+ void GetDimensions(uint32_t mipLevel, float& outWidth, float& outHeight, float& outDepth, float& outNumberOfLevels)
+ {
+ const auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outHeight = dims.height;
+ outDepth = dims.depth;
+ outNumberOfLevels = dims.numberOfLevels;
+ }
+
T Load(const int3& loc) const { T out; texture->Load(&loc.x, &out); return out; }
T& operator[](const uint3& loc) { return *(T*)texture->refAt(&loc.x); }
IRWTexture* texture;
};
+
template <typename T>
struct RWTexture1DArray
{
+ void GetDimensions(uint32_t& outWidth, uint32_t& outElements)
+ {
+ auto dims = texture->GetDimensions();
+ outWidth = dims.width;
+ outElements = dims.arrayElementCount;
+ }
+ void GetDimensions(uint32_t mipLevel, uint32_t& outWidth, uint32_t& outElements, uint32_t& outNumberOfLevels)
+ {
+ const auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outElements = dims.arrayElementCount;
+ outNumberOfLevels = dims.numberOfLevels;
+ }
+ void GetDimensions(float& outWidth, float& outElements)
+ {
+ auto dims = texture->GetDimensions();
+ outWidth = dims.width;
+ outElements = dims.arrayElementCount;
+ }
+ void GetDimensions(uint32_t mipLevel, float& outWidth, float& outElements, float& outNumberOfLevels)
+ {
+ const auto dims = texture->GetDimensions(mipLevel);
+ outWidth = dims.width;
+ outElements = dims.arrayElementCount;
+ outNumberOfLevels = dims.numberOfLevels;
+ }
+
T Load(int2 loc) const { T out; texture->Load(&loc.x, &out); return out; }
T& operator[](uint2 loc) { return *(T*)texture->refAt(&loc.x); }
IRWTexture* texture;
@@ -348,12 +730,42 @@ struct RWTexture1DArray
template <typename T>
struct RWTexture2DArray
{
+ 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;
+ }
+
T Load(const int3& loc) const { T out; texture->Load(&loc.x, &out); return out; }
T& operator[](const uint3& loc) { return *(T*)texture->refAt(&loc.x); }
IRWTexture* texture;
};
-
/* Varying input for Compute */
/* Used when running a single thread */
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 6c1163adc..2b43206a3 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -707,7 +707,12 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
switch(baseShape)
{
case TextureFlavor::Shape::Shape1D:
- sb << "($" << aa++ << opStr << "))";
+ sb << "($" << aa++ << opStr << ")";
+ if (isArray)
+ {
+ sb << ".x";
+ }
+ sb << ")";
cc = 1;
break;
diff --git a/tests/compute/texture-get-dimensions.slang b/tests/compute/texture-get-dimensions.slang
new file mode 100644
index 000000000..67c1fddc8
--- /dev/null
+++ b/tests/compute/texture-get-dimensions.slang
@@ -0,0 +1,106 @@
+//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute
+//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute
+//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12
+//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 -profile cs_6_0 -use-dxil
+// TODO(JS): Doesn't work on vk currently, because createTextureView not implemented on vk renderer
+//DISABLE_TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute
+// TODO(JS): Doesn't work on CUDA as there aren't any CUDA functions to get dimensions.
+//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-cuda -compute
+
+//TEST_INPUT: Texture1D(size=4, content = one):name t1D
+Texture1D<float> t1D;
+//TEST_INPUT: Texture2D(size=8, content = one):name t2D
+Texture2D<float> t2D;
+//TEST_INPUT: Texture3D(size=2, content = one):name t3D
+Texture3D<float> t3D;
+//TEST_INPUT: TextureCube(size=16, content = one):name tCube
+TextureCube<float> tCube;
+
+//TEST_INPUT: Texture1D(size=2, content = one, arrayLength=2):name t1DArray
+Texture1DArray<float> t1DArray;
+//TEST_INPUT: Texture2D(size=4, content = one, arrayLength=3):name t2DArray
+Texture2DArray<float> t2DArray;
+//TEST_INPUT: TextureCube(size=16, content = one, arrayLength=1):name tCubeArray
+TextureCubeArray<float> tCubeArray;
+
+//TEST_INPUT: Sampler:name samplerState
+SamplerState samplerState;
+
+//TEST_INPUT: ubuffer(data=[0 0 0 0 0 0 0 0], stride=4):out,name outputBuffer
+RWStructuredBuffer<float> outputBuffer;
+
+[numthreads(8, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ int idx = dispatchThreadID.x;
+
+ uint mipWidth = 0;
+ uint mipHeight = 0;
+ uint mipDepth = 0;
+ uint mipCount = 1;
+ uint elementCount = 0;
+
+ uint width = 0;
+ uint height = 0;
+ uint depth = 0;
+
+ switch (idx)
+ {
+ case 0:
+ {
+ t1D.GetDimensions(width);
+ t1D.GetDimensions(0, mipWidth, mipCount);
+ break;
+ }
+ case 1:
+ {
+ t2D.GetDimensions(width, height);
+ t2D.GetDimensions(0, mipWidth, mipHeight, mipCount);
+ break;
+ }
+ case 2:
+ {
+ t3D.GetDimensions(width, height, depth);
+ t3D.GetDimensions(0, mipWidth, mipHeight, mipDepth, mipCount);
+ break;
+ }
+ case 3:
+ {
+ tCube.GetDimensions(width, height);
+ tCube.GetDimensions(0, mipWidth, mipHeight, mipCount);
+ break;
+ }
+ case 4:
+ {
+ t1DArray.GetDimensions(width, elementCount);
+ t1DArray.GetDimensions(0, mipWidth, elementCount, mipCount);
+ break;
+ }
+ case 5:
+ {
+ t2DArray.GetDimensions(width, height, elementCount);
+ t2DArray.GetDimensions(0, mipWidth, mipHeight, elementCount, mipCount);
+ break;
+ }
+ case 6:
+ {
+ tCubeArray.GetDimensions(width, height, elementCount);
+ tCubeArray.GetDimensions(0, mipWidth, mipHeight, elementCount, mipCount);
+ break;
+ }
+ }
+
+ width = (mipWidth != width) ? ~0 : width;
+ height = (mipHeight != height) ? ~0 : height;
+ depth = (mipDepth != depth) ? ~0 : depth;
+
+ // Only depth or element count can be set
+ if (depth == 0 && elementCount > 0)
+ {
+ depth = elementCount;
+ }
+
+ uint val = ((0xff & width) << 24) | ((0xff & height) << 16) | ((0xff & depth) << 8) | (mipCount);
+
+ outputBuffer[idx] = val;
+}
diff --git a/tests/compute/texture-get-dimensions.slang.expected.txt b/tests/compute/texture-get-dimensions.slang.expected.txt
new file mode 100644
index 000000000..3b060b4ae
--- /dev/null
+++ b/tests/compute/texture-get-dimensions.slang.expected.txt
@@ -0,0 +1,8 @@
+4C800000
+4D008000
+4C008080
+4D808000
+4C000080
+4C808060
+4D808008
+3F800000
diff --git a/tests/diagnostics/bad-operator-call.slang.expected b/tests/diagnostics/bad-operator-call.slang.expected
index f41fdf7c0..fd85fdbfc 100644
--- a/tests/diagnostics/bad-operator-call.slang.expected
+++ b/tests/diagnostics/bad-operator-call.slang.expected
@@ -1,51 +1,51 @@
result code = -1
standard error = {
tests/diagnostics/bad-operator-call.slang(17): error 39999: no overload for '+=' applicable to arguments of type (int, S)
-core.meta.slang(1756): note 39999: candidate: func +=<T, R:int, C:int>(matrix<T,R,C>, T) -> matrix<T,R,C>
-core.meta.slang(1748): note 39999: candidate: func +=<T, R:int, C:int>(matrix<T,R,C>, matrix<T,R,C>) -> matrix<T,R,C>
-core.meta.slang(1740): note 39999: candidate: func +=<T, N:int>(vector<T,N>, T) -> vector<T,N>
-core.meta.slang(1732): note 39999: candidate: func +=<T, N:int>(vector<T,N>, vector<T,N>) -> vector<T,N>
-core.meta.slang(1724): note 39999: candidate: func +=<T>(T, T) -> T
+core.meta.slang(1745): note 39999: candidate: func +=<T, R:int, C:int>(matrix<T,R,C>, T) -> matrix<T,R,C>
+core.meta.slang(1737): note 39999: candidate: func +=<T, R:int, C:int>(matrix<T,R,C>, matrix<T,R,C>) -> matrix<T,R,C>
+core.meta.slang(1729): note 39999: candidate: func +=<T, N:int>(vector<T,N>, T) -> vector<T,N>
+core.meta.slang(1721): note 39999: candidate: func +=<T, N:int>(vector<T,N>, vector<T,N>) -> vector<T,N>
+core.meta.slang(1713): note 39999: candidate: func +=<T>(T, T) -> T
tests/diagnostics/bad-operator-call.slang(19): error 39999: no overload for '+' applicable to arguments of type (int, S)
-core.meta.slang(1646): note 39999: candidate: func +(uint64_t, uint64_t) -> uint64_t
-core.meta.slang(1639): note 39999: candidate: func +(uint, uint) -> uint
-core.meta.slang(1632): note 39999: candidate: func +(uint16_t, uint16_t) -> uint16_t
-core.meta.slang(1625): note 39999: candidate: func +(uint8_t, uint8_t) -> uint8_t
-core.meta.slang(1618): note 39999: candidate: func +(double, double) -> double
-core.meta.slang(1611): note 39999: candidate: func +(float, float) -> float
-core.meta.slang(1604): note 39999: candidate: func +(half, half) -> half
-core.meta.slang(1597): note 39999: candidate: func +(int64_t, int64_t) -> int64_t
-core.meta.slang(1590): note 39999: candidate: func +(int, int) -> int
-core.meta.slang(1583): note 39999: candidate: func +(int16_t, int16_t) -> int16_t
+core.meta.slang(1635): note 39999: candidate: func +(uint64_t, uint64_t) -> uint64_t
+core.meta.slang(1628): note 39999: candidate: func +(uint, uint) -> uint
+core.meta.slang(1621): note 39999: candidate: func +(uint16_t, uint16_t) -> uint16_t
+core.meta.slang(1614): note 39999: candidate: func +(uint8_t, uint8_t) -> uint8_t
+core.meta.slang(1607): note 39999: candidate: func +(double, double) -> double
+core.meta.slang(1600): note 39999: candidate: func +(float, float) -> float
+core.meta.slang(1593): note 39999: candidate: func +(half, half) -> half
+core.meta.slang(1586): note 39999: candidate: func +(int64_t, int64_t) -> int64_t
+core.meta.slang(1579): note 39999: candidate: func +(int, int) -> int
+core.meta.slang(1572): note 39999: candidate: func +(int16_t, int16_t) -> int16_t
tests/diagnostics/bad-operator-call.slang(19): note 39999: 1 more overload candidates
tests/diagnostics/bad-operator-call.slang(21): error 39999: no overload for '~' applicable to arguments of type (S)
-slang-stdlib.cpp(1638): note 39999: candidate: func ~(uint64_t) -> uint64_t
-slang-stdlib.cpp(1635): note 39999: candidate: func ~(uint) -> uint
-slang-stdlib.cpp(1632): note 39999: candidate: func ~(uint16_t) -> uint16_t
-slang-stdlib.cpp(1629): note 39999: candidate: func ~(uint8_t) -> uint8_t
-slang-stdlib.cpp(1626): note 39999: candidate: func ~(int64_t) -> int64_t
-slang-stdlib.cpp(1623): note 39999: candidate: func ~(int) -> int
-slang-stdlib.cpp(1620): note 39999: candidate: func ~(int16_t) -> int16_t
-slang-stdlib.cpp(1617): note 39999: candidate: func ~(int8_t) -> int8_t
+slang-stdlib.cpp(1646): note 39999: candidate: func ~(uint64_t) -> uint64_t
+slang-stdlib.cpp(1643): note 39999: candidate: func ~(uint) -> uint
+slang-stdlib.cpp(1640): note 39999: candidate: func ~(uint16_t) -> uint16_t
+slang-stdlib.cpp(1637): note 39999: candidate: func ~(uint8_t) -> uint8_t
+slang-stdlib.cpp(1634): note 39999: candidate: func ~(int64_t) -> int64_t
+slang-stdlib.cpp(1631): note 39999: candidate: func ~(int) -> int
+slang-stdlib.cpp(1628): note 39999: candidate: func ~(int16_t) -> int16_t
+slang-stdlib.cpp(1625): note 39999: candidate: func ~(int8_t) -> int8_t
tests/diagnostics/bad-operator-call.slang(26): error 30047: argument passed to parameter '0' must be l-value.
tests/diagnostics/bad-operator-call.slang(26): note 30048: argument was implicitly cast from 'int' to 'vector<int,4>', and Slang does not support using an implicit cast as an l-value
tests/diagnostics/bad-operator-call.slang(30): error 39999: no overload for '+=' applicable to arguments of type (vector<float,3>, vector<int,4>)
-core.meta.slang(1756): note 39999: candidate: func +=<T, R:int, C:int>(matrix<T,R,C>, T) -> matrix<T,R,C>
-core.meta.slang(1748): note 39999: candidate: func +=<T, R:int, C:int>(matrix<T,R,C>, matrix<T,R,C>) -> matrix<T,R,C>
-core.meta.slang(1740): note 39999: candidate: func +=<T, N:int>(vector<T,N>, T) -> vector<T,N>
-core.meta.slang(1732): note 39999: candidate: func +=<T, N:int>(vector<T,N>, vector<T,N>) -> vector<T,N>
-core.meta.slang(1724): note 39999: candidate: func +=<T>(T, T) -> T
+core.meta.slang(1745): note 39999: candidate: func +=<T, R:int, C:int>(matrix<T,R,C>, T) -> matrix<T,R,C>
+core.meta.slang(1737): note 39999: candidate: func +=<T, R:int, C:int>(matrix<T,R,C>, matrix<T,R,C>) -> matrix<T,R,C>
+core.meta.slang(1729): note 39999: candidate: func +=<T, N:int>(vector<T,N>, T) -> vector<T,N>
+core.meta.slang(1721): note 39999: candidate: func +=<T, N:int>(vector<T,N>, vector<T,N>) -> vector<T,N>
+core.meta.slang(1713): note 39999: candidate: func +=<T>(T, T) -> T
tests/diagnostics/bad-operator-call.slang(32): error 39999: no overload for '+' applicable to arguments of type (vector<int,4>, vector<float,3>)
-core.meta.slang(1651): note 39999: candidate: func +<4>(vector<uint64_t,4>, uint64_t) -> vector<uint64_t,4>
-core.meta.slang(1649): note 39999: candidate: func +<3>(uint64_t, vector<uint64_t,3>) -> vector<uint64_t,3>
-core.meta.slang(1646): note 39999: candidate: func +(uint64_t, uint64_t) -> uint64_t
-core.meta.slang(1644): note 39999: candidate: func +<4>(vector<uint,4>, uint) -> vector<uint,4>
-core.meta.slang(1642): note 39999: candidate: func +<3>(uint, vector<uint,3>) -> vector<uint,3>
-core.meta.slang(1639): note 39999: candidate: func +(uint, uint) -> uint
-core.meta.slang(1637): note 39999: candidate: func +<4>(vector<uint16_t,4>, uint16_t) -> vector<uint16_t,4>
-core.meta.slang(1635): note 39999: candidate: func +<3>(uint16_t, vector<uint16_t,3>) -> vector<uint16_t,3>
-core.meta.slang(1632): note 39999: candidate: func +(uint16_t, uint16_t) -> uint16_t
-core.meta.slang(1630): note 39999: candidate: func +<4>(vector<uint8_t,4>, uint8_t) -> vector<uint8_t,4>
+core.meta.slang(1640): note 39999: candidate: func +<4>(vector<uint64_t,4>, uint64_t) -> vector<uint64_t,4>
+core.meta.slang(1638): note 39999: candidate: func +<3>(uint64_t, vector<uint64_t,3>) -> vector<uint64_t,3>
+core.meta.slang(1635): note 39999: candidate: func +(uint64_t, uint64_t) -> uint64_t
+core.meta.slang(1633): note 39999: candidate: func +<4>(vector<uint,4>, uint) -> vector<uint,4>
+core.meta.slang(1631): note 39999: candidate: func +<3>(uint, vector<uint,3>) -> vector<uint,3>
+core.meta.slang(1628): note 39999: candidate: func +(uint, uint) -> uint
+core.meta.slang(1626): note 39999: candidate: func +<4>(vector<uint16_t,4>, uint16_t) -> vector<uint16_t,4>
+core.meta.slang(1624): note 39999: candidate: func +<3>(uint16_t, vector<uint16_t,3>) -> vector<uint16_t,3>
+core.meta.slang(1621): note 39999: candidate: func +(uint16_t, uint16_t) -> uint16_t
+core.meta.slang(1619): note 39999: candidate: func +<4>(vector<uint8_t,4>, uint8_t) -> vector<uint8_t,4>
tests/diagnostics/bad-operator-call.slang(32): note 39999: 23 more overload candidates
}
standard output = {
diff --git a/tools/render-test/cpu-compute-util.cpp b/tools/render-test/cpu-compute-util.cpp
index ea3927621..2ea74052f 100644
--- a/tools/render-test/cpu-compute-util.cpp
+++ b/tools/render-test/cpu-compute-util.cpp
@@ -15,10 +15,41 @@
namespace renderer_test {
using namespace Slang;
+static void _fixMipSize(uint32_t& ioDim, int mipLevel)
+{
+ uint32_t dim = ioDim;
+ if (dim > 0)
+ {
+ dim >>= mipLevel;
+ dim = (dim == 0) ? 1 : dim;
+ ioDim = dim;
+ }
+}
+
+CPPPrelude::TextureDimensions _calcMipDims(int mipLevel, const CPPPrelude::TextureDimensions& inDims)
+{
+ if (mipLevel > 0 && mipLevel < int(inDims.numberOfLevels))
+ {
+ CPPPrelude::TextureDimensions dims(inDims);
+ _fixMipSize(dims.width, mipLevel);
+ _fixMipSize(dims.height, mipLevel);
+ _fixMipSize(dims.depth, mipLevel);
+ return dims;
+ }
+ else
+ {
+ return inDims;
+ }
+}
+
template <int COUNT>
struct ValueTexture : public CPUComputeUtil::Resource, public CPPPrelude::ITexture
{
// ITexture interface
+ virtual CPPPrelude::TextureDimensions GetDimensions(int mipLevel) SLANG_OVERRIDE
+ {
+ return _calcMipDims(mipLevel, m_dims);
+ }
virtual void Load(const int32_t* loc, void* out) SLANG_OVERRIDE
{
_set(out);
@@ -32,8 +63,9 @@ struct ValueTexture : public CPUComputeUtil::Resource, public CPPPrelude::ITextu
_set(out);
}
- ValueTexture(float value) :
- m_value(value)
+ ValueTexture(const CPPPrelude::TextureDimensions& dims, float value) :
+ m_value(value),
+ m_dims(dims)
{
m_interface = static_cast<CPPPrelude::ITexture*>(this);
}
@@ -48,6 +80,7 @@ struct ValueTexture : public CPUComputeUtil::Resource, public CPPPrelude::ITextu
}
float m_value;
+ CPPPrelude::TextureDimensions m_dims;
};
class FloatTextureData
@@ -162,27 +195,40 @@ public:
struct FloatRWTexture : public CPUComputeUtil::Resource, public CPPPrelude::IRWTexture
{
// IRWTexture
+ virtual CPPPrelude::TextureDimensions GetDimensions(int mipLevel) SLANG_OVERRIDE
+ {
+ return _calcMipDims(mipLevel, m_dims);
+ }
virtual void Load(const int32_t* loc, void* out) SLANG_OVERRIDE { m_data.getAt((const uint32_t*)loc, (float*)out); }
virtual void* refAt(const uint32_t* loc) SLANG_OVERRIDE { return m_data.getAt(loc); }
- FloatRWTexture(int elementCount, int dimsCount, const uint32_t* dims, float initialValue)
+ FloatRWTexture(int elementCount, const CPPPrelude::TextureDimensions& inDims, float initialValue):
+ m_dims(inDims)
{
- m_data.init(elementCount, dimsCount, dims);
+ uint32_t dimSizes[4];
+ int dimSizesCount = inDims.getDimSizes(dimSizes);
+
+ m_data.init(elementCount, dimSizesCount, dimSizes);
m_data.setValue(initialValue);
m_interface = static_cast<CPPPrelude::IRWTexture*>(this);
}
FloatTextureData m_data;
+ CPPPrelude::TextureDimensions m_dims;
};
-static int _calcDims(const InputTextureDesc& desc, slang::TypeLayoutReflection* typeLayout, uint32_t outDims[4])
+static int _calcDims(const InputTextureDesc& desc, slang::TypeLayoutReflection* typeLayout, CPPPrelude::TextureDimensions& outDims)
{
+ outDims.reset();
+
const auto kind = typeLayout->getKind();
SLANG_ASSERT(kind == slang::TypeReflection::Kind::Resource);
auto type = typeLayout->getType();
auto shape = type->getResourceShape();
+ outDims.shape = shape;
+
const uint32_t size = uint32_t(desc.size);
const auto baseShape = (shape & SLANG_RESOURCE_BASE_SHAPE_MASK);
@@ -192,48 +238,52 @@ static int _calcDims(const InputTextureDesc& desc, slang::TypeLayoutReflection*
{
case SLANG_TEXTURE_1D:
{
- outDims[dimsCount++] = size;
+ outDims.width = size;
break;
}
case SLANG_TEXTURE_2D:
{
- outDims[dimsCount++] = size;
- outDims[dimsCount++] = size;
+ outDims.width = size;
+ outDims.height = size;
break;
}
case SLANG_TEXTURE_3D:
{
- outDims[dimsCount++] = size;
- outDims[dimsCount++] = size;
- outDims[dimsCount++] = size;
+ outDims.width = size;
+ outDims.height = size;
+ outDims.depth = size;
break;
}
case SLANG_TEXTURE_CUBE:
{
- outDims[dimsCount++] = size;
- outDims[dimsCount++] = size;
- outDims[dimsCount++] = 6;
+ outDims.width = size;
+ outDims.height = size;
break;
}
}
if (shape & SLANG_TEXTURE_ARRAY_FLAG)
{
- uint32_t arrayLength = uint32_t(desc.arrayLength);
- outDims[dimsCount++] = arrayLength;
+ outDims.arrayElementCount = uint32_t(desc.arrayLength);
}
+ int maxMipCount = outDims.calcMaxMIPLevels();
+ SLANG_ASSERT(desc.mipMapCount <= maxMipCount);
+
+ outDims.numberOfLevels = (desc.mipMapCount == 0) ? uint32_t(maxMipCount) : uint32_t(desc.mipMapCount);
+
return dimsCount;
}
-static CPUComputeUtil::Resource* _newReadTexture(int elemCount, SlangResourceShape shape, float initialValue)
+
+static CPUComputeUtil::Resource* _newReadTexture(int elemCount, const CPPPrelude::TextureDimensions& dims, float initialValue)
{
switch (elemCount)
{
- case 1: return new ValueTexture<1>(initialValue);
- case 2: return new ValueTexture<2>(initialValue);
- case 3: return new ValueTexture<3>(initialValue);
- case 4: return new ValueTexture<4>(initialValue);
+ case 1: return new ValueTexture<1>(dims, initialValue);
+ case 2: return new ValueTexture<2>(dims, initialValue);
+ case 3: return new ValueTexture<3>(dims, initialValue);
+ case 4: return new ValueTexture<4>(dims, initialValue);
default: break;
}
return nullptr;
@@ -270,12 +320,13 @@ static SlangResult _newTexture(const InputTextureDesc& desc, slang::TypeLayoutRe
default: break;
}
+ CPPPrelude::TextureDimensions dims;
+ _calcDims(desc, typeLayout, dims);
+
// These need a different style of texture if can be written to
if (access == SLANG_RESOURCE_ACCESS_READ_WRITE)
{
- uint32_t dims[4];
- const int dimsCount = _calcDims(desc, typeLayout, dims);
-
+
switch (shape)
{
case SLANG_TEXTURE_1D:
@@ -285,14 +336,14 @@ static SlangResult _newTexture(const InputTextureDesc& desc, slang::TypeLayoutRe
case SLANG_TEXTURE_1D_ARRAY:
case SLANG_TEXTURE_2D_ARRAY:
{
- outResource = new FloatRWTexture(elemCount, dimsCount, dims, initialValue);
+ outResource = new FloatRWTexture(elemCount, dims, initialValue);
return SLANG_OK;
}
}
}
else
{
- outResource = _newReadTexture(elemCount, shape, initialValue);
+ outResource = _newReadTexture(elemCount, dims, initialValue);
return outResource ? SLANG_OK : SLANG_FAIL;
}