From b408557c7e1ff7135e3cb2178b3cb37af2c05952 Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Tue, 9 Jun 2020 14:44:50 -0400 Subject: [PATCH] Set maxVertexInputBindingStride and maxVertexInputAttributeOffset to min Vulkan values. Ensure kMVKUndefinedLarge... family of constant values are each a power-of-two. Change several power-of-two math functions to template functions. --- Docs/Whats_New.md | 2 + .../Commands/MVKMTLBufferAllocation.mm | 4 +- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 4 +- MoltenVK/MoltenVK/Utility/MVKFoundation.h | 47 ++++++++++--------- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 118881e07..a114c71b1 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -21,6 +21,8 @@ Released 2020/06/09 - Fix issue in reporting properties of substitutable `VkFormats`. - Fix vertex attribute offset adjustments when vertex buffer stride is zero. - Update `fetchDependencies` script to use pre-built `spirv-tools` files by default. +- Update `maxVertexInputBindingStride` and `maxVertexInputAttributeOffset` + to minimum Vulkan values. - Numerous documentation typo corrections. - Update `VK_MVK_MOLTENVK_SPEC_VERSION` to `26`. - Update Travis CI to Xcode 11.5. diff --git a/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.mm b/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.mm index 7e1bf2563..a09386b0b 100644 --- a/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.mm +++ b/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.mm @@ -81,7 +81,7 @@ MVKAssert(length <= _maxAllocationLength, "This MVKMTLBufferAllocator has been configured to dispense MVKMTLBufferRegions no larger than %lu bytes.", (unsigned long)_maxAllocationLength); // Convert max length to the next power-of-two exponent to use as a lookup - uint32_t p2Exp = mvkPowerOfTwoExponent(length); + NSUInteger p2Exp = mvkPowerOfTwoExponent(length); MVKMTLBufferAllocationPool* pRP = _regionPools[p2Exp]; return _makeThreadSafe ? pRP->acquireObjectSafely() : pRP->acquireObject(); } @@ -91,7 +91,7 @@ _makeThreadSafe = makeThreadSafe; // Convert max length to the next power-of-two exponent - uint32_t maxP2Exp = mvkPowerOfTwoExponent(_maxAllocationLength); + NSUInteger maxP2Exp = mvkPowerOfTwoExponent(_maxAllocationLength); // Populate the array of region pools to cover the maximum region size _regionPools.reserve(maxP2Exp + 1); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index aec27ae7f..7362b3044 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -1253,8 +1253,8 @@ _properties.limits.maxVertexInputAttributes = 31; _properties.limits.maxVertexInputBindings = 31; - _properties.limits.maxVertexInputAttributeOffset = (4 * KIBI); - _properties.limits.maxVertexInputBindingStride = _properties.limits.maxVertexInputAttributeOffset - 1; + _properties.limits.maxVertexInputBindingStride = (2 * KIBI); + _properties.limits.maxVertexInputAttributeOffset = _properties.limits.maxVertexInputBindingStride - 1; _properties.limits.maxPerStageDescriptorSamplers = _metalFeatures.maxPerStageSamplerCount; _properties.limits.maxPerStageDescriptorUniformBuffers = _metalFeatures.maxPerStageBufferCount; diff --git a/MoltenVK/MoltenVK/Utility/MVKFoundation.h b/MoltenVK/MoltenVK/Utility/MVKFoundation.h index a0f0eacc8..a8ea008b5 100644 --- a/MoltenVK/MoltenVK/Utility/MVKFoundation.h +++ b/MoltenVK/MoltenVK/Utility/MVKFoundation.h @@ -29,18 +29,6 @@ #pragma mark Math -/** - * The following constants are used to indicate values that have no defined limit. - * They are ridiculously large numbers, but low enough to be safely used as both - * uint and int values without risking overflowing between positive and negative values. - */ -static int32_t kMVKUndefinedLargeNegativeInt32 = std::numeric_limits::min() / 2; -static int32_t kMVKUndefinedLargePositiveInt32 = std::numeric_limits::max() / 2; -static uint32_t kMVKUndefinedLargeUInt32 = kMVKUndefinedLargePositiveInt32; -static int64_t kMVKUndefinedLargeNegativeInt64 = std::numeric_limits::min() / 2; -static int64_t kMVKUndefinedLargePositiveInt64 = std::numeric_limits::max() / 2; -static uint64_t kMVKUndefinedLargeUInt64 = kMVKUndefinedLargePositiveInt64; - // Common scaling multipliers #define KIBI (1024) #define MEBI (KIBI * KIBI) @@ -136,21 +124,23 @@ static inline std::string mvkGetMoltenVKVersionString(uint32_t mvkVersion) { #pragma mark - #pragma mark Alignment functions -/** Returns whether the specified value is a power-of-two. */ -static inline bool mvkIsPowerOfTwo(uintptr_t value) { +/** Returns whether the specified positive value is a power-of-two. */ +template +static inline bool mvkIsPowerOfTwo(T value) { // Test POT: (x != 0) && ((x & (x - 1)) == 0) return value && ((value & (value - 1)) == 0); } /** - * Ensures the specified value is a power-of-two. Returns the specified value if it is a - * power-of-two value. If it is not, returns the next power-of-two value that is larger - * than the specified value is returned. + * Ensures the specified positive value is a power-of-two. Returns the specified value + * if it is a power-of-two value. If it is not, returns the next power-of-two value + * that is larger than the specified value is returned. */ -static inline uintptr_t mvkEnsurePowerOfTwo(uintptr_t value) { +template +static inline T mvkEnsurePowerOfTwo(T value) { if (mvkIsPowerOfTwo(value)) { return value; } - uintptr_t pot = 1; + T pot = 1; while(pot <= value) { pot <<= 1; }; return pot; } @@ -161,12 +151,13 @@ static inline uintptr_t mvkEnsurePowerOfTwo(uintptr_t value) { * * This implementation returns zero for both zero and one as inputs. */ -static inline uint32_t mvkPowerOfTwoExponent(uintptr_t value) { - uintptr_t p2Value = mvkEnsurePowerOfTwo(value); +template +static inline T mvkPowerOfTwoExponent(T value) { + T p2Value = mvkEnsurePowerOfTwo(value); // Count the trailing zeros p2Value = (p2Value ^ (p2Value - 1)) >> 1; // Set trailing 0s to 1s and zero rest - uint32_t potExp = 0; + T potExp = 0; while (p2Value) { p2Value >>= 1; potExp++; @@ -230,6 +221,18 @@ static inline uintptr_t mvkAlignByteCount(uintptr_t byteCount, uintptr_t byteAli */ void mvkFlipVertically(void* rowMajorData, uint32_t rowCount, size_t bytesPerRow); +/** + * The following constants are used to indicate values that have no defined limit. + * They are ridiculously large numbers, but low enough to be safely used as both + * uint and int values without risking overflowing between positive and negative values. + */ +static int32_t kMVKUndefinedLargePositiveInt32 = mvkEnsurePowerOfTwo(std::numeric_limits::max() / 2); +static int32_t kMVKUndefinedLargeNegativeInt32 = -kMVKUndefinedLargePositiveInt32; +static uint32_t kMVKUndefinedLargeUInt32 = kMVKUndefinedLargePositiveInt32; +static int64_t kMVKUndefinedLargePositiveInt64 = mvkEnsurePowerOfTwo(std::numeric_limits::max() / 2); +static int64_t kMVKUndefinedLargeNegativeInt64 = -kMVKUndefinedLargePositiveInt64; +static uint64_t kMVKUndefinedLargeUInt64 = kMVKUndefinedLargePositiveInt64; + #pragma mark Vulkan structure support functions