diff --git a/include/slang-image-format-defs.h b/include/slang-image-format-defs.h index 0f7c7cec3f..5e7922f44e 100644 --- a/include/slang-image-format-defs.h +++ b/include/slang-image-format-defs.h @@ -45,5 +45,6 @@ SLANG_FORMAT(r16ui, (UINT16, 1, sizeof(uint16_t))) SLANG_FORMAT(r8ui, (UINT8, 1, sizeof(uint8_t))) SLANG_FORMAT(r64ui, (UINT64, 1, sizeof(uint64_t))) SLANG_FORMAT(r64i, (INT64, 1, sizeof(int64_t))) +SLANG_FORMAT(bgra8, (UINT8, 4, sizeof(uint32_t))) #undef SLANG_FORMAT diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 37dfc81147..cf338edfa6 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -1059,6 +1059,13 @@ DIAGNOSTIC( explicitUniformLocation, "Explicit binding of uniform locations is discouraged. Prefer 'ConstantBuffer<$0>' over " "'uniform $0'") +DIAGNOSTIC( + 31105, + Warning, + imageFormatUnsupportedByBackend, + "Image format '$0' is not explicitly supported by the $1 backend, using supported format '$2' " + "instead.") + DIAGNOSTIC(31120, Error, invalidAttributeTarget, "invalid syntax target for user defined attribute") diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp index b94f446908..61457d98e5 100644 --- a/source/slang/slang-emit-glsl.cpp +++ b/source/slang/slang-emit-glsl.cpp @@ -608,6 +608,19 @@ void GLSLSourceEmitter::_emitGLSLParameterGroup( m_writer->emit(";\n"); } +static bool isImageFormatSupportedByGLSL(ImageFormat format) +{ + switch (format) + { + case ImageFormat::bgra8: + // These are formats Slang accept, but are not explicitly supported in GLSL. + return false; + default: + return true; + } +}; + + void GLSLSourceEmitter::_emitGLSLImageFormatModifier(IRInst* var, IRTextureType* resourceType) { SLANG_UNUSED(resourceType); @@ -618,6 +631,18 @@ void GLSLSourceEmitter::_emitGLSLImageFormatModifier(IRInst* var, IRTextureType* if (auto formatDecoration = var->findDecoration()) { auto format = formatDecoration->getFormat(); + const auto formatInfo = getImageFormatInfo(format); + if (!isImageFormatSupportedByGLSL(format)) + { + getSink()->diagnose( + SourceLoc(), + Diagnostics::imageFormatUnsupportedByBackend, + formatInfo.name, + "GLSL", + "unknown"); + format = ImageFormat::unknown; + } + if (format == ImageFormat::unknown) { // If the user explicitly opts out of having a format, then @@ -636,7 +661,6 @@ void GLSLSourceEmitter::_emitGLSLImageFormatModifier(IRInst* var, IRTextureType* } else { - auto formatInfo = getImageFormatInfo(format); if (formatInfo.scalarType == SLANG_SCALAR_TYPE_UINT64 || formatInfo.scalarType == SLANG_SCALAR_TYPE_INT64) { diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 951507ab90..7c2e80846d 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -1901,7 +1901,7 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex } } - static SpvImageFormat getSpvImageFormat(IRTextureTypeBase* type) + SpvImageFormat getSpvImageFormat(IRTextureTypeBase* type) { ImageFormat imageFormat = type->hasFormat() ? (ImageFormat)type->getFormat() : ImageFormat::unknown; @@ -1992,7 +1992,14 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex case ImageFormat::r64i: return SpvImageFormatR64i; default: - SLANG_UNIMPLEMENTED_X("unknown image format for spirv emit"); + const auto imageFormatInfo = getImageFormatInfo(imageFormat); + m_sink->diagnose( + SourceLoc(), + Diagnostics::imageFormatUnsupportedByBackend, + imageFormatInfo.name, + "SPIRV", + "unknown"); + return SpvImageFormatUnknown; } } diff --git a/source/slang/slang-emit-wgsl.cpp b/source/slang/slang-emit-wgsl.cpp index 30a7af9385..ce60cc2a0e 100644 --- a/source/slang/slang-emit-wgsl.cpp +++ b/source/slang/slang-emit-wgsl.cpp @@ -326,7 +326,7 @@ void WGSLSourceEmitter::emit(const AddressSpace addressSpace) } } -static const char* getWgslImageFormat(IRTextureTypeBase* type) +const char* WGSLSourceEmitter::getWgslImageFormat(IRTextureTypeBase* type) { // You can find the supported WGSL texel format from the URL: // https://www.w3.org/TR/WGSL/#storage-texel-formats @@ -405,11 +405,19 @@ static const char* getWgslImageFormat(IRTextureTypeBase* type) return "rgba32sint"; case ImageFormat::rgba32f: return "rgba32float"; + case ImageFormat::bgra8: + return "bgra8unorm"; case ImageFormat::unknown: // Unlike SPIR-V, WGSL doesn't have a texel format for "unknown". return "rgba32float"; default: - // We may need to print a warning for types WGSL doesn't support + const auto imageFormatInfo = getImageFormatInfo(imageFormat); + getSink()->diagnose( + SourceLoc(), + Diagnostics::imageFormatUnsupportedByBackend, + imageFormatInfo.name, + "WGSL", + "rgba32float"); return "rgba32float"; } } diff --git a/source/slang/slang-emit-wgsl.h b/source/slang/slang-emit-wgsl.h index 4e0c18821d..714a722d7d 100644 --- a/source/slang/slang-emit-wgsl.h +++ b/source/slang/slang-emit-wgsl.h @@ -71,6 +71,8 @@ class WGSLSourceEmitter : public CLikeSourceEmitter const IRIntegerValue& rowCountWGSL, const IRIntegerValue& colCountWGSL); + const char* getWgslImageFormat(IRTextureTypeBase* type); + bool m_f16ExtensionEnabled = false; }; diff --git a/tests/diagnostics/image-format-unsupported-by-backend.slang b/tests/diagnostics/image-format-unsupported-by-backend.slang new file mode 100644 index 0000000000..270c2b63e2 --- /dev/null +++ b/tests/diagnostics/image-format-unsupported-by-backend.slang @@ -0,0 +1,19 @@ +//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK_SPIRV): -target spirv +//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK_GLSL): -target glsl +//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK_WGSL): -target wgsl + +// CHECK_SPIRV: warning 31105{{.*}}bgra8 +// CHECK_GLSL: warning 31105{{.*}}bgra8 +[format("bgra8")] +RWTexture2D outputTexture; + +// CHECK_WGSL: warning 31105{{.*}}rg8 +[format("rg8")] +RWTexture2D outputTexture2; + +[numthreads(8, 8, 1)] +void main(uint3 threadID : SV_DispatchThreadID) +{ + outputTexture[threadID.xy] = float4(1.0, 1.0, 1.0, 1.0); + outputTexture2[threadID.xy] = float4(1.0, 1.0, 1.0, 1.0); +} diff --git a/tests/hlsl-intrinsic/quad-control/quad-control-comp-functionality.slang b/tests/hlsl-intrinsic/quad-control/quad-control-comp-functionality.slang index c8f82772d4..01771f7a40 100644 --- a/tests/hlsl-intrinsic/quad-control/quad-control-comp-functionality.slang +++ b/tests/hlsl-intrinsic/quad-control/quad-control-comp-functionality.slang @@ -1,6 +1,6 @@ //TEST(compute):COMPARE_COMPUTE_EX:-vk -compute -shaderobj -emit-spirv-directly //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -profile cs_6_7 -dx12 -use-dxil -shaderobj -render-feature hardware-device -//TEST(compute):COMPARE_COMPUTE_EX:-metal -compute -shaderobj +//TEST(compute):COMPARE_COMPUTE_EX:-metal -compute -shaderobj -xslang -DMETAL //TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], stride=4):out,name outputBuffer RWStructuredBuffer outputBuffer; @@ -8,7 +8,11 @@ RWStructuredBuffer outputBuffer; [numthreads(16, 1, 1)] void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) { +#if !defined(METAL) + uint index = WaveGetLaneIndex(); +#else uint index = dispatchThreadID.x; +#endif if (index < 4) { diff --git a/tests/wgsl/texture-storage.slang b/tests/wgsl/texture-storage.slang index 1109dbfb18..62c8d13c82 100644 --- a/tests/wgsl/texture-storage.slang +++ b/tests/wgsl/texture-storage.slang @@ -28,6 +28,16 @@ RWStructuredBuffer outputBuffer; [format("rgba8")] RWTexture3D w3D_f32v4; [format("rgba8")] RWTexture2DArray w2DArray_f32v4; +//TEST_INPUT: RWTexture1D(format=B8G8R8A8_UNORM, size=4, content = zero):name w1D_f32_bgra_v4 +//TEST_INPUT: RWTexture2D(format=B8G8R8A8_UNORM, size=4, content = zero):name w2D_f32_bgra_v4 +//TEST_INPUT: RWTexture3D(format=B8G8R8A8_UNORM, size=4, content = zero):name w3D_f32_bgra_v4 +//TEST_INPUT: RWTexture2D(format=B8G8R8A8_UNORM, size=4, content = zero, arrayLength=2):name w2DArray_f32_bgra_v4 +// WGSL: var w1D_f32_bgra_v4{{[^:]*}}: texture_storage_1d +[format("bgra8")] RWTexture1D w1D_f32_bgra_v4; +[format("bgra8")] RWTexture2D w2D_f32_bgra_v4; +[format("bgra8")] RWTexture3D w3D_f32_bgra_v4; +[format("bgra8")] RWTexture2DArray w2DArray_f32_bgra_v4; + // i32 types //TEST_INPUT: RWTexture1D(format=R32G32_SINT, size=4, content = zero):name w1D_i32v2 @@ -127,6 +137,7 @@ void fragMain() bool result = true && TEST_textureStorage_StoreLoad(w1D_f32v2, w2D_f32v2, w3D_f32v2, w2DArray_f32v2) && TEST_textureStorage_StoreLoad(w1D_f32v4, w2D_f32v4, w3D_f32v4, w2DArray_f32v4) + && TEST_textureStorage_StoreLoad(w1D_f32_bgra_v4, w2D_f32_bgra_v4, w3D_f32_bgra_v4, w2DArray_f32_bgra_v4) && TEST_textureStorage_StoreLoad(w1D_i32v2, w2D_i32v2, w3D_i32v2, w2DArray_i32v2) && TEST_textureStorage_StoreLoad(w1D_i32v4, w2D_i32v4, w3D_i32v4, w2DArray_i32v4) && TEST_textureStorage_StoreLoad(w1D_u32v2, w2D_u32v2, w3D_u32v2, w2DArray_u32v2)