Merge pull request #789 from billhollings/master

Fix inconsistency in reporting device local memory between type and heap on macOS.
This commit is contained in:
Bill Hollings 2019-12-16 09:16:53 -05:00 committed by GitHub
commit ef8575f219
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 270 additions and 233 deletions

View File

@ -545,7 +545,7 @@
29B97313FDCFA39411CA2CEA /* Project object */ = { 29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 1120; LastUpgradeCheck = 1130;
}; };
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "API-Samples" */; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "API-Samples" */;
compatibilityVersion = "Xcode 8.0"; compatibilityVersion = "Xcode 8.0";

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -234,7 +234,7 @@
29B97313FDCFA39411CA2CEA /* Project object */ = { 29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 1120; LastUpgradeCheck = 1130;
}; };
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Cube" */; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Cube" */;
compatibilityVersion = "Xcode 8.0"; compatibilityVersion = "Xcode 8.0";

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -265,7 +265,7 @@
29B97313FDCFA39411CA2CEA /* Project object */ = { 29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 1120; LastUpgradeCheck = 1130;
}; };
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Hologram" */; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Hologram" */;
compatibilityVersion = "Xcode 8.0"; compatibilityVersion = "Xcode 8.0";

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -27,8 +27,12 @@ Released TBD
- Fix image subresource sizing calculations for heap-based textures. - Fix image subresource sizing calculations for heap-based textures.
- Fix `MTLHeap` memory leak in `MVKDeviceMemory`. - Fix `MTLHeap` memory leak in `MVKDeviceMemory`.
- Fix tessellation break when control stage declares but does not use position builtin. - Fix tessellation break when control stage declares but does not use position builtin.
- Fix inconsistency in reporting device local memory between type and heap on macOS.
- Fix bug where dynamic shader buffers are overflowing.
- Avoid reading env vars inside library constructor functions.
- Update `VK_MVK_MOLTENVK_SPEC_VERSION` to `23`.
- Cube demo use `VK_EXT_metal_surface` extension. - Cube demo use `VK_EXT_metal_surface` extension.
- Support *Xcode 11.2*. - Support *Xcode 11.3*.

View File

@ -2946,7 +2946,7 @@
A9F55D25198BE6A7004EC31B /* Project object */ = { A9F55D25198BE6A7004EC31B /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 1120; LastUpgradeCheck = 1130;
ORGANIZATIONNAME = "The Brenwill Workshop Ltd."; ORGANIZATIONNAME = "The Brenwill Workshop Ltd.";
TargetAttributes = { TargetAttributes = {
A972A7E421CEC72F0013AB25 = { A972A7E421CEC72F0013AB25 = {

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -830,7 +830,7 @@
A9F55D25198BE6A7004EC31B /* Project object */ = { A9F55D25198BE6A7004EC31B /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 1120; LastUpgradeCheck = 1130;
ORGANIZATIONNAME = "The Brenwill Workshop Ltd."; ORGANIZATIONNAME = "The Brenwill Workshop Ltd.";
TargetAttributes = { TargetAttributes = {
A9B8EE091A98D796009C5A02 = { A9B8EE091A98D796009C5A02 = {

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -455,12 +455,12 @@ static inline VkExtent3D mvkVkExtent3DFromMTLSize(MTLSize mtlSize) {
/** Macro indicating the Vulkan memory type bits corresponding to Metal private memory (not host visible). */ /** Macro indicating the Vulkan memory type bits corresponding to Metal private memory (not host visible). */
#define MVK_VK_MEMORY_TYPE_METAL_PRIVATE (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) #define MVK_VK_MEMORY_TYPE_METAL_PRIVATE (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
/** Macro indicating the Vulkan memory type bits corresponding to Metal shared memory (host visible and coherent). */
#define MVK_VK_MEMORY_TYPE_METAL_SHARED (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
/** Macro indicating the Vulkan memory type bits corresponding to Metal managed memory (host visible and non-coherent). */ /** Macro indicating the Vulkan memory type bits corresponding to Metal managed memory (host visible and non-coherent). */
#define MVK_VK_MEMORY_TYPE_METAL_MANAGED (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT) #define MVK_VK_MEMORY_TYPE_METAL_MANAGED (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
/** Macro indicating the Vulkan memory type bits corresponding to Metal shared memory (host visible and coherent). */
#define MVK_VK_MEMORY_TYPE_METAL_SHARED (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
/** Macro indicating the Vulkan memory type bits corresponding to Metal memoryless memory (not host visible and lazily allocated). */ /** Macro indicating the Vulkan memory type bits corresponding to Metal memoryless memory (not host visible and lazily allocated). */
#define MVK_VK_MEMORY_TYPE_METAL_MEMORYLESS (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) #define MVK_VK_MEMORY_TYPE_METAL_MEMORYLESS (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)

View File

@ -55,7 +55,7 @@ typedef unsigned long MTLLanguageVersion;
#define MVK_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch)) #define MVK_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch))
#define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH) #define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH)
#define VK_MVK_MOLTENVK_SPEC_VERSION 22 #define VK_MVK_MOLTENVK_SPEC_VERSION 23
#define VK_MVK_MOLTENVK_EXTENSION_NAME "VK_MVK_moltenvk" #define VK_MVK_MOLTENVK_EXTENSION_NAME "VK_MVK_moltenvk"
/** /**
@ -528,7 +528,7 @@ typedef struct {
uint32_t mslVersion; /**< The version of the Metal Shading Language available on this device. The format of the integer is MMmmpp, with two decimal digts each for Major, minor, and patch version values (eg. MSL 1.2 would appear as 010200). */ uint32_t mslVersion; /**< The version of the Metal Shading Language available on this device. The format of the integer is MMmmpp, with two decimal digts each for Major, minor, and patch version values (eg. MSL 1.2 would appear as 010200). */
VkBool32 indirectDrawing; /**< If true, draw calls support parameters held in a GPU buffer. */ VkBool32 indirectDrawing; /**< If true, draw calls support parameters held in a GPU buffer. */
VkBool32 baseVertexInstanceDrawing; /**< If true, draw calls support specifiying the base vertex and instance. */ VkBool32 baseVertexInstanceDrawing; /**< If true, draw calls support specifiying the base vertex and instance. */
VkBool32 dynamicMTLBuffers; /**< If true, dynamic MTLBuffers for setting vertex, fragment, and compute bytes are supported. */ uint32_t dynamicMTLBufferSize; /**< If greater than zero, dynamic MTLBuffers for setting vertex, fragment, and compute bytes are supported, and their content must be below this value. */
VkBool32 shaderSpecialization; /**< If true, shader specialization (aka Metal function constants) is supported. */ VkBool32 shaderSpecialization; /**< If true, shader specialization (aka Metal function constants) is supported. */
VkBool32 ioSurfaces; /**< If true, VkImages can be underlaid by IOSurfaces via the vkUseIOSurfaceMVK() function, to support inter-process image transfers. */ VkBool32 ioSurfaces; /**< If true, VkImages can be underlaid by IOSurfaces via the vkUseIOSurfaceMVK() function, to support inter-process image transfers. */
VkBool32 texelBuffers; /**< If true, texel buffers are supported, allowing the contents of a buffer to be interpreted as an image via a VkBufferView. */ VkBool32 texelBuffers; /**< If true, texel buffers are supported, allowing the contents of a buffer to be interpreted as an image via a VkBufferView. */

View File

@ -502,7 +502,7 @@ void MVKCommandEncoder::setVertexBytes(id<MTLRenderCommandEncoder> mtlEncoder,
const void* bytes, const void* bytes,
NSUInteger length, NSUInteger length,
uint32_t mtlBuffIndex) { uint32_t mtlBuffIndex) {
if (_pDeviceMetalFeatures->dynamicMTLBuffers) { if (_pDeviceMetalFeatures->dynamicMTLBufferSize && length <= _pDeviceMetalFeatures->dynamicMTLBufferSize) {
[mtlEncoder setVertexBytes: bytes length: length atIndex: mtlBuffIndex]; [mtlEncoder setVertexBytes: bytes length: length atIndex: mtlBuffIndex];
} else { } else {
const MVKMTLBufferAllocation* mtlBuffAlloc = copyToTempMTLBufferAllocation(bytes, length); const MVKMTLBufferAllocation* mtlBuffAlloc = copyToTempMTLBufferAllocation(bytes, length);
@ -514,7 +514,7 @@ void MVKCommandEncoder::setFragmentBytes(id<MTLRenderCommandEncoder> mtlEncoder,
const void* bytes, const void* bytes,
NSUInteger length, NSUInteger length,
uint32_t mtlBuffIndex) { uint32_t mtlBuffIndex) {
if (_pDeviceMetalFeatures->dynamicMTLBuffers) { if (_pDeviceMetalFeatures->dynamicMTLBufferSize && length <= _pDeviceMetalFeatures->dynamicMTLBufferSize) {
[mtlEncoder setFragmentBytes: bytes length: length atIndex: mtlBuffIndex]; [mtlEncoder setFragmentBytes: bytes length: length atIndex: mtlBuffIndex];
} else { } else {
const MVKMTLBufferAllocation* mtlBuffAlloc = copyToTempMTLBufferAllocation(bytes, length); const MVKMTLBufferAllocation* mtlBuffAlloc = copyToTempMTLBufferAllocation(bytes, length);
@ -526,7 +526,7 @@ void MVKCommandEncoder::setComputeBytes(id<MTLComputeCommandEncoder> mtlEncoder,
const void* bytes, const void* bytes,
NSUInteger length, NSUInteger length,
uint32_t mtlBuffIndex) { uint32_t mtlBuffIndex) {
if (_pDeviceMetalFeatures->dynamicMTLBuffers) { if (_pDeviceMetalFeatures->dynamicMTLBufferSize && length <= _pDeviceMetalFeatures->dynamicMTLBufferSize) {
[mtlEncoder setBytes: bytes length: length atIndex: mtlBuffIndex]; [mtlEncoder setBytes: bytes length: length atIndex: mtlBuffIndex];
} else { } else {
const MVKMTLBufferAllocation* mtlBuffAlloc = copyToTempMTLBufferAllocation(bytes, length); const MVKMTLBufferAllocation* mtlBuffAlloc = copyToTempMTLBufferAllocation(bytes, length);

View File

@ -137,7 +137,7 @@ typedef struct MVKRPSKeyClearAtt_t {
} }
void reset() { void reset() {
memset(this, 0, sizeof(*this)); mvkClear(this);
mtlSampleCount = mvkSampleCountFromVkSampleCountFlagBits(VK_SAMPLE_COUNT_1_BIT); mtlSampleCount = mvkSampleCountFromVkSampleCountFlagBits(VK_SAMPLE_COUNT_1_BIT);
} }
@ -180,7 +180,7 @@ typedef struct MVKMTLStencilDescriptorData_t {
// Start with all zeros to ensure memory comparisons will work, // Start with all zeros to ensure memory comparisons will work,
// even if the structure contains alignment gaps. // even if the structure contains alignment gaps.
memset(this, 0, sizeof(*this)); mvkClear(this);
enabled = false, enabled = false,
stencilCompareFunction = MTLCompareFunctionAlways; stencilCompareFunction = MTLCompareFunctionAlways;
@ -233,7 +233,7 @@ typedef struct MVKMTLDepthStencilDescriptorData_t {
MVKMTLDepthStencilDescriptorData_t() { MVKMTLDepthStencilDescriptorData_t() {
// Start with all zeros to ensure memory comparisons will work, // Start with all zeros to ensure memory comparisons will work,
// even if the structure contains alignment gaps. // even if the structure contains alignment gaps.
memset(this, 0, sizeof(*this)); mvkClear(this);
disable(true, true); disable(true, true);
} }
@ -276,7 +276,7 @@ typedef struct MVKImageDescriptorData_t {
return mvkHash((uint64_t*)this, sizeof(*this) / sizeof(uint64_t)); return mvkHash((uint64_t*)this, sizeof(*this) / sizeof(uint64_t));
} }
MVKImageDescriptorData_t() { memset(this, 0, sizeof(*this)); } MVKImageDescriptorData_t() { mvkClear(this); }
} __attribute__((aligned(sizeof(uint64_t)))) MVKImageDescriptorData; } __attribute__((aligned(sizeof(uint64_t)))) MVKImageDescriptorData;
@ -313,7 +313,7 @@ typedef struct MVKBufferDescriptorData_t {
return mvkHash((uint64_t*)this, sizeof(*this) / sizeof(uint64_t)); return mvkHash((uint64_t*)this, sizeof(*this) / sizeof(uint64_t));
} }
MVKBufferDescriptorData_t() { memset(this, 0, sizeof(*this)); } MVKBufferDescriptorData_t() { mvkClear(this); }
} __attribute__((aligned(sizeof(uint64_t)))) MVKBufferDescriptorData; } __attribute__((aligned(sizeof(uint64_t)))) MVKBufferDescriptorData;

View File

@ -338,6 +338,8 @@ protected:
void initProperties(); void initProperties();
void initGPUInfoProperties(); void initGPUInfoProperties();
void initMemoryProperties(); void initMemoryProperties();
void setMemoryHeap(uint32_t heapIndex, VkDeviceSize heapSize, VkMemoryHeapFlags heapFlags);
void setMemoryType(uint32_t typeIndex, uint32_t heapIndex, VkMemoryPropertyFlags propertyFlags);
uint64_t getVRAMSize(); uint64_t getVRAMSize();
uint64_t getRecommendedMaxWorkingSetSize(); uint64_t getRecommendedMaxWorkingSetSize();
uint64_t getCurrentAllocatedSize(); uint64_t getCurrentAllocatedSize();

View File

@ -272,7 +272,7 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format,
case VK_IMAGE_TYPE_1D: case VK_IMAGE_TYPE_1D:
maxExt.height = 1; maxExt.height = 1;
maxExt.depth = 1; maxExt.depth = 1;
if (_mvkTexture1DAs2D) { if (mvkTreatTexture1DAs2D()) {
maxExt.width = pLimits->maxImageDimension2D; maxExt.width = pLimits->maxImageDimension2D;
maxLevels = mvkMipmapLevels3D(maxExt); maxLevels = mvkMipmapLevels3D(maxExt);
} else { } else {
@ -752,8 +752,8 @@ VkResult MVKPhysicalDevice::getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMe
switch (next->sType) { switch (next->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: {
auto* budgetProps = (VkPhysicalDeviceMemoryBudgetPropertiesEXT*)next; auto* budgetProps = (VkPhysicalDeviceMemoryBudgetPropertiesEXT*)next;
memset(budgetProps->heapBudget, 0, sizeof(budgetProps->heapBudget)); mvkClear(budgetProps->heapBudget);
memset(budgetProps->heapUsage, 0, sizeof(budgetProps->heapUsage)); mvkClear(budgetProps->heapUsage);
budgetProps->heapBudget[0] = (VkDeviceSize)getRecommendedMaxWorkingSetSize(); budgetProps->heapBudget[0] = (VkDeviceSize)getRecommendedMaxWorkingSetSize();
budgetProps->heapUsage[0] = (VkDeviceSize)getCurrentAllocatedSize(); budgetProps->heapUsage[0] = (VkDeviceSize)getCurrentAllocatedSize();
if (!getHasUnifiedMemory()) { if (!getHasUnifiedMemory()) {
@ -787,11 +787,11 @@ MVKPhysicalDevice::MVKPhysicalDevice(MVKInstance* mvkInstance, id<MTLDevice> mtl
/** Initializes the Metal-specific physical device features of this instance. */ /** Initializes the Metal-specific physical device features of this instance. */
void MVKPhysicalDevice::initMetalFeatures() { void MVKPhysicalDevice::initMetalFeatures() {
memset(&_metalFeatures, 0, sizeof(_metalFeatures)); // Start with everything cleared mvkClear(&_metalFeatures); // Start with everything cleared
_metalFeatures.maxPerStageBufferCount = 31; _metalFeatures.maxPerStageBufferCount = 31;
_metalFeatures.maxMTLBufferSize = (256 * MEBI); _metalFeatures.maxMTLBufferSize = (256 * MEBI);
_metalFeatures.dynamicMTLBuffers = false; _metalFeatures.dynamicMTLBufferSize = 0;
_metalFeatures.maxPerStageSamplerCount = 16; _metalFeatures.maxPerStageSamplerCount = 16;
_metalFeatures.maxQueryBufferSize = (64 * KIBI); _metalFeatures.maxQueryBufferSize = (64 * KIBI);
@ -812,7 +812,7 @@ void MVKPhysicalDevice::initMetalFeatures() {
if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily1_v2] ) { if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily1_v2] ) {
_metalFeatures.mslVersionEnum = MTLLanguageVersion1_1; _metalFeatures.mslVersionEnum = MTLLanguageVersion1_1;
_metalFeatures.dynamicMTLBuffers = true; _metalFeatures.dynamicMTLBufferSize = (4 * KIBI);
_metalFeatures.maxTextureDimension = (8 * KIBI); _metalFeatures.maxTextureDimension = (8 * KIBI);
} }
@ -881,7 +881,7 @@ void MVKPhysicalDevice::initMetalFeatures() {
if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily1_v2] ) { if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily1_v2] ) {
_metalFeatures.mslVersionEnum = MTLLanguageVersion1_2; _metalFeatures.mslVersionEnum = MTLLanguageVersion1_2;
_metalFeatures.dynamicMTLBuffers = true; _metalFeatures.dynamicMTLBufferSize = (4 * KIBI);
_metalFeatures.shaderSpecialization = true; _metalFeatures.shaderSpecialization = true;
_metalFeatures.stencilViews = true; _metalFeatures.stencilViews = true;
_metalFeatures.samplerClampToBorder = true; _metalFeatures.samplerClampToBorder = true;
@ -979,7 +979,7 @@ bool MVKPhysicalDevice::getSupportsGPUFamily(MTLGPUFamily gpuFamily) {
// Initializes the physical device features of this instance. // Initializes the physical device features of this instance.
void MVKPhysicalDevice::initFeatures() { void MVKPhysicalDevice::initFeatures() {
memset(&_features, 0, sizeof(_features)); // Start with everything cleared mvkClear(&_features); // Start with everything cleared
_features.robustBufferAccess = true; // XXX Required by Vulkan spec _features.robustBufferAccess = true; // XXX Required by Vulkan spec
_features.fullDrawIndexUint32 = true; _features.fullDrawIndexUint32 = true;
@ -1130,7 +1130,7 @@ void MVKPhysicalDevice::initFeatures() {
/** Initializes the physical device properties of this instance. */ /** Initializes the physical device properties of this instance. */
void MVKPhysicalDevice::initProperties() { void MVKPhysicalDevice::initProperties() {
memset(&_properties, 0, sizeof(_properties)); // Start with everything cleared mvkClear(&_properties); // Start with everything cleared
_properties.apiVersion = MVK_VULKAN_API_VERSION; _properties.apiVersion = MVK_VULKAN_API_VERSION;
_properties.driverVersion = MVK_VERSION; _properties.driverVersion = MVK_VERSION;
@ -1667,7 +1667,7 @@ void MVKPhysicalDevice::initGPUInfoProperties() {
void MVKPhysicalDevice::initPipelineCacheUUID() { void MVKPhysicalDevice::initPipelineCacheUUID() {
// Clear the UUID // Clear the UUID
memset(&_properties.pipelineCacheUUID, 0, sizeof(_properties.pipelineCacheUUID)); mvkClear(&_properties.pipelineCacheUUID);
size_t uuidComponentOffset = 0; size_t uuidComponentOffset = 0;
@ -1749,9 +1749,17 @@ uint64_t MVKPhysicalDevice::getSpirvCrossRevision() {
return revVal; return revVal;
} }
/** Initializes the memory properties of this instance. */ void MVKPhysicalDevice::setMemoryHeap(uint32_t heapIndex, VkDeviceSize heapSize, VkMemoryHeapFlags heapFlags) {
void MVKPhysicalDevice::initMemoryProperties() { _memoryProperties.memoryHeaps[heapIndex].size = heapSize;
_memoryProperties.memoryHeaps[heapIndex].flags = heapFlags;
}
void MVKPhysicalDevice::setMemoryType(uint32_t typeIndex, uint32_t heapIndex, VkMemoryPropertyFlags propertyFlags) {
_memoryProperties.memoryTypes[typeIndex].heapIndex = heapIndex;
_memoryProperties.memoryTypes[typeIndex].propertyFlags = propertyFlags;
}
// Initializes the memory properties of this instance.
// Metal Shared: // Metal Shared:
// - applies to both buffers and textures // - applies to both buffers and textures
// - default mode for buffers on both iOS & macOS // - default mode for buffers on both iOS & macOS
@ -1783,71 +1791,68 @@ void MVKPhysicalDevice::initMemoryProperties() {
// - storage comes from tile memory // - storage comes from tile memory
// - contents are undefined after rendering // - contents are undefined after rendering
// - use for temporary renderable textures // - use for temporary renderable textures
void MVKPhysicalDevice::initMemoryProperties() {
_memoryProperties = (VkPhysicalDeviceMemoryProperties){ mvkClear(&_memoryProperties); // Start with everything cleared
.memoryHeapCount = 1,
.memoryHeaps = {
{
.flags = (VK_MEMORY_HEAP_DEVICE_LOCAL_BIT),
.size = (VkDeviceSize)getVRAMSize(),
},
},
// NB this list needs to stay sorted by propertyFlags (as bit sets)
.memoryTypes = {
{
.heapIndex = 0,
.propertyFlags = MVK_VK_MEMORY_TYPE_METAL_PRIVATE, // Private storage
},
#if MVK_MACOS
{
.heapIndex = 0,
.propertyFlags = MVK_VK_MEMORY_TYPE_METAL_MANAGED, // Managed storage
},
#endif
{
.heapIndex = 0,
.propertyFlags = MVK_VK_MEMORY_TYPE_METAL_SHARED, // Shared storage
},
#if MVK_IOS
{
.heapIndex = 0,
.propertyFlags = MVK_VK_MEMORY_TYPE_METAL_MEMORYLESS, // Memoryless storage
},
#endif
},
};
// Main heap
uint32_t mainHeapIdx = 0;
setMemoryHeap(mainHeapIdx, getVRAMSize(), VK_MEMORY_HEAP_DEVICE_LOCAL_BIT);
// Optional second heap for shared memory
uint32_t sharedHeapIdx;
VkMemoryPropertyFlags sharedTypePropFlags;
if (getHasUnifiedMemory()) {
// Shared memory goes in the single main heap in unified memory, and per Vulkan spec must be marked local
sharedHeapIdx = mainHeapIdx;
sharedTypePropFlags = MVK_VK_MEMORY_TYPE_METAL_SHARED | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
} else {
// Define a second heap to mark the shared memory as non-local
sharedHeapIdx = mainHeapIdx + 1;
setMemoryHeap(sharedHeapIdx, mvkGetSystemMemorySize(), 0);
sharedTypePropFlags = MVK_VK_MEMORY_TYPE_METAL_SHARED;
}
_memoryProperties.memoryHeapCount = sharedHeapIdx + 1;
// Memory types
uint32_t typeIdx = 0;
// Private storage
uint32_t privateBit = 1 << typeIdx;
setMemoryType(typeIdx, mainHeapIdx, MVK_VK_MEMORY_TYPE_METAL_PRIVATE);
typeIdx++;
// Shared storage
uint32_t sharedBit = 1 << typeIdx;
setMemoryType(typeIdx, sharedHeapIdx, sharedTypePropFlags);
typeIdx++;
// Managed storage
uint32_t managedBit = 0;
#if MVK_MACOS #if MVK_MACOS
_memoryProperties.memoryTypeCount = 3; managedBit = 1 << typeIdx;
_privateMemoryTypes = 0x1; // Private only setMemoryType(typeIdx, mainHeapIdx, MVK_VK_MEMORY_TYPE_METAL_MANAGED);
_lazilyAllocatedMemoryTypes = 0x0; // Not supported on macOS typeIdx++;
_hostCoherentMemoryTypes = 0x4; // Shared only
_hostVisibleMemoryTypes = 0x6; // Shared & managed
_allMemoryTypes = 0x7; // Private, shared, & managed
#endif #endif
// Memoryless storage
uint32_t memlessBit = 0;
#if MVK_IOS #if MVK_IOS
_memoryProperties.memoryTypeCount = 2; // Managed storage not available on iOS if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily1_v3]) {
_privateMemoryTypes = 0x1; // Private only memlessBit = 1 << typeIdx;
_lazilyAllocatedMemoryTypes = 0x0; // Not supported on this version setMemoryType(typeIdx, mainHeapIdx, MVK_VK_MEMORY_TYPE_METAL_MEMORYLESS);
_hostCoherentMemoryTypes = 0x2; // Shared only typeIdx++;
_hostVisibleMemoryTypes = 0x2; // Shared only
_allMemoryTypes = 0x3; // Private & shared
if ([getMTLDevice() supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily1_v3]) {
_memoryProperties.memoryTypeCount = 3; // Memoryless storage available
_privateMemoryTypes = 0x5; // Private & memoryless
_lazilyAllocatedMemoryTypes = 0x4; // Memoryless only
_allMemoryTypes = 0x7; // Private, shared & memoryless
}
#endif
#if MVK_MACOS
if (!getHasUnifiedMemory()) {
// This means we really have two heaps. The second heap is system memory.
_memoryProperties.memoryHeapCount = 2;
_memoryProperties.memoryHeaps[1].size = mvkGetSystemMemorySize();
_memoryProperties.memoryHeaps[1].flags = 0;
_memoryProperties.memoryTypes[2].heapIndex = 1; // Shared memory in the shared heap
} }
#endif #endif
_memoryProperties.memoryTypeCount = typeIdx;
_privateMemoryTypes = privateBit | memlessBit;
_hostVisibleMemoryTypes = sharedBit | managedBit;
_hostCoherentMemoryTypes = sharedBit;
_lazilyAllocatedMemoryTypes = memlessBit;
_allMemoryTypes = privateBit | sharedBit | managedBit | memlessBit;
} }
bool MVKPhysicalDevice::getHasUnifiedMemory() { bool MVKPhysicalDevice::getHasUnifiedMemory() {
@ -1855,21 +1860,20 @@ bool MVKPhysicalDevice::getHasUnifiedMemory() {
return true; return true;
#endif #endif
#if MVK_MACOS #if MVK_MACOS
return [_mtlDevice respondsToSelector: @selector(hasUnifiedMemory)] && _mtlDevice.hasUnifiedMemory; return (([_mtlDevice respondsToSelector: @selector(hasUnifiedMemory)] && _mtlDevice.hasUnifiedMemory)
|| _mtlDevice.isLowPower
|| getInstance()->getPhysicalDeviceCount() == 1);
#endif #endif
} }
uint64_t MVKPhysicalDevice::getVRAMSize() { uint64_t MVKPhysicalDevice::getVRAMSize() {
#if MVK_IOS if (getHasUnifiedMemory()) {
// All iOS devices are UMA, so return the system memory size.
return mvkGetSystemMemorySize(); return mvkGetSystemMemorySize();
#endif } else {
#if MVK_MACOS
if (getHasUnifiedMemory()) { return mvkGetSystemMemorySize(); }
// There's actually no way to query the total physical VRAM on the device in Metal. // There's actually no way to query the total physical VRAM on the device in Metal.
// Just default to using the recommended max working set size (i.e. the budget). // Just default to using the recommended max working set size (i.e. the budget).
return getRecommendedMaxWorkingSetSize(); return getRecommendedMaxWorkingSetSize();
#endif }
} }
uint64_t MVKPhysicalDevice::getRecommendedMaxWorkingSetSize() { uint64_t MVKPhysicalDevice::getRecommendedMaxWorkingSetSize() {
@ -2050,7 +2054,7 @@ void MVKDevice::getDescriptorSetLayoutSupport(const VkDescriptorSetLayoutCreateI
} }
VkResult MVKDevice::getDeviceGroupPresentCapabilities(VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) { VkResult MVKDevice::getDeviceGroupPresentCapabilities(VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
memset(pDeviceGroupPresentCapabilities->presentMask, 0, sizeof(pDeviceGroupPresentCapabilities->presentMask)); mvkClear(pDeviceGroupPresentCapabilities->presentMask);
pDeviceGroupPresentCapabilities->presentMask[0] = 0x1; pDeviceGroupPresentCapabilities->presentMask[0] = 0x1;
pDeviceGroupPresentCapabilities->modes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR; pDeviceGroupPresentCapabilities->modes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
@ -2680,18 +2684,18 @@ void MVKDevice::initPhysicalDevice(MVKPhysicalDevice* physicalDevice, const VkDe
void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) { void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) {
// Start with all features disabled // Start with all features disabled
memset((void*)&_enabledFeatures, 0, sizeof(_enabledFeatures)); mvkClear(&_enabledFeatures);
memset((void*)&_enabledStorage16Features, 0, sizeof(_enabledStorage16Features)); mvkClear(&_enabledStorage16Features);
memset((void*)&_enabledStorage8Features, 0, sizeof(_enabledStorage8Features)); mvkClear(&_enabledStorage8Features);
memset((void*)&_enabledF16I8Features, 0, sizeof(_enabledF16I8Features)); mvkClear(&_enabledF16I8Features);
memset((void*)&_enabledUBOLayoutFeatures, 0, sizeof(_enabledUBOLayoutFeatures)); mvkClear(&_enabledUBOLayoutFeatures);
memset((void*)&_enabledVarPtrFeatures, 0, sizeof(_enabledVarPtrFeatures)); mvkClear(&_enabledVarPtrFeatures);
memset((void*)&_enabledInterlockFeatures, 0, sizeof(_enabledInterlockFeatures)); mvkClear(&_enabledInterlockFeatures);
memset((void*)&_enabledHostQryResetFeatures, 0, sizeof(_enabledHostQryResetFeatures)); mvkClear(&_enabledHostQryResetFeatures);
memset((void*)&_enabledScalarLayoutFeatures, 0, sizeof(_enabledScalarLayoutFeatures)); mvkClear(&_enabledScalarLayoutFeatures);
memset((void*)&_enabledTexelBuffAlignFeatures, 0, sizeof(_enabledTexelBuffAlignFeatures)); mvkClear(&_enabledTexelBuffAlignFeatures);
memset((void*)&_enabledVtxAttrDivFeatures, 0, sizeof(_enabledVtxAttrDivFeatures)); mvkClear(&_enabledVtxAttrDivFeatures);
memset((void*)&_enabledPortabilityFeatures, 0, sizeof(_enabledPortabilityFeatures)); mvkClear(&_enabledPortabilityFeatures);
// Fetch the available physical device features. // Fetch the available physical device features.
VkPhysicalDevicePortabilitySubsetFeaturesEXTX pdPortabilityFeatures; VkPhysicalDevicePortabilitySubsetFeaturesEXTX pdPortabilityFeatures;

View File

@ -231,7 +231,9 @@ bool MVKImage::validateUseTexelBuffer() {
useTexelBuffer = useTexelBuffer && _deviceMemory && _deviceMemory->_mtlBuffer; // Buffer is available to overlay useTexelBuffer = useTexelBuffer && _deviceMemory && _deviceMemory->_mtlBuffer; // Buffer is available to overlay
#if MVK_MACOS #if MVK_MACOS
useTexelBuffer = useTexelBuffer && !isMemoryHostCoherent(); // macOS cannot use shared memory for texel buffers // macOS cannot use shared memory for texel buffers.
// Test _deviceMemory->isMemoryHostCoherent() directly because local version overrides.
useTexelBuffer = useTexelBuffer && _deviceMemory && !_deviceMemory->isMemoryHostCoherent();
#endif #endif
return useTexelBuffer; return useTexelBuffer;
@ -476,12 +478,12 @@ MTLTextureDescriptor* MVKImage::newMTLTextureDescriptor() {
MTLStorageMode MVKImage::getMTLStorageMode() { MTLStorageMode MVKImage::getMTLStorageMode() {
if ( !_deviceMemory ) return MTLStorageModePrivate; if ( !_deviceMemory ) return MTLStorageModePrivate;
// For macOS, textures cannot use Shared storage mode, so change to Managed storage mode.
MTLStorageMode stgMode = _deviceMemory->getMTLStorageMode(); MTLStorageMode stgMode = _deviceMemory->getMTLStorageMode();
if (_ioSurface && stgMode == MTLStorageModePrivate) { stgMode = MTLStorageModeShared; } if (_ioSurface && stgMode == MTLStorageModePrivate) { stgMode = MTLStorageModeShared; }
#if MVK_MACOS #if MVK_MACOS
// For macOS, textures cannot use Shared storage mode, so change to Managed storage mode.
if (stgMode == MTLStorageModeShared) { stgMode = MTLStorageModeManaged; } if (stgMode == MTLStorageModeShared) { stgMode = MTLStorageModeManaged; }
#endif #endif
return stgMode; return stgMode;
@ -660,7 +662,7 @@ VkSampleCountFlagBits MVKImage::validateSamples(const VkImageCreateInfo* pCreate
if (validSamples == VK_SAMPLE_COUNT_1_BIT) { return validSamples; } if (validSamples == VK_SAMPLE_COUNT_1_BIT) { return validSamples; }
// Don't use getImageType() because it hasn't been set yet. // Don't use getImageType() because it hasn't been set yet.
if ( !((pCreateInfo->imageType == VK_IMAGE_TYPE_2D) || ((pCreateInfo->imageType == VK_IMAGE_TYPE_1D) && _mvkTexture1DAs2D)) ) { if ( !((pCreateInfo->imageType == VK_IMAGE_TYPE_2D) || ((pCreateInfo->imageType == VK_IMAGE_TYPE_1D) && mvkTreatTexture1DAs2D())) ) {
setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, multisampling can only be used with a 2D image type. Setting sample count to 1.")); setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, multisampling can only be used with a 2D image type. Setting sample count to 1."));
validSamples = VK_SAMPLE_COUNT_1_BIT; validSamples = VK_SAMPLE_COUNT_1_BIT;
} }

View File

@ -71,6 +71,9 @@ public:
/** Returns the function pointer corresponding to the named entry point, or NULL if it doesn't exist. */ /** Returns the function pointer corresponding to the named entry point, or NULL if it doesn't exist. */
PFN_vkVoidFunction getProcAddr(const char* pName); PFN_vkVoidFunction getProcAddr(const char* pName);
/** Returns the number of available physical devices. */
uint32_t getPhysicalDeviceCount() { return (uint32_t)_physicalDevices.size(); }
/** /**
* If pPhysicalDevices is null, the value of pCount is updated with the number of * If pPhysicalDevices is null, the value of pCount is updated with the number of
* physical devices supported by this instance. * physical devices supported by this instance.

View File

@ -50,7 +50,7 @@ PFN_vkVoidFunction MVKInstance::getProcAddr(const char* pName) {
VkResult MVKInstance::getPhysicalDevices(uint32_t* pCount, VkPhysicalDevice* pPhysicalDevices) { VkResult MVKInstance::getPhysicalDevices(uint32_t* pCount, VkPhysicalDevice* pPhysicalDevices) {
// Get the number of physical devices // Get the number of physical devices
uint32_t pdCnt = (uint32_t)_physicalDevices.size(); uint32_t pdCnt = getPhysicalDeviceCount();
// If properties aren't actually being requested yet, simply update the returned count // If properties aren't actually being requested yet, simply update the returned count
if ( !pPhysicalDevices ) { if ( !pPhysicalDevices ) {
@ -72,13 +72,11 @@ VkResult MVKInstance::getPhysicalDevices(uint32_t* pCount, VkPhysicalDevice* pPh
VkResult MVKInstance::getPhysicalDeviceGroups(uint32_t* pCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProps) { VkResult MVKInstance::getPhysicalDeviceGroups(uint32_t* pCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProps) {
// According to the Vulkan spec: // According to the Vulkan spec: "Every physical device *must* be in exactly one device group."
// "Every physical device *must* be in exactly one device group." // Since we don't really support this yet, we must return one group for every device.
// Since we don't really support this yet, we must return one group for every
// device.
// Get the number of physical devices // Get the number of physical devices
uint32_t pdCnt = (uint32_t)_physicalDevices.size(); uint32_t pdCnt = getPhysicalDeviceCount();
// If properties aren't actually being requested yet, simply update the returned count // If properties aren't actually being requested yet, simply update the returned count
if ( !pPhysicalDeviceGroupProps ) { if ( !pPhysicalDeviceGroupProps ) {

View File

@ -326,7 +326,7 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
} }
// Track dynamic state in _dynamicStateEnabled array // Track dynamic state in _dynamicStateEnabled array
memset(&_dynamicStateEnabled, false, sizeof(_dynamicStateEnabled)); // start with all dynamic state disabled mvkClear(&_dynamicStateEnabled); // start with all dynamic state disabled
const VkPipelineDynamicStateCreateInfo* pDS = pCreateInfo->pDynamicState; const VkPipelineDynamicStateCreateInfo* pDS = pCreateInfo->pDynamicState;
if (pDS) { if (pDS) {
for (uint32_t i = 0; i < pDS->dynamicStateCount; i++) { for (uint32_t i = 0; i < pDS->dynamicStateCount; i++) {
@ -1158,7 +1158,7 @@ void MVKGraphicsPipeline::initMVKShaderConverterContext(SPIRVToMSLConversionConf
_tessCtlPatchOutputBufferIndex = layout->getTessCtlPatchOutputBufferIndex(); _tessCtlPatchOutputBufferIndex = layout->getTessCtlPatchOutputBufferIndex();
_tessCtlLevelBufferIndex = layout->getTessCtlLevelBufferIndex(); _tessCtlLevelBufferIndex = layout->getTessCtlLevelBufferIndex();
shaderContext.options.mslOptions.texture_1D_as_2D = _mvkTexture1DAs2D; shaderContext.options.mslOptions.texture_1D_as_2D = mvkTreatTexture1DAs2D();
shaderContext.options.mslOptions.enable_point_size_builtin = isRenderingPoints(pCreateInfo, reflectData); shaderContext.options.mslOptions.enable_point_size_builtin = isRenderingPoints(pCreateInfo, reflectData);
shaderContext.options.shouldFlipVertexY = _device->_pMVKConfig->shaderConversionFlipVertexY; shaderContext.options.shouldFlipVertexY = _device->_pMVKConfig->shaderConversionFlipVertexY;
shaderContext.options.mslOptions.swizzle_texture_samples = _fullImageViewSwizzle && !getDevice()->_pMetalFeatures->nativeTextureSwizzle; shaderContext.options.mslOptions.swizzle_texture_samples = _fullImageViewSwizzle && !getDevice()->_pMetalFeatures->nativeTextureSwizzle;
@ -1351,7 +1351,7 @@ MVKMTLFunction MVKComputePipeline::getMTLFunction(const VkComputePipelineCreateI
shaderContext.options.mslOptions.swizzle_texture_samples = _fullImageViewSwizzle && !getDevice()->_pMetalFeatures->nativeTextureSwizzle; shaderContext.options.mslOptions.swizzle_texture_samples = _fullImageViewSwizzle && !getDevice()->_pMetalFeatures->nativeTextureSwizzle;
shaderContext.options.mslOptions.texture_buffer_native = _device->_pMetalFeatures->textureBuffers; shaderContext.options.mslOptions.texture_buffer_native = _device->_pMetalFeatures->textureBuffers;
shaderContext.options.mslOptions.dispatch_base = _allowsDispatchBase; shaderContext.options.mslOptions.dispatch_base = _allowsDispatchBase;
shaderContext.options.mslOptions.texture_1D_as_2D = _mvkTexture1DAs2D; shaderContext.options.mslOptions.texture_1D_as_2D = mvkTreatTexture1DAs2D();
MVKPipelineLayout* layout = (MVKPipelineLayout*)pCreateInfo->layout; MVKPipelineLayout* layout = (MVKPipelineLayout*)pCreateInfo->layout;
layout->populateShaderConverterContext(shaderContext); layout->populateShaderConverterContext(shaderContext);

View File

@ -259,7 +259,7 @@ void MVKOcclusionQueryPool::resetResults(uint32_t firstQuery, uint32_t queryCoun
} else { // Host-side reset } else { // Host-side reset
id<MTLBuffer> vizBuff = getVisibilityResultMTLBuffer(); id<MTLBuffer> vizBuff = getVisibilityResultMTLBuffer();
size_t size = std::min(lastOffset, vizBuff.length) - firstOffset; size_t size = std::min(lastOffset, vizBuff.length) - firstOffset;
memset((char *)[vizBuff contents] + firstOffset, 0, size); mvkClear((char *)[vizBuff contents] + firstOffset, size);
} }
} }

View File

@ -33,7 +33,7 @@ using namespace std;
// Returns a VkExtensionProperties struct populated with a name and version // Returns a VkExtensionProperties struct populated with a name and version
static VkExtensionProperties mvkMakeExtProps(const char* extensionName, uint32_t specVersion) { static VkExtensionProperties mvkMakeExtProps(const char* extensionName, uint32_t specVersion) {
VkExtensionProperties extProps; VkExtensionProperties extProps;
memset(extProps.extensionName, 0, sizeof(extProps.extensionName)); mvkClear(extProps.extensionName);
if (extensionName) { strcpy(extProps.extensionName, extensionName); } if (extensionName) { strcpy(extProps.extensionName, extensionName); }
extProps.specVersion = specVersion; extProps.specVersion = specVersion;
return extProps; return extProps;

View File

@ -18,6 +18,7 @@
#include "MVKLayers.h" #include "MVKLayers.h"
#include "MVKEnvironment.h" #include "MVKEnvironment.h"
#include "MVKFoundation.h"
#include "vk_mvk_moltenvk.h" #include "vk_mvk_moltenvk.h"
#include <mutex> #include <mutex>
@ -40,9 +41,9 @@ VkResult MVKLayer::getInstanceExtensionProperties(uint32_t* pCount, VkExtensionP
MVKLayer::MVKLayer() : _supportedInstanceExtensions(nullptr, true) { MVKLayer::MVKLayer() : _supportedInstanceExtensions(nullptr, true) {
// The core driver layer // The core driver layer
memset(_layerProperties.layerName, 0, sizeof(_layerProperties.layerName)); mvkClear(_layerProperties.layerName);
strcpy(_layerProperties.layerName, "MoltenVK"); strcpy(_layerProperties.layerName, "MoltenVK");
memset(_layerProperties.description, 0, sizeof(_layerProperties.description)); mvkClear(_layerProperties.description);
strcpy(_layerProperties.description, "MoltenVK driver layer"); strcpy(_layerProperties.description, "MoltenVK driver layer");
_layerProperties.specVersion = MVK_VULKAN_API_VERSION; _layerProperties.specVersion = MVK_VULKAN_API_VERSION;
_layerProperties.implementationVersion = MVK_VERSION; _layerProperties.implementationVersion = MVK_VERSION;

View File

@ -36,15 +36,18 @@ using namespace std;
#endif #endif
static uint32_t _mvkLogLevel = MVK_CONFIG_LOG_LEVEL; static uint32_t _mvkLogLevel = MVK_CONFIG_LOG_LEVEL;
// Initialize log level from environment
static bool _mvkLoggingInitialized = false; static bool _mvkLoggingInitialized = false;
__attribute__((constructor)) static void MVKInitLogging() {
if (_mvkLoggingInitialized ) { return; }
_mvkLoggingInitialized = true;
// Returns log level from environment variable.
// We do this once lazily instead of in a library constructor function to
// ensure the NSProcessInfo environment is available when called upon.
static inline uint32_t getMVKLogLevel() {
if ( !_mvkLoggingInitialized ) {
_mvkLoggingInitialized = true;
MVK_SET_FROM_ENV_OR_BUILD_INT32(_mvkLogLevel, MVK_CONFIG_LOG_LEVEL); MVK_SET_FROM_ENV_OR_BUILD_INT32(_mvkLogLevel, MVK_CONFIG_LOG_LEVEL);
} }
return _mvkLogLevel;
}
static const char* getReportingLevelString(int aslLvl) { static const char* getReportingLevelString(int aslLvl) {
switch (aslLvl) { switch (aslLvl) {
@ -99,7 +102,7 @@ void MVKBaseObject::reportMessage(MVKBaseObject* mvkObj, int aslLvl, const char*
MVKVulkanAPIObject* mvkAPIObj = mvkObj ? mvkObj->getVulkanAPIObject() : nullptr; MVKVulkanAPIObject* mvkAPIObj = mvkObj ? mvkObj->getVulkanAPIObject() : nullptr;
MVKInstance* mvkInst = mvkAPIObj ? mvkAPIObj->getInstance() : nullptr; MVKInstance* mvkInst = mvkAPIObj ? mvkAPIObj->getInstance() : nullptr;
bool hasDebugCallbacks = mvkInst && mvkInst->hasDebugCallbacks(); bool hasDebugCallbacks = mvkInst && mvkInst->hasDebugCallbacks();
bool shouldLog = (aslLvl < (_mvkLogLevel << 2)); bool shouldLog = (aslLvl < (getMVKLogLevel() << 2));
// Fail fast to avoid further unnecessary processing. // Fail fast to avoid further unnecessary processing.
if ( !(shouldLog || hasDebugCallbacks) ) { return; } if ( !(shouldLog || hasDebugCallbacks) ) { return; }

View File

@ -416,18 +416,25 @@ void mvkRemoveAllOccurances(C& container, T val) {
container.erase(remove(container.begin(), container.end(), val), container.end()); container.erase(remove(container.begin(), container.end(), val), container.end());
} }
/** If pVal is not null, clears the memory occupied by *pVal by writing zeros to all the bytes. */
template<typename T>
void mvkClear(T* pVal, size_t clearSize = sizeof(T)) { if (pVal) { memset(pVal, 0, clearSize); } }
/** If pVal is not null, overrides the const declaration, and clears the memory occupied by *pVal by writing zeros to all the bytes. */
template<typename T>
void mvkClear(const T* pVal, size_t clearSize = sizeof(T)) { mvkClear((T*)pVal, clearSize); }
/** /**
* If pSrc and pDst are not null, copies at most copySize bytes from the contents of the source * If pSrc and pDst are not null, copies at most copySize bytes from the contents of the source
* struct to the destination struct, and returns the number of bytes copied, which is the smaller * value to the destination value, and returns the number of bytes copied, which is the smaller
* of copySize and the actual size of the struct. If either pSrc or pDst are null, returns zero. * of copySize and the actual size of the struct. If either pSrc or pDst are null, returns zero.
*/ */
template<typename S> template<typename S>
size_t mvkCopyStruct(S* pDst, const S* pSrc, size_t copySize = sizeof(S)) { size_t mvkCopy(S* pDst, const S* pSrc, size_t copySize = sizeof(S)) {
size_t bytesCopied = 0; if ( !(pSrc && pDst) ) { return 0; }
if (pSrc && pDst) {
bytesCopied = std::min(copySize, sizeof(S)); size_t bytesCopied = std::min(copySize, sizeof(S));
memcpy(pDst, pSrc, bytesCopied); memcpy(pDst, pSrc, bytesCopied);
}
return bytesCopied; return bytesCopied;
} }
@ -449,7 +456,7 @@ bool mvkSetOrClear(T* pDest, const T* pSrc) {
*pDest = *pSrc; *pDest = *pSrc;
return true; return true;
} }
if (pDest) { memset(pDest, 0, sizeof(T)); } if (pDest) { mvkClear(pDest); }
return false; return false;
} }

View File

@ -31,10 +31,6 @@ class MVKBaseObject;
* which is part of the public external MoltenVK C API. * which is part of the public external MoltenVK C API.
*/ */
/** Support the MVK_CONFIG_TEXTURE_1D_AS_2D runtime environment variable. */
extern bool _mvkTexture1DAs2D;
#pragma mark - #pragma mark -
#pragma mark Support for VK_EXT_debug_report extension #pragma mark Support for VK_EXT_debug_report extension
@ -91,4 +87,7 @@ MTLTessellationPartitionMode mvkMTLTessellationPartitionModeFromSpvExecutionMode
/** Enumerates all formats that support the given features, calling a specified function for each one. */ /** Enumerates all formats that support the given features, calling a specified function for each one. */
void mvkEnumerateSupportedFormats(VkFormatProperties properties, bool any, std::function<bool(VkFormat)> func); void mvkEnumerateSupportedFormats(VkFormatProperties properties, bool any, std::function<bool(VkFormat)> func);
/** Returns whether 1D textures should be treated as Metal 2D textures with height 1. */
bool mvkTreatTexture1DAs2D();
#endif #endif

View File

@ -499,9 +499,9 @@ static uint16_t _fmtDescIndicesByMTLVertexFormats[_mtlVertexFormatCount];
static void MVKInitFormatMaps() { static void MVKInitFormatMaps() {
// Set all VkFormats and MTLPixelFormats to undefined/invalid // Set all VkFormats and MTLPixelFormats to undefined/invalid
memset(_fmtDescIndicesByVkFormatsCore, 0, sizeof(_fmtDescIndicesByVkFormatsCore)); mvkClear(_fmtDescIndicesByVkFormatsCore);
memset(_fmtDescIndicesByMTLPixelFormats, 0, sizeof(_fmtDescIndicesByMTLPixelFormats)); mvkClear(_fmtDescIndicesByMTLPixelFormats);
memset(_fmtDescIndicesByMTLVertexFormats, 0, sizeof(_fmtDescIndicesByMTLVertexFormats)); mvkClear(_fmtDescIndicesByMTLVertexFormats);
_pFmtDescIndicesByVkFormatsExt = new MVKFormatIndexByVkFormatMap(); _pFmtDescIndicesByVkFormatsExt = new MVKFormatIndexByVkFormatMap();
@ -822,7 +822,7 @@ MVK_PUBLIC_SYMBOL MTLTextureType mvkMTLTextureTypeFromVkImageType(VkImageType vk
bool isMultisample) { bool isMultisample) {
switch (vkImageType) { switch (vkImageType) {
case VK_IMAGE_TYPE_3D: return MTLTextureType3D; case VK_IMAGE_TYPE_3D: return MTLTextureType3D;
case VK_IMAGE_TYPE_1D: return (_mvkTexture1DAs2D case VK_IMAGE_TYPE_1D: return (mvkTreatTexture1DAs2D()
? mvkMTLTextureTypeFromVkImageType(VK_IMAGE_TYPE_2D, arraySize, isMultisample) ? mvkMTLTextureTypeFromVkImageType(VK_IMAGE_TYPE_2D, arraySize, isMultisample)
: (arraySize > 1 ? MTLTextureType1DArray : MTLTextureType1D)); : (arraySize > 1 ? MTLTextureType1DArray : MTLTextureType1D));
case VK_IMAGE_TYPE_2D: case VK_IMAGE_TYPE_2D:
@ -854,8 +854,8 @@ MVK_PUBLIC_SYMBOL MTLTextureType mvkMTLTextureTypeFromVkImageViewType(VkImageVie
case VK_IMAGE_VIEW_TYPE_3D: return MTLTextureType3D; case VK_IMAGE_VIEW_TYPE_3D: return MTLTextureType3D;
case VK_IMAGE_VIEW_TYPE_CUBE: return MTLTextureTypeCube; case VK_IMAGE_VIEW_TYPE_CUBE: return MTLTextureTypeCube;
case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return MTLTextureTypeCubeArray; case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return MTLTextureTypeCubeArray;
case VK_IMAGE_VIEW_TYPE_1D: return _mvkTexture1DAs2D ? mvkMTLTextureTypeFromVkImageViewType(VK_IMAGE_VIEW_TYPE_2D, isMultisample) : MTLTextureType1D; case VK_IMAGE_VIEW_TYPE_1D: return mvkTreatTexture1DAs2D() ? mvkMTLTextureTypeFromVkImageViewType(VK_IMAGE_VIEW_TYPE_2D, isMultisample) : MTLTextureType1D;
case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return _mvkTexture1DAs2D ? mvkMTLTextureTypeFromVkImageViewType(VK_IMAGE_VIEW_TYPE_2D_ARRAY, isMultisample) : MTLTextureType1DArray; case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return mvkTreatTexture1DAs2D() ? mvkMTLTextureTypeFromVkImageViewType(VK_IMAGE_VIEW_TYPE_2D_ARRAY, isMultisample) : MTLTextureType1DArray;
case VK_IMAGE_VIEW_TYPE_2D_ARRAY: case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
#if MVK_MACOS #if MVK_MACOS
@ -1450,12 +1450,24 @@ MVK_PUBLIC_SYMBOL MTLResourceOptions mvkMTLResourceOptions(MTLStorageMode mtlSto
return (mtlStorageMode << MTLResourceStorageModeShift) | (mtlCPUCacheMode << MTLResourceCPUCacheModeShift); return (mtlStorageMode << MTLResourceStorageModeShift) | (mtlCPUCacheMode << MTLResourceCPUCacheModeShift);
} }
static bool _mvkTexture1DAs2D = MVK_CONFIG_TEXTURE_1D_AS_2D;
static bool _mvkTexture1DAs2DInitialized = false;
// Returns environment variable indicating whether to use Metal 2D textures for 1D textures.
// We do this once lazily instead of in a library constructor function to
// ensure the NSProcessInfo environment is available when called upon.
bool mvkTreatTexture1DAs2D() {
if ( !_mvkTexture1DAs2DInitialized ) {
_mvkTexture1DAs2DInitialized = true;
MVK_SET_FROM_ENV_OR_BUILD_INT32(_mvkTexture1DAs2D, MVK_CONFIG_TEXTURE_1D_AS_2D);
}
return _mvkTexture1DAs2D;
}
#pragma mark - #pragma mark -
#pragma mark Library initialization #pragma mark Library initialization
bool _mvkTexture1DAs2D = MVK_CONFIG_TEXTURE_1D_AS_2D;
/** /**
* Called automatically when the framework is loaded and initialized. * Called automatically when the framework is loaded and initialized.
* *
@ -1464,12 +1476,9 @@ bool _mvkTexture1DAs2D = MVK_CONFIG_TEXTURE_1D_AS_2D;
static bool _mvkDataTypesInitialized = false; static bool _mvkDataTypesInitialized = false;
__attribute__((constructor)) static void MVKInitDataTypes() { __attribute__((constructor)) static void MVKInitDataTypes() {
if (_mvkDataTypesInitialized ) { return; } if (_mvkDataTypesInitialized ) { return; }
_mvkDataTypesInitialized = true;
MVKInitFormatMaps(); MVKInitFormatMaps();
MVK_SET_FROM_ENV_OR_BUILD_BOOL(_mvkTexture1DAs2D, MVK_CONFIG_TEXTURE_1D_AS_2D);
_mvkDataTypesInitialized = true;
} }

View File

@ -34,10 +34,10 @@ using namespace std;
// value of *pCopySize is the same as the actual size of the struct, or VK_INCOMPLETE otherwise. // value of *pCopySize is the same as the actual size of the struct, or VK_INCOMPLETE otherwise.
// If either pSrc or pDst are null, sets the value of *pCopySize to the size of the struct and returns VK_SUCCESS. // If either pSrc or pDst are null, sets the value of *pCopySize to the size of the struct and returns VK_SUCCESS.
template<typename S> template<typename S>
VkResult mvkCopyStruct(S* pDst, const S* pSrc, size_t* pCopySize) { VkResult mvkCopy(S* pDst, const S* pSrc, size_t* pCopySize) {
if (pSrc && pDst) { if (pSrc && pDst) {
size_t origSize = *pCopySize; size_t origSize = *pCopySize;
*pCopySize = mvkCopyStruct(pDst, pSrc, origSize); *pCopySize = mvkCopy(pDst, pSrc, origSize);
return (*pCopySize == origSize) ? VK_SUCCESS : VK_INCOMPLETE; return (*pCopySize == origSize) ? VK_SUCCESS : VK_INCOMPLETE;
} else { } else {
*pCopySize = sizeof(S); *pCopySize = sizeof(S);
@ -51,7 +51,7 @@ MVK_PUBLIC_SYMBOL VkResult vkGetMoltenVKConfigurationMVK(
size_t* pConfigurationSize) { size_t* pConfigurationSize) {
MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance); MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance);
return mvkCopyStruct(pConfiguration, mvkInst->getMoltenVKConfiguration(), pConfigurationSize); return mvkCopy(pConfiguration, mvkInst->getMoltenVKConfiguration(), pConfigurationSize);
} }
MVK_PUBLIC_SYMBOL VkResult vkSetMoltenVKConfigurationMVK( MVK_PUBLIC_SYMBOL VkResult vkSetMoltenVKConfigurationMVK(
@ -60,7 +60,7 @@ MVK_PUBLIC_SYMBOL VkResult vkSetMoltenVKConfigurationMVK(
size_t* pConfigurationSize) { size_t* pConfigurationSize) {
MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance); MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance);
return mvkCopyStruct((MVKConfiguration*)mvkInst->getMoltenVKConfiguration(), pConfiguration, pConfigurationSize); return mvkCopy((MVKConfiguration*)mvkInst->getMoltenVKConfiguration(), pConfiguration, pConfigurationSize);
} }
MVK_PUBLIC_SYMBOL VkResult vkGetPhysicalDeviceMetalFeaturesMVK( MVK_PUBLIC_SYMBOL VkResult vkGetPhysicalDeviceMetalFeaturesMVK(
@ -69,7 +69,7 @@ MVK_PUBLIC_SYMBOL VkResult vkGetPhysicalDeviceMetalFeaturesMVK(
size_t* pMetalFeaturesSize) { size_t* pMetalFeaturesSize) {
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice); MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
return mvkCopyStruct(pMetalFeatures, mvkPD->getMetalFeatures(), pMetalFeaturesSize); return mvkCopy(pMetalFeatures, mvkPD->getMetalFeatures(), pMetalFeaturesSize);
} }
MVK_PUBLIC_SYMBOL VkResult vkGetSwapchainPerformanceMVK( MVK_PUBLIC_SYMBOL VkResult vkGetSwapchainPerformanceMVK(
@ -79,7 +79,7 @@ MVK_PUBLIC_SYMBOL VkResult vkGetSwapchainPerformanceMVK(
size_t* pSwapchainPerfSize) { size_t* pSwapchainPerfSize) {
MVKSwapchain* mvkSC = (MVKSwapchain*)swapchain; MVKSwapchain* mvkSC = (MVKSwapchain*)swapchain;
return mvkCopyStruct(pSwapchainPerf, mvkSC->getPerformanceStatistics(), pSwapchainPerfSize); return mvkCopy(pSwapchainPerf, mvkSC->getPerformanceStatistics(), pSwapchainPerfSize);
} }
MVK_PUBLIC_SYMBOL VkResult vkGetPerformanceStatisticsMVK( MVK_PUBLIC_SYMBOL VkResult vkGetPerformanceStatisticsMVK(
@ -89,7 +89,7 @@ MVK_PUBLIC_SYMBOL VkResult vkGetPerformanceStatisticsMVK(
MVKPerformanceStatistics mvkPerf; MVKPerformanceStatistics mvkPerf;
MVKDevice::getMVKDevice(device)->getPerformanceStatistics(&mvkPerf); MVKDevice::getMVKDevice(device)->getPerformanceStatistics(&mvkPerf);
return mvkCopyStruct(pPerf, &mvkPerf, pPerfSize); return mvkCopy(pPerf, &mvkPerf, pPerfSize);
} }
MVK_PUBLIC_SYMBOL void vkGetVersionStringsMVK( MVK_PUBLIC_SYMBOL void vkGetVersionStringsMVK(

View File

@ -51,19 +51,24 @@
# define MVK_CONFIG_TRACE_VULKAN_CALLS 0 # define MVK_CONFIG_TRACE_VULKAN_CALLS 0
#endif #endif
static uint32_t _mvkTraceVulkanCalls = 0; static uint32_t _mvkTraceVulkanCalls = MVK_CONFIG_TRACE_VULKAN_CALLS;
static bool _mvkVulkanCallTracingInitialized = false; static bool _mvkVulkanCallTracingInitialized = false;
__attribute__((constructor)) static void MVKInitVulkanCallTracing() {
if (_mvkVulkanCallTracingInitialized ) { return; }
_mvkVulkanCallTracingInitialized = true;
// Returns Vulkan call trace level from environment variable.
// We do this once lazily instead of in a library constructor function to
// ensure the NSProcessInfo environment is available when called upon.
static inline uint32_t getCallTraceLevel() {
if ( !_mvkVulkanCallTracingInitialized ) {
_mvkVulkanCallTracingInitialized = true;
MVK_SET_FROM_ENV_OR_BUILD_INT32(_mvkTraceVulkanCalls, MVK_CONFIG_TRACE_VULKAN_CALLS); MVK_SET_FROM_ENV_OR_BUILD_INT32(_mvkTraceVulkanCalls, MVK_CONFIG_TRACE_VULKAN_CALLS);
} }
return _mvkTraceVulkanCalls;
}
// Optionally log start of function calls to stderr // Optionally log start of function calls to stderr
static inline uint64_t MVKTraceVulkanCallStartImpl(const char* funcName) { static inline uint64_t MVKTraceVulkanCallStartImpl(const char* funcName) {
uint64_t timestamp = 0; uint64_t timestamp = 0;
switch(_mvkTraceVulkanCalls) { switch(getCallTraceLevel()) {
case 3: // Fall through case 3: // Fall through
timestamp = mvkGetTimestamp(); timestamp = mvkGetTimestamp();
case 2: case 2:
@ -81,7 +86,7 @@ static inline uint64_t MVKTraceVulkanCallStartImpl(const char* funcName) {
// Optionally log end of function calls and timings to stderr // Optionally log end of function calls and timings to stderr
static inline void MVKTraceVulkanCallEndImpl(const char* funcName, uint64_t startTime) { static inline void MVKTraceVulkanCallEndImpl(const char* funcName, uint64_t startTime) {
switch(_mvkTraceVulkanCalls) { switch(getCallTraceLevel()) {
case 3: case 3:
fprintf(stderr, "[mvk-trace] } %s() (%.4f ms)\n", funcName, mvkGetElapsedMilliseconds(startTime)); fprintf(stderr, "[mvk-trace] } %s() (%.4f ms)\n", funcName, mvkGetElapsedMilliseconds(startTime));
break; break;

View File

@ -248,7 +248,7 @@
A90B2B1D1A9B6170008EE819 /* Project object */ = { A90B2B1D1A9B6170008EE819 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 1120; LastUpgradeCheck = 1130;
TargetAttributes = { TargetAttributes = {
A9FEADBC1F3517480010240E = { A9FEADBC1F3517480010240E = {
DevelopmentTeam = VU3TCKU48B; DevelopmentTeam = VU3TCKU48B;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "NO" parallelizeBuildables = "NO"

View File

@ -415,7 +415,7 @@
A9F55D25198BE6A7004EC31B /* Project object */ = { A9F55D25198BE6A7004EC31B /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 1120; LastUpgradeCheck = 1130;
ORGANIZATIONNAME = "The Brenwill Workshop Ltd."; ORGANIZATIONNAME = "The Brenwill Workshop Ltd.";
TargetAttributes = { TargetAttributes = {
A9092A8C1A81717B00051823 = { A9092A8C1A81717B00051823 = {

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1120" LastUpgradeVersion = "1130"
version = "2.0"> version = "2.0">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"