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:
commit
ef8575f219
@ -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";
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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";
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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";
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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*.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 = {
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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 = {
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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. */
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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 ) {
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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; }
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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 = {
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user