diff options
| -rw-r--r-- | source/slang/hlsl.meta.slang | 21 | ||||
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 47 | ||||
| -rw-r--r-- | source/slang/slang-check.h | 3 | ||||
| -rw-r--r-- | source/slang/slang-mangle.cpp | 31 | ||||
| -rw-r--r-- | tests/hlsl-intrinsic/vector-dot-int.slang | 23 | ||||
| -rw-r--r-- | tests/hlsl-intrinsic/vector-dot-int.slang.expected.txt | 4 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 32 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.h | 2 | ||||
| -rw-r--r-- | tools/gfx/vulkan/vk-util.cpp | 57 | ||||
| -rw-r--r-- | tools/gfx/vulkan/vk-util.h | 4 |
10 files changed, 193 insertions, 31 deletions
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 2c969e174..7d107888a 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -1582,7 +1582,7 @@ T distance(vector<T, N> x, vector<T, N> y) // Vector dot product -__generic<T : __BuiltinArithmeticType, let N : int> +__generic<T : __BuiltinFloatingPointType, let N : int> __target_intrinsic(hlsl) __target_intrinsic(glsl) T dot(vector<T, N> x, vector<T, N> y) @@ -1593,6 +1593,17 @@ T dot(vector<T, N> x, vector<T, N> y) return result; } +__generic<T : __BuiltinIntegerType, let N : int> +__target_intrinsic(hlsl) +T dot(vector<T, N> x, vector<T, N> y) +{ + T result = T(0); + for(int i = 0; i < N; ++i) + result += x[i] * y[i]; + return result; +} + + // Helper for computing distance terms for lighting (obsolete) __generic<T : __BuiltinFloatingPointType> vector<T,4> dst(vector<T,4> x, vector<T,4> y); @@ -2568,13 +2579,19 @@ __intrinsic_op($(kIROp_Mul)) matrix<T, N, M> mul(T x, matrix<T, N, M> y); // vector-vector (dot product) -__generic<T : __BuiltinArithmeticType, let N : int> +__generic<T : __BuiltinFloatingPointType, let N : int> __target_intrinsic(hlsl) __target_intrinsic(glsl, "dot") T mul(vector<T, N> x, vector<T, N> y) { return dot(x, y); } +__generic<T : __BuiltinIntegerType, let N : int> +__target_intrinsic(hlsl) +T mul(vector<T, N> x, vector<T, N> y) +{ + return dot(x, y); +} // vector-matrix __generic<T : __BuiltinArithmeticType, let N : int, let M : int> diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 8db157a37..3c654a48b 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -12,6 +12,8 @@ #include "slang-lookup.h" +#include "slang-syntax.h" + namespace Slang { /// Visitor to transition declarations to `DeclCheckState::CheckedModifiers` @@ -5342,4 +5344,49 @@ namespace Slang } } + static void _getCanonicalConstraintTypes(List<Type*>& outTypeList, Type* type) + { + if (auto andType = as<AndType>(type)) + { + _getCanonicalConstraintTypes(outTypeList, andType->left); + _getCanonicalConstraintTypes(outTypeList, andType->right); + } + else + { + outTypeList.add(type); + } + } + OrderedDictionary<GenericTypeParamDecl*, List<Type*>> getCanonicalGenericConstraints( + DeclRef<ContainerDecl> genericDecl) + { + OrderedDictionary<GenericTypeParamDecl*, List<Type*>> genericConstraints; + for (auto mm : getMembersOfType<GenericTypeParamDecl>(genericDecl)) + { + genericConstraints[mm.getDecl()] = List<Type*>(); + } + for (auto genericTypeConstraintDecl : getMembersOfType<GenericTypeConstraintDecl>(genericDecl)) + { + assert( + genericTypeConstraintDecl.getDecl()->sub.type->astNodeType == + ASTNodeType::DeclRefType); + auto typeParamDecl = as<DeclRefType>(genericTypeConstraintDecl.getDecl()->sub.type)->declRef.getDecl(); + List<Type*>* constraintTypes = genericConstraints.TryGetValue(typeParamDecl); + assert(constraintTypes); + constraintTypes->add(genericTypeConstraintDecl.getDecl()->getSup().type); + } + + OrderedDictionary<GenericTypeParamDecl*, List<Type*>> result; + for (auto& constraints : genericConstraints) + { + List<Type*> typeList; + for (auto type : constraints.Value) + { + _getCanonicalConstraintTypes(typeList, type); + } + // TODO: we also need to sort the types within the list for each generic type param. + result[constraints.Key] = typeList; + } + return result; + } + } diff --git a/source/slang/slang-check.h b/source/slang/slang-check.h index e84ad0bc5..a7d51f951 100644 --- a/source/slang/slang-check.h +++ b/source/slang/slang-check.h @@ -22,4 +22,7 @@ namespace Slang bool isFromStdLib(Decl* decl); void registerBuiltinDecls(Session* session, Decl* decl); + + OrderedDictionary<GenericTypeParamDecl*, List<Type*>> getCanonicalGenericConstraints( + DeclRef<ContainerDecl> genericDecl); } diff --git a/source/slang/slang-mangle.cpp b/source/slang/slang-mangle.cpp index e6c0a8e7f..ca6dcecd7 100644 --- a/source/slang/slang-mangle.cpp +++ b/source/slang/slang-mangle.cpp @@ -2,6 +2,7 @@ #include "../compiler-core/slang-name.h" #include "slang-syntax.h" +#include "slang-check.h" namespace Slang { @@ -330,6 +331,12 @@ namespace Slang return; } + // TODO: we should special case GenericTypeParamDecl and GenericValueParamDecl nodes + // instead of just dumping their names here to avoid the name of a generic parameter + // to have affect the binary signature. + // For each generic parameter, we should assign it a unique ID (i, j), where i is the + // nesting level of the generic, and j is the sequential order of the parameter within + // its generic parent, and use this 2D ID to refer to such a parameter. emitName(context, declRef.getName()); // Special case: accessors need some way to distinguish themselves @@ -392,26 +399,34 @@ namespace Slang } emit(context, genericParameterCount); - for( auto mm : getMembers(parentGenericDeclRef) ) + + OrderedDictionary<GenericTypeParamDecl*, List<Type*>> genericConstraints; + for (auto mm : getMembers(parentGenericDeclRef)) { - if(auto genericTypeParamDecl = mm.as<GenericTypeParamDecl>()) + if (auto genericTypeParamDecl = mm.as<GenericTypeParamDecl>()) { emitRaw(context, "T"); } - else if(auto genericValueParamDecl = mm.as<GenericValueParamDecl>()) + else if (auto genericValueParamDecl = mm.as<GenericValueParamDecl>()) { emitRaw(context, "v"); emitType(context, getType(context->astBuilder, genericValueParamDecl)); } - else if(mm.as<GenericTypeConstraintDecl>()) - { - emitRaw(context, "C"); - // TODO: actually emit info about the constraint - } else + {} + } + + auto canonicalizedConstraints = getCanonicalGenericConstraints(parentGenericDeclRef); + for (auto& constraint : canonicalizedConstraints) + { + for (auto type : constraint.Value) { + emitRaw(context, "C"); + emitQualifiedName(context, DeclRef<Decl>(constraint.Key, nullptr)); + emitType(context, type); } } + } } diff --git a/tests/hlsl-intrinsic/vector-dot-int.slang b/tests/hlsl-intrinsic/vector-dot-int.slang new file mode 100644 index 000000000..922bd001d --- /dev/null +++ b/tests/hlsl-intrinsic/vector-dot-int.slang @@ -0,0 +1,23 @@ +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute -shaderobj +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 -use-dxil -shaderobj +//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -shaderobj +//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-cuda -compute -shaderobj + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer<int> outputBuffer; + +[numthreads(1, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int idx = int(dispatchThreadID.x); + + float tmp = dot(float3(idx), float3(1)); + + int3 a = { idx + 1, idx + 2, idx + 3}; + int3 b = { 1, 2, 3}; + + int result = dot(a, b); + + outputBuffer[idx] = result; +}
\ No newline at end of file diff --git a/tests/hlsl-intrinsic/vector-dot-int.slang.expected.txt b/tests/hlsl-intrinsic/vector-dot-int.slang.expected.txt new file mode 100644 index 000000000..18ff54819 --- /dev/null +++ b/tests/hlsl-intrinsic/vector-dot-int.slang.expected.txt @@ -0,0 +1,4 @@ +E +0 +0 +0
\ No newline at end of file diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index acc22af02..f47ca5873 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -2007,6 +2007,10 @@ Result DeviceImpl::createSamplerState(ISamplerState::Desc const& desc, ISamplerS samplerInfo.minLod = Math::Max(0.0f, desc.minLOD); samplerInfo.maxLod = Math::Clamp(desc.maxLOD, samplerInfo.minLod, VK_LOD_CLAMP_NONE); + VkSamplerReductionModeCreateInfo reductionInfo = {VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO}; + reductionInfo.reductionMode = VulkanUtil::translateReductionOp(desc.reductionOp); + samplerInfo.pNext = &reductionInfo; + VkSampler sampler; SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateSampler(m_device, &samplerInfo, nullptr, &sampler)); @@ -6575,19 +6579,6 @@ void ResourceCommandEncoder::writeTimestamp(IQueryPool* queryPool, GfxIndex inde &m_commandBuffer->m_renderer->m_api, m_commandBuffer->m_commandBuffer, queryPool, index); } -VkImageAspectFlags ResourceCommandEncoder::getAspectMask(TextureAspect aspect) -{ - VkImageAspectFlags flags = 0; - - if ((uint32_t)aspect & (uint32_t)TextureAspect::Depth) - flags |= VK_IMAGE_ASPECT_DEPTH_BIT; - if ((uint32_t)aspect & (uint32_t)TextureAspect::Stencil) - flags |= VK_IMAGE_ASPECT_STENCIL_BIT; - if ((uint32_t)aspect & (uint32_t)TextureAspect::Color) - flags |= VK_IMAGE_ASPECT_COLOR_BIT; - return flags; -} - void ResourceCommandEncoder::copyTexture( ITextureResource* dst, ResourceState dstState, @@ -6622,12 +6613,12 @@ void ResourceCommandEncoder::copyTexture( srcSubresource.mipLevelCount = dstDesc->numMipLevels; } VkImageCopy region = {}; - region.srcSubresource.aspectMask = getAspectMask(srcSubresource.aspectMask); + region.srcSubresource.aspectMask = VulkanUtil::getAspectMask(srcSubresource.aspectMask, srcImage->m_vkformat); region.srcSubresource.baseArrayLayer = srcSubresource.baseArrayLayer; region.srcSubresource.mipLevel = srcSubresource.mipLevel; region.srcSubresource.layerCount = srcSubresource.layerCount; region.srcOffset = {(int32_t)srcOffset.x, (int32_t)srcOffset.y, (int32_t)srcOffset.z}; - region.dstSubresource.aspectMask = getAspectMask(dstSubresource.aspectMask); + region.dstSubresource.aspectMask = VulkanUtil::getAspectMask(dstSubresource.aspectMask, dstImage->m_vkformat); region.dstSubresource.baseArrayLayer = dstSubresource.baseArrayLayer; region.dstSubresource.mipLevel = dstSubresource.mipLevel; region.dstSubresource.layerCount = dstSubresource.layerCount; @@ -6959,8 +6950,11 @@ void ResourceCommandEncoder::clearResourceView( auto viewImpl = static_cast<PlainBufferResourceViewImpl*>(viewImplBase); uint64_t clearStart = viewImpl->m_desc.bufferRange.firstElement; uint64_t clearSize = viewImpl->m_desc.bufferRange.elementCount; + if (clearSize == 0) clearSize = viewImpl->m_buffer->getDesc()->sizeInBytes - clearStart; + if (viewImpl->m_desc.bufferElementSize != 0) + clearSize *= viewImpl->m_desc.bufferElementSize; api.vkCmdFillBuffer( m_commandBuffer->m_commandBuffer, viewImpl->m_buffer->m_buffer.m_buffer, @@ -7012,12 +7006,12 @@ void ResourceCommandEncoder::resolveResource( for (GfxIndex mip = 0; mip < sourceRange.mipLevelCount; ++mip) { VkImageResolve region = {}; - region.srcSubresource.aspectMask = getAspectMask(sourceRange.aspectMask); + region.srcSubresource.aspectMask = VulkanUtil::getAspectMask(sourceRange.aspectMask, srcTexture->m_vkformat); region.srcSubresource.baseArrayLayer = layer + sourceRange.baseArrayLayer; region.srcSubresource.layerCount = 1; region.srcSubresource.mipLevel = mip + sourceRange.mipLevel; region.srcOffset = {0, 0, 0}; - region.dstSubresource.aspectMask = getAspectMask(destRange.aspectMask); + region.dstSubresource.aspectMask = VulkanUtil::getAspectMask(destRange.aspectMask, dstTexture->m_vkformat); region.dstSubresource.baseArrayLayer = layer + destRange.baseArrayLayer; region.dstSubresource.layerCount = 1; region.dstSubresource.mipLevel = mip + destRange.mipLevel; @@ -7077,7 +7071,7 @@ void ResourceCommandEncoder::copyTextureToBuffer( region.bufferOffset = dstOffset; region.bufferRowLength = 0; region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = getAspectMask(srcSubresource.aspectMask); + region.imageSubresource.aspectMask = VulkanUtil::getAspectMask(srcSubresource.aspectMask, image->m_vkformat); region.imageSubresource.mipLevel = srcSubresource.mipLevel; region.imageSubresource.baseArrayLayer = srcSubresource.baseArrayLayer; region.imageSubresource.layerCount = srcSubresource.layerCount; @@ -7109,7 +7103,7 @@ void ResourceCommandEncoder::textureSubresourceBarrier( barrier.image = image->m_image; barrier.oldLayout = translateImageLayout(src); barrier.newLayout = translateImageLayout(dst); - barrier.subresourceRange.aspectMask = getAspectMask(subresourceRange.aspectMask); + barrier.subresourceRange.aspectMask = VulkanUtil::getAspectMask(subresourceRange.aspectMask, image->m_vkformat); barrier.subresourceRange.baseArrayLayer = subresourceRange.baseArrayLayer; barrier.subresourceRange.baseMipLevel = subresourceRange.mipLevel; barrier.subresourceRange.layerCount = subresourceRange.layerCount; diff --git a/tools/gfx/vulkan/render-vk.h b/tools/gfx/vulkan/render-vk.h index 646c3eb98..5cec63787 100644 --- a/tools/gfx/vulkan/render-vk.h +++ b/tools/gfx/vulkan/render-vk.h @@ -1408,8 +1408,6 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* queryPool, GfxIndex index) override; - VkImageAspectFlags getAspectMask(TextureAspect aspect); - virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( ITextureResource* dst, ResourceState dstState, diff --git a/tools/gfx/vulkan/vk-util.cpp b/tools/gfx/vulkan/vk-util.cpp index 8e2a187a3..251e91cab 100644 --- a/tools/gfx/vulkan/vk-util.cpp +++ b/tools/gfx/vulkan/vk-util.cpp @@ -113,6 +113,50 @@ namespace gfx { } } +VkImageAspectFlags VulkanUtil::getAspectMask(TextureAspect aspect, VkFormat format) +{ + switch (aspect) + { + case TextureAspect::Default: + switch (format) + { + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_D32_SFLOAT: + case VK_FORMAT_X8_D24_UNORM_PACK32: + return VK_IMAGE_ASPECT_DEPTH_BIT; + case VK_FORMAT_S8_UINT: + return VK_IMAGE_ASPECT_STENCIL_BIT; + default: + return VK_IMAGE_ASPECT_COLOR_BIT; + } + case TextureAspect::Color: + return VK_IMAGE_ASPECT_COLOR_BIT; + case TextureAspect::Depth: + return VK_IMAGE_ASPECT_DEPTH_BIT; + case TextureAspect::DepthStencil: + return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + case TextureAspect::Stencil: + return VK_IMAGE_ASPECT_STENCIL_BIT; + case TextureAspect::Plane0: + return VK_IMAGE_ASPECT_PLANE_0_BIT; + case TextureAspect::Plane1: + return VK_IMAGE_ASPECT_PLANE_1_BIT; + + case TextureAspect::Plane2: + return VK_IMAGE_ASPECT_PLANE_2_BIT; + + case TextureAspect::MetaData: + return VK_IMAGE_ASPECT_METADATA_BIT; + default: + SLANG_UNREACHABLE("getAspectMask"); + return 0; + } +} + /* static */SlangResult VulkanUtil::toSlangResult(VkResult res) { return (res == VK_SUCCESS) ? SLANG_OK : SLANG_FAIL; @@ -454,6 +498,19 @@ VkStencilOpState VulkanUtil::translateStencilState(DepthStencilOpDesc desc) return rs; } +VkSamplerReductionMode VulkanUtil::translateReductionOp(TextureReductionOp op) +{ + switch (op) + { + case gfx::TextureReductionOp::Minimum: + return VK_SAMPLER_REDUCTION_MODE_MIN; + case gfx::TextureReductionOp::Maximum: + return VK_SAMPLER_REDUCTION_MODE_MAX; + default: + return VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; + } +} + /* static */Slang::Result VulkanUtil::handleFail(VkResult res) { if (res != VK_SUCCESS) diff --git a/tools/gfx/vulkan/vk-util.h b/tools/gfx/vulkan/vk-util.h index 05533dad1..ade62ba59 100644 --- a/tools/gfx/vulkan/vk-util.h +++ b/tools/gfx/vulkan/vk-util.h @@ -25,6 +25,8 @@ struct VulkanUtil /// Returns VK_FORMAT_UNDEFINED if a match is not found static VkFormat getVkFormat(Format format); + static VkImageAspectFlags getAspectMask(TextureAspect aspect, VkFormat format); + /// Called by SLANG_VK_RETURN_FAIL if a res is a failure. /// On debug builds this will cause an assertion on failure. static Slang::Result handleFail(VkResult res); @@ -100,6 +102,8 @@ struct VulkanUtil static VkStencilOpState translateStencilState(DepthStencilOpDesc desc); + static VkSamplerReductionMode translateReductionOp(TextureReductionOp op); + }; struct AccelerationStructureBuildGeometryInfoBuilder |
