Skip to content

Commit

Permalink
Fix WGSL texture intrinsics
Browse files Browse the repository at this point in the history
This commit fixes a few issues with WGSL texture intrinsics.
 - static_assert-s are corrected.
 - Gather functions work properly with depth textures
 - Load functions work properly with depth textures
 - texture_storage_Xd is more properly emitted, although it is still not
   working fully.
  • Loading branch information
jkwak-work committed Sep 25, 2024
1 parent ef3552d commit 177f75d
Show file tree
Hide file tree
Showing 7 changed files with 923 additions and 107 deletions.
116 changes: 61 additions & 55 deletions source/slang/hlsl.meta.slang
Original file line number Diff line number Diff line change
Expand Up @@ -2229,6 +2229,22 @@ vector<TElement,4> __texture_gather(
result:$$vector<TElement,4> = OpImageGather %sampledImage $location $component;
};
case wgsl:
if (isShadow == 1)
{
// If depth texture, `textureGather` doesn't take channel value, `$3`.
if (isArray == 1)
{
switch (Shape.flavor)
{
case $(SLANG_TEXTURE_2D):
__intrinsic_asm "textureGather($0, $1, ($2).xy, u32(($2).z))";
case $(SLANG_TEXTURE_CUBE):
__intrinsic_asm "textureGather($0, $1, ($2).xyz, u32(($2).w))";
}
}
__intrinsic_asm "textureGather($0, $1, $2)";
}

if (isArray == 1)
{
switch (Shape.flavor)
Expand Down Expand Up @@ -2293,6 +2309,22 @@ vector<TElement,4> __texture_gather_offset(
result:$$vector<TElement,4> = OpImageGather %sampledImage $location $component ConstOffset $offset;
};
case wgsl:
if (isShadow == 1)
{
// If depth texture, `textureGather` doesn't take channel value, `$4`.
if (isArray == 1)
{
switch (Shape.flavor)
{
case $(SLANG_TEXTURE_2D):
__intrinsic_asm "textureGather($0, $1, ($2).xy, u32(($2).z), $3)";
case $(SLANG_TEXTURE_CUBE):
__intrinsic_asm "textureGather($0, $1, ($2).xyz, u32(($2).w), $3)";
}
}
__intrinsic_asm "textureGather($0, $1, $2, $3)";
}

if (isArray == 1)
{
switch (Shape.flavor)
Expand Down Expand Up @@ -2413,6 +2445,8 @@ vector<TElement,4> __texture_gatherCmp(
result:$$vector<TElement,4> = OpImageDrefGather %sampledImage $location $compareValue;
};
case wgsl:
static_assert(isShadow == 1, "WGSL supports textureGatherCompare only for depth textures.");

if (isArray == 1)
{
switch (Shape.flavor)
Expand Down Expand Up @@ -2477,6 +2511,8 @@ vector<TElement,4> __texture_gatherCmp_offset(
result:$$vector<TElement,4> = OpImageDrefGather %sampledImage $location $compareValue ConstOffset $offset;
};
case wgsl:
static_assert(isShadow == 1, "WGSL supports textureGatherCompare only for depth textures.");

if (isArray == 1)
{
switch (Shape.flavor)
Expand Down Expand Up @@ -2840,12 +2876,13 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,0,isShadow,isCombined,form
};
}
case wgsl:
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
, "WGSL supports only f32 type textures");
static_assert(Shape.flavor == $(SLANG_TEXTURE_1D)
|| Shape.flavor == $(SLANG_TEXTURE_2D)
|| Shape.flavor == $(SLANG_TEXTURE_3D)
, "WGSL supports textureLoad only for 1D, 2D and 3D textures");
, "WGSL doesn't supports textureLoad for Cube texture.");
static_assert(isArray == 0 || Shape.flavor == $(SLANG_TEXTURE_2D)
, "WGSL supports textureLoad for texture_2d_array but not for array of 1D, 3D or Cube.");

if (isArray == 1)
{
switch (Shape.flavor)
Expand All @@ -2870,7 +2907,7 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,0,isShadow,isCombined,form
__glsl_extension(GL_EXT_samplerless_texture_functions)
[__readNone]
[ForceInline]
[require(cpp_glsl_hlsl_spirv_wgsl, texture_sm_4_1_samplerless)]
[require(cpp_glsl_hlsl_spirv, texture_sm_4_1_samplerless)]
T Load(vector<int, Shape.dimensions+isArray+1> location, constexpr vector<int, Shape.planeDimensions> offset)
{
__target_switch
Expand Down Expand Up @@ -2901,22 +2938,6 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,0,isShadow,isCombined,form
__truncate $$T result __sampledType(T) %sampled;
};
}
case wgsl:
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
, "WGSL supports only f32 type textures");
if (isArray == 1)
{
switch (Shape.flavor)
{
case $(SLANG_TEXTURE_1D):
__intrinsic_asm "textureLoad($0, ($1).x, i32(($1).y), $2)$z";
case $(SLANG_TEXTURE_2D):
__intrinsic_asm "textureLoad($0, ($1).xy, i32(($1).z), $2)$z";
case $(SLANG_TEXTURE_CUBE):
__intrinsic_asm "textureLoad($0, ($1).xyz, i32(($1).w), $2)$z";
}
}
__intrinsic_asm "textureLoad($0, $1, $2)$z";
}
}

Expand Down Expand Up @@ -3044,20 +3065,11 @@ extension __TextureImpl<T,Shape,isArray,1,sampleCount,0,isShadow,isCombined,form
};
}
case wgsl:
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
, "WGSL supports only f32 type textures");
if (isArray == 1)
{
switch (Shape.flavor)
{
case $(SLANG_TEXTURE_1D):
__intrinsic_asm "textureLoad($0, ($1).x, i32(($1).y), $2)$z";
case $(SLANG_TEXTURE_2D):
__intrinsic_asm "textureLoad($0, ($1).xy, i32(($1).z), $2)$z";
case $(SLANG_TEXTURE_CUBE):
__intrinsic_asm "textureLoad($0, ($1).xyz, i32(($1).w), $2)$z";
}
}
static_assert(Shape.flavor == $(SLANG_TEXTURE_2D)
, "WGSL supports textureLoad for texture_multisampled_2d but not for multisampled of 1D, 3D or Cube.");
static_assert(isArray == 0
, "WGSL doesn't support array variants of multisampled textures for textureLoad.");

__intrinsic_asm "textureLoad($0, $1, $2)$z";
}
}
Expand Down Expand Up @@ -3282,18 +3294,21 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,$(access),isShadow, 0,form
static_assert(false, "Unsupported 'Load' of 'texture' for 'metal' target");
__intrinsic_asm "<invalid intrinsics>";
case wgsl:
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
, "WGSL supports only f32 type textures");
static_assert(Shape.flavor == $(SLANG_TEXTURE_1D)
|| Shape.flavor == $(SLANG_TEXTURE_2D)
|| Shape.flavor == $(SLANG_TEXTURE_3D)
, "WGSL doesn't supports textureLoad for Cube texture.");
static_assert(isArray == 0 || Shape.flavor == $(SLANG_TEXTURE_2D)
, "WGSL supports textureLoad for texture_storage_2d_array but not for array of 1D, 3D or Cube.");
static_assert(isShadow == 0 || T is float
, "WGSL supports only f32 depth textures");

if (isArray == 1)
{
switch (Shape.flavor)
{
case $(SLANG_TEXTURE_1D):
__intrinsic_asm "textureLoad($0, ($1).x, i32(($1).y))$z";
case $(SLANG_TEXTURE_2D):
__intrinsic_asm "textureLoad($0, ($1).xy, i32(($1).z))$z";
case $(SLANG_TEXTURE_CUBE):
__intrinsic_asm "textureLoad($0, ($1).xyz, i32(($1).w))$z";
}
}
__intrinsic_asm "textureLoad($0, $1)$z";
Expand Down Expand Up @@ -3540,21 +3555,12 @@ extension __TextureImpl<T,Shape,isArray,1,sampleCount,$(access),isShadow, 0,form
__truncate $$T result __sampledType(T) %sampled;
};
case wgsl:
static_assert(T is float || T is vector<float,2> || T is vector<float,3> || T is vector<float,4>
, "WGSL supports only f32 type textures");
if (isArray == 1)
{
switch (Shape.flavor)
{
case $(SLANG_TEXTURE_1D):
__intrinsic_asm "textureLoad($0, ($1).x, i32(($1).y))$z";
case $(SLANG_TEXTURE_2D):
__intrinsic_asm "textureLoad($0, ($1).xy, i32(($1).z))$z";
case $(SLANG_TEXTURE_CUBE):
__intrinsic_asm "textureLoad($0, ($1).xyz, i32(($1).w))$z";
}
}
__intrinsic_asm "textureLoad($0, $1)$z";
static_assert(Shape.flavor == $(SLANG_TEXTURE_2D)
, "WGSL supports textureLoad for texture_multisampled_2d but not for multisampled of 1D, 3D or Cube.");
static_assert(isArray == 0
, "WGSL doesn't support array variants of multisampled textures for textureLoad.");

__intrinsic_asm "textureLoad($0, $1, $2)$z";
}
}

Expand Down
46 changes: 42 additions & 4 deletions source/slang/slang-emit-wgsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,31 @@ void WGSLSourceEmitter::emit(const AddressSpace addressSpace)
}
}

static const char* getWgslImageFormat(IRTextureTypeBase* type)
{
ImageFormat imageFormat = type->hasFormat() ? (ImageFormat)type->getFormat() : ImageFormat::unknown;
switch (imageFormat)
{
case ImageFormat::rgba8: return "rgba8unorm";
case ImageFormat::rgba8_snorm: return "rgba8snorm";
case ImageFormat::rgba8ui: return "rgba8uint";
case ImageFormat::rgba8i: return "rgba8sint";
case ImageFormat::rgba16ui: return "rgba16uint";
case ImageFormat::rgba16i: return "rgba16sint";
case ImageFormat::rgba16f: return "rgba16float";
case ImageFormat::r32ui: return "r32uint";
case ImageFormat::r32i: return "r32sint";
case ImageFormat::r32f: return "r32float";
case ImageFormat::rg32ui: return "rg32uint";
case ImageFormat::rg32i: return "rg32sint";
case ImageFormat::rg32f: return "rg32float";
case ImageFormat::rgba32ui: return "rgba32uint";
case ImageFormat::rgba32i: return "rgba32sint";
case ImageFormat::rgba32f: return "rgba32float";
default: return "rgba8unorm";
}
}

void WGSLSourceEmitter::emitSimpleTypeImpl(IRType* type)
{
switch (type->getOp())
Expand Down Expand Up @@ -467,11 +492,24 @@ void WGSLSourceEmitter::emitSimpleTypeImpl(IRType* type)
if (!texType->isShadow())
{
m_writer->emit("<");

auto elemType = texType->getElementType();
if (auto vecElemType = as<IRVectorType>(elemType))
emitSimpleType(vecElemType->getElementType());
else
emitType(elemType);

switch (texType->getAccess())
{
case SLANG_RESOURCE_ACCESS_READ_WRITE:
m_writer->emit(getWgslImageFormat(texType));
m_writer->emit(", read_write");
break;

default:
if (auto vecElemType = as<IRVectorType>(elemType))
emitSimpleType(vecElemType->getElementType());
else
emitType(elemType);
break;
}

m_writer->emit(">");
}
}
Expand Down
11 changes: 10 additions & 1 deletion source/slang/slang-intrinsic-expand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,10 +530,12 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor)

auto textureArg = m_args[0].get();
IRType* elementType = nullptr;
bool isShadowTexture = false;

if (auto baseTextureType = as<IRTextureTypeBase>(textureArg->getDataType()))
{
elementType = baseTextureType->getElementType();
isShadowTexture = baseTextureType->isShadow();
}
else
{
Expand All @@ -548,7 +550,14 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor)
if (const auto basicType = as<IRBasicType>(elementType))
{
// A scalar result is expected
m_writer->emit(".x");

// If the texture type is a scalar type, the return type from the target intrinsic
// probably returns a scalar type already. For GLSL, ".x" swizzling happened to
// work fine on a scalar value like "1.x", but it is invalid for WGSL.
if (!isShadowTexture)
{
m_writer->emit(".x");
}
}
else if (auto vectorType = as<IRVectorType>(elementType))
{
Expand Down
Loading

0 comments on commit 177f75d

Please sign in to comment.