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 */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1120;
|
||||
LastUpgradeCheck = 1130;
|
||||
};
|
||||
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "API-Samples" */;
|
||||
compatibilityVersion = "Xcode 8.0";
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -234,7 +234,7 @@
|
||||
29B97313FDCFA39411CA2CEA /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1120;
|
||||
LastUpgradeCheck = 1130;
|
||||
};
|
||||
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Cube" */;
|
||||
compatibilityVersion = "Xcode 8.0";
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -265,7 +265,7 @@
|
||||
29B97313FDCFA39411CA2CEA /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1120;
|
||||
LastUpgradeCheck = 1130;
|
||||
};
|
||||
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Hologram" */;
|
||||
compatibilityVersion = "Xcode 8.0";
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -27,8 +27,12 @@ Released TBD
|
||||
- Fix image subresource sizing calculations for heap-based textures.
|
||||
- Fix `MTLHeap` memory leak in `MVKDeviceMemory`.
|
||||
- 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.
|
||||
- Support *Xcode 11.2*.
|
||||
- Support *Xcode 11.3*.
|
||||
|
||||
|
||||
|
||||
|
@ -2946,7 +2946,7 @@
|
||||
A9F55D25198BE6A7004EC31B /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1120;
|
||||
LastUpgradeCheck = 1130;
|
||||
ORGANIZATIONNAME = "The Brenwill Workshop Ltd.";
|
||||
TargetAttributes = {
|
||||
A972A7E421CEC72F0013AB25 = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -830,7 +830,7 @@
|
||||
A9F55D25198BE6A7004EC31B /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1120;
|
||||
LastUpgradeCheck = 1130;
|
||||
ORGANIZATIONNAME = "The Brenwill Workshop Ltd.";
|
||||
TargetAttributes = {
|
||||
A9B8EE091A98D796009C5A02 = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
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). */
|
||||
#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). */
|
||||
#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). */
|
||||
#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_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"
|
||||
|
||||
/**
|
||||
@ -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). */
|
||||
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 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 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. */
|
||||
|
@ -502,7 +502,7 @@ void MVKCommandEncoder::setVertexBytes(id<MTLRenderCommandEncoder> mtlEncoder,
|
||||
const void* bytes,
|
||||
NSUInteger length,
|
||||
uint32_t mtlBuffIndex) {
|
||||
if (_pDeviceMetalFeatures->dynamicMTLBuffers) {
|
||||
if (_pDeviceMetalFeatures->dynamicMTLBufferSize && length <= _pDeviceMetalFeatures->dynamicMTLBufferSize) {
|
||||
[mtlEncoder setVertexBytes: bytes length: length atIndex: mtlBuffIndex];
|
||||
} else {
|
||||
const MVKMTLBufferAllocation* mtlBuffAlloc = copyToTempMTLBufferAllocation(bytes, length);
|
||||
@ -514,7 +514,7 @@ void MVKCommandEncoder::setFragmentBytes(id<MTLRenderCommandEncoder> mtlEncoder,
|
||||
const void* bytes,
|
||||
NSUInteger length,
|
||||
uint32_t mtlBuffIndex) {
|
||||
if (_pDeviceMetalFeatures->dynamicMTLBuffers) {
|
||||
if (_pDeviceMetalFeatures->dynamicMTLBufferSize && length <= _pDeviceMetalFeatures->dynamicMTLBufferSize) {
|
||||
[mtlEncoder setFragmentBytes: bytes length: length atIndex: mtlBuffIndex];
|
||||
} else {
|
||||
const MVKMTLBufferAllocation* mtlBuffAlloc = copyToTempMTLBufferAllocation(bytes, length);
|
||||
@ -526,7 +526,7 @@ void MVKCommandEncoder::setComputeBytes(id<MTLComputeCommandEncoder> mtlEncoder,
|
||||
const void* bytes,
|
||||
NSUInteger length,
|
||||
uint32_t mtlBuffIndex) {
|
||||
if (_pDeviceMetalFeatures->dynamicMTLBuffers) {
|
||||
if (_pDeviceMetalFeatures->dynamicMTLBufferSize && length <= _pDeviceMetalFeatures->dynamicMTLBufferSize) {
|
||||
[mtlEncoder setBytes: bytes length: length atIndex: mtlBuffIndex];
|
||||
} else {
|
||||
const MVKMTLBufferAllocation* mtlBuffAlloc = copyToTempMTLBufferAllocation(bytes, length);
|
||||
|
@ -137,7 +137,7 @@ typedef struct MVKRPSKeyClearAtt_t {
|
||||
}
|
||||
|
||||
void reset() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
mvkClear(this);
|
||||
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,
|
||||
// even if the structure contains alignment gaps.
|
||||
memset(this, 0, sizeof(*this));
|
||||
mvkClear(this);
|
||||
|
||||
enabled = false,
|
||||
stencilCompareFunction = MTLCompareFunctionAlways;
|
||||
@ -233,7 +233,7 @@ typedef struct MVKMTLDepthStencilDescriptorData_t {
|
||||
MVKMTLDepthStencilDescriptorData_t() {
|
||||
// Start with all zeros to ensure memory comparisons will work,
|
||||
// even if the structure contains alignment gaps.
|
||||
memset(this, 0, sizeof(*this));
|
||||
mvkClear(this);
|
||||
disable(true, true);
|
||||
}
|
||||
|
||||
@ -276,7 +276,7 @@ typedef struct MVKImageDescriptorData_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;
|
||||
|
||||
@ -313,7 +313,7 @@ typedef struct MVKBufferDescriptorData_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;
|
||||
|
||||
|
@ -338,6 +338,8 @@ protected:
|
||||
void initProperties();
|
||||
void initGPUInfoProperties();
|
||||
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 getRecommendedMaxWorkingSetSize();
|
||||
uint64_t getCurrentAllocatedSize();
|
||||
|
@ -272,7 +272,7 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format,
|
||||
case VK_IMAGE_TYPE_1D:
|
||||
maxExt.height = 1;
|
||||
maxExt.depth = 1;
|
||||
if (_mvkTexture1DAs2D) {
|
||||
if (mvkTreatTexture1DAs2D()) {
|
||||
maxExt.width = pLimits->maxImageDimension2D;
|
||||
maxLevels = mvkMipmapLevels3D(maxExt);
|
||||
} else {
|
||||
@ -752,8 +752,8 @@ VkResult MVKPhysicalDevice::getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMe
|
||||
switch (next->sType) {
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: {
|
||||
auto* budgetProps = (VkPhysicalDeviceMemoryBudgetPropertiesEXT*)next;
|
||||
memset(budgetProps->heapBudget, 0, sizeof(budgetProps->heapBudget));
|
||||
memset(budgetProps->heapUsage, 0, sizeof(budgetProps->heapUsage));
|
||||
mvkClear(budgetProps->heapBudget);
|
||||
mvkClear(budgetProps->heapUsage);
|
||||
budgetProps->heapBudget[0] = (VkDeviceSize)getRecommendedMaxWorkingSetSize();
|
||||
budgetProps->heapUsage[0] = (VkDeviceSize)getCurrentAllocatedSize();
|
||||
if (!getHasUnifiedMemory()) {
|
||||
@ -787,11 +787,11 @@ MVKPhysicalDevice::MVKPhysicalDevice(MVKInstance* mvkInstance, id<MTLDevice> mtl
|
||||
|
||||
/** Initializes the Metal-specific physical device features of this instance. */
|
||||
void MVKPhysicalDevice::initMetalFeatures() {
|
||||
memset(&_metalFeatures, 0, sizeof(_metalFeatures)); // Start with everything cleared
|
||||
mvkClear(&_metalFeatures); // Start with everything cleared
|
||||
|
||||
_metalFeatures.maxPerStageBufferCount = 31;
|
||||
_metalFeatures.maxMTLBufferSize = (256 * MEBI);
|
||||
_metalFeatures.dynamicMTLBuffers = false;
|
||||
_metalFeatures.dynamicMTLBufferSize = 0;
|
||||
|
||||
_metalFeatures.maxPerStageSamplerCount = 16;
|
||||
_metalFeatures.maxQueryBufferSize = (64 * KIBI);
|
||||
@ -812,7 +812,7 @@ void MVKPhysicalDevice::initMetalFeatures() {
|
||||
|
||||
if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily1_v2] ) {
|
||||
_metalFeatures.mslVersionEnum = MTLLanguageVersion1_1;
|
||||
_metalFeatures.dynamicMTLBuffers = true;
|
||||
_metalFeatures.dynamicMTLBufferSize = (4 * KIBI);
|
||||
_metalFeatures.maxTextureDimension = (8 * KIBI);
|
||||
}
|
||||
|
||||
@ -881,7 +881,7 @@ void MVKPhysicalDevice::initMetalFeatures() {
|
||||
|
||||
if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily1_v2] ) {
|
||||
_metalFeatures.mslVersionEnum = MTLLanguageVersion1_2;
|
||||
_metalFeatures.dynamicMTLBuffers = true;
|
||||
_metalFeatures.dynamicMTLBufferSize = (4 * KIBI);
|
||||
_metalFeatures.shaderSpecialization = true;
|
||||
_metalFeatures.stencilViews = true;
|
||||
_metalFeatures.samplerClampToBorder = true;
|
||||
@ -979,7 +979,7 @@ bool MVKPhysicalDevice::getSupportsGPUFamily(MTLGPUFamily gpuFamily) {
|
||||
|
||||
// Initializes the physical device features of this instance.
|
||||
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.fullDrawIndexUint32 = true;
|
||||
@ -1130,7 +1130,7 @@ void MVKPhysicalDevice::initFeatures() {
|
||||
|
||||
/** Initializes the physical device properties of this instance. */
|
||||
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.driverVersion = MVK_VERSION;
|
||||
@ -1667,7 +1667,7 @@ void MVKPhysicalDevice::initGPUInfoProperties() {
|
||||
void MVKPhysicalDevice::initPipelineCacheUUID() {
|
||||
|
||||
// Clear the UUID
|
||||
memset(&_properties.pipelineCacheUUID, 0, sizeof(_properties.pipelineCacheUUID));
|
||||
mvkClear(&_properties.pipelineCacheUUID);
|
||||
|
||||
size_t uuidComponentOffset = 0;
|
||||
|
||||
@ -1749,105 +1749,110 @@ uint64_t MVKPhysicalDevice::getSpirvCrossRevision() {
|
||||
return revVal;
|
||||
}
|
||||
|
||||
/** Initializes the memory properties of this instance. */
|
||||
void MVKPhysicalDevice::setMemoryHeap(uint32_t heapIndex, VkDeviceSize heapSize, VkMemoryHeapFlags heapFlags) {
|
||||
_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:
|
||||
// - applies to both buffers and textures
|
||||
// - default mode for buffers on both iOS & macOS
|
||||
// - default mode for textures on iOS
|
||||
// - one copy of memory visible to both CPU & GPU
|
||||
// - coherent at command buffer boundaries
|
||||
// Metal Private:
|
||||
// - applies to both buffers and textures
|
||||
// - accessed only by GPU through render, compute, or BLIT operations
|
||||
// - no access by CPU
|
||||
// - always use for framebuffers and renderable textures
|
||||
// Metal Managed:
|
||||
// - applies to both buffers and textures
|
||||
// - default mode for textures on macOS
|
||||
// - two copies of each buffer or texture when discrete memory available
|
||||
// - convenience of shared mode, performance of private mode
|
||||
// - on unified systems behaves like shared memory and has only one copy of content
|
||||
// - when writing, use:
|
||||
// - buffer didModifyRange:
|
||||
// - texture replaceRegion:
|
||||
// - when reading, use:
|
||||
// - encoder synchronizeResource: followed by
|
||||
// - cmdbuff waitUntilCompleted (or completion handler)
|
||||
// - buffer/texture getBytes:
|
||||
// Metal Memoryless:
|
||||
// - applies only to textures used as transient render targets
|
||||
// - only available with TBDR devices (i.e. on iOS)
|
||||
// - no device memory is reserved at all
|
||||
// - storage comes from tile memory
|
||||
// - contents are undefined after rendering
|
||||
// - use for temporary renderable textures
|
||||
void MVKPhysicalDevice::initMemoryProperties() {
|
||||
|
||||
// Metal Shared:
|
||||
// - applies to both buffers and textures
|
||||
// - default mode for buffers on both iOS & macOS
|
||||
// - default mode for textures on iOS
|
||||
// - one copy of memory visible to both CPU & GPU
|
||||
// - coherent at command buffer boundaries
|
||||
// Metal Private:
|
||||
// - applies to both buffers and textures
|
||||
// - accessed only by GPU through render, compute, or BLIT operations
|
||||
// - no access by CPU
|
||||
// - always use for framebuffers and renderable textures
|
||||
// Metal Managed:
|
||||
// - applies to both buffers and textures
|
||||
// - default mode for textures on macOS
|
||||
// - two copies of each buffer or texture when discrete memory available
|
||||
// - convenience of shared mode, performance of private mode
|
||||
// - on unified systems behaves like shared memory and has only one copy of content
|
||||
// - when writing, use:
|
||||
// - buffer didModifyRange:
|
||||
// - texture replaceRegion:
|
||||
// - when reading, use:
|
||||
// - encoder synchronizeResource: followed by
|
||||
// - cmdbuff waitUntilCompleted (or completion handler)
|
||||
// - buffer/texture getBytes:
|
||||
// Metal Memoryless:
|
||||
// - applies only to textures used as transient render targets
|
||||
// - only available with TBDR devices (i.e. on iOS)
|
||||
// - no device memory is reserved at all
|
||||
// - storage comes from tile memory
|
||||
// - contents are undefined after rendering
|
||||
// - use for temporary renderable textures
|
||||
mvkClear(&_memoryProperties); // Start with everything cleared
|
||||
|
||||
_memoryProperties = (VkPhysicalDeviceMemoryProperties){
|
||||
.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
|
||||
_memoryProperties.memoryTypeCount = 3;
|
||||
_privateMemoryTypes = 0x1; // Private only
|
||||
_lazilyAllocatedMemoryTypes = 0x0; // Not supported on macOS
|
||||
_hostCoherentMemoryTypes = 0x4; // Shared only
|
||||
_hostVisibleMemoryTypes = 0x6; // Shared & managed
|
||||
_allMemoryTypes = 0x7; // Private, shared, & managed
|
||||
managedBit = 1 << typeIdx;
|
||||
setMemoryType(typeIdx, mainHeapIdx, MVK_VK_MEMORY_TYPE_METAL_MANAGED);
|
||||
typeIdx++;
|
||||
#endif
|
||||
|
||||
// Memoryless storage
|
||||
uint32_t memlessBit = 0;
|
||||
#if MVK_IOS
|
||||
_memoryProperties.memoryTypeCount = 2; // Managed storage not available on iOS
|
||||
_privateMemoryTypes = 0x1; // Private only
|
||||
_lazilyAllocatedMemoryTypes = 0x0; // Not supported on this version
|
||||
_hostCoherentMemoryTypes = 0x2; // Shared only
|
||||
_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
|
||||
if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily1_v3]) {
|
||||
memlessBit = 1 << typeIdx;
|
||||
setMemoryType(typeIdx, mainHeapIdx, MVK_VK_MEMORY_TYPE_METAL_MEMORYLESS);
|
||||
typeIdx++;
|
||||
}
|
||||
#endif
|
||||
|
||||
_memoryProperties.memoryTypeCount = typeIdx;
|
||||
|
||||
_privateMemoryTypes = privateBit | memlessBit;
|
||||
_hostVisibleMemoryTypes = sharedBit | managedBit;
|
||||
_hostCoherentMemoryTypes = sharedBit;
|
||||
_lazilyAllocatedMemoryTypes = memlessBit;
|
||||
_allMemoryTypes = privateBit | sharedBit | managedBit | memlessBit;
|
||||
}
|
||||
|
||||
bool MVKPhysicalDevice::getHasUnifiedMemory() {
|
||||
@ -1855,21 +1860,20 @@ bool MVKPhysicalDevice::getHasUnifiedMemory() {
|
||||
return true;
|
||||
#endif
|
||||
#if MVK_MACOS
|
||||
return [_mtlDevice respondsToSelector: @selector(hasUnifiedMemory)] && _mtlDevice.hasUnifiedMemory;
|
||||
return (([_mtlDevice respondsToSelector: @selector(hasUnifiedMemory)] && _mtlDevice.hasUnifiedMemory)
|
||||
|| _mtlDevice.isLowPower
|
||||
|| getInstance()->getPhysicalDeviceCount() == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t MVKPhysicalDevice::getVRAMSize() {
|
||||
#if MVK_IOS
|
||||
// All iOS devices are UMA, so return the system memory size.
|
||||
return mvkGetSystemMemorySize();
|
||||
#endif
|
||||
#if MVK_MACOS
|
||||
if (getHasUnifiedMemory()) { return mvkGetSystemMemorySize(); }
|
||||
// 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).
|
||||
return getRecommendedMaxWorkingSetSize();
|
||||
#endif
|
||||
if (getHasUnifiedMemory()) {
|
||||
return mvkGetSystemMemorySize();
|
||||
} else {
|
||||
// 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).
|
||||
return getRecommendedMaxWorkingSetSize();
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t MVKPhysicalDevice::getRecommendedMaxWorkingSetSize() {
|
||||
@ -2050,7 +2054,7 @@ void MVKDevice::getDescriptorSetLayoutSupport(const VkDescriptorSetLayoutCreateI
|
||||
}
|
||||
|
||||
VkResult MVKDevice::getDeviceGroupPresentCapabilities(VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
|
||||
memset(pDeviceGroupPresentCapabilities->presentMask, 0, sizeof(pDeviceGroupPresentCapabilities->presentMask));
|
||||
mvkClear(pDeviceGroupPresentCapabilities->presentMask);
|
||||
pDeviceGroupPresentCapabilities->presentMask[0] = 0x1;
|
||||
|
||||
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) {
|
||||
|
||||
// Start with all features disabled
|
||||
memset((void*)&_enabledFeatures, 0, sizeof(_enabledFeatures));
|
||||
memset((void*)&_enabledStorage16Features, 0, sizeof(_enabledStorage16Features));
|
||||
memset((void*)&_enabledStorage8Features, 0, sizeof(_enabledStorage8Features));
|
||||
memset((void*)&_enabledF16I8Features, 0, sizeof(_enabledF16I8Features));
|
||||
memset((void*)&_enabledUBOLayoutFeatures, 0, sizeof(_enabledUBOLayoutFeatures));
|
||||
memset((void*)&_enabledVarPtrFeatures, 0, sizeof(_enabledVarPtrFeatures));
|
||||
memset((void*)&_enabledInterlockFeatures, 0, sizeof(_enabledInterlockFeatures));
|
||||
memset((void*)&_enabledHostQryResetFeatures, 0, sizeof(_enabledHostQryResetFeatures));
|
||||
memset((void*)&_enabledScalarLayoutFeatures, 0, sizeof(_enabledScalarLayoutFeatures));
|
||||
memset((void*)&_enabledTexelBuffAlignFeatures, 0, sizeof(_enabledTexelBuffAlignFeatures));
|
||||
memset((void*)&_enabledVtxAttrDivFeatures, 0, sizeof(_enabledVtxAttrDivFeatures));
|
||||
memset((void*)&_enabledPortabilityFeatures, 0, sizeof(_enabledPortabilityFeatures));
|
||||
mvkClear(&_enabledFeatures);
|
||||
mvkClear(&_enabledStorage16Features);
|
||||
mvkClear(&_enabledStorage8Features);
|
||||
mvkClear(&_enabledF16I8Features);
|
||||
mvkClear(&_enabledUBOLayoutFeatures);
|
||||
mvkClear(&_enabledVarPtrFeatures);
|
||||
mvkClear(&_enabledInterlockFeatures);
|
||||
mvkClear(&_enabledHostQryResetFeatures);
|
||||
mvkClear(&_enabledScalarLayoutFeatures);
|
||||
mvkClear(&_enabledTexelBuffAlignFeatures);
|
||||
mvkClear(&_enabledVtxAttrDivFeatures);
|
||||
mvkClear(&_enabledPortabilityFeatures);
|
||||
|
||||
// Fetch the available physical device features.
|
||||
VkPhysicalDevicePortabilitySubsetFeaturesEXTX pdPortabilityFeatures;
|
||||
|
@ -231,7 +231,9 @@ bool MVKImage::validateUseTexelBuffer() {
|
||||
useTexelBuffer = useTexelBuffer && _deviceMemory && _deviceMemory->_mtlBuffer; // Buffer is available to overlay
|
||||
|
||||
#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
|
||||
|
||||
return useTexelBuffer;
|
||||
@ -476,12 +478,12 @@ MTLTextureDescriptor* MVKImage::newMTLTextureDescriptor() {
|
||||
MTLStorageMode MVKImage::getMTLStorageMode() {
|
||||
if ( !_deviceMemory ) return MTLStorageModePrivate;
|
||||
|
||||
// For macOS, textures cannot use Shared storage mode, so change to Managed storage mode.
|
||||
MTLStorageMode stgMode = _deviceMemory->getMTLStorageMode();
|
||||
|
||||
if (_ioSurface && stgMode == MTLStorageModePrivate) { stgMode = MTLStorageModeShared; }
|
||||
|
||||
#if MVK_MACOS
|
||||
// For macOS, textures cannot use Shared storage mode, so change to Managed storage mode.
|
||||
if (stgMode == MTLStorageModeShared) { stgMode = MTLStorageModeManaged; }
|
||||
#endif
|
||||
return stgMode;
|
||||
@ -660,7 +662,7 @@ VkSampleCountFlagBits MVKImage::validateSamples(const VkImageCreateInfo* pCreate
|
||||
if (validSamples == VK_SAMPLE_COUNT_1_BIT) { return validSamples; }
|
||||
|
||||
// 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."));
|
||||
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. */
|
||||
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
|
||||
* 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) {
|
||||
|
||||
// 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 ( !pPhysicalDevices ) {
|
||||
@ -72,13 +72,11 @@ VkResult MVKInstance::getPhysicalDevices(uint32_t* pCount, VkPhysicalDevice* pPh
|
||||
|
||||
VkResult MVKInstance::getPhysicalDeviceGroups(uint32_t* pCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProps) {
|
||||
|
||||
// According to the Vulkan spec:
|
||||
// "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.
|
||||
// According to the Vulkan spec: "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.
|
||||
|
||||
// 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 ( !pPhysicalDeviceGroupProps ) {
|
||||
|
@ -326,7 +326,7 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
|
||||
}
|
||||
|
||||
// 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;
|
||||
if (pDS) {
|
||||
for (uint32_t i = 0; i < pDS->dynamicStateCount; i++) {
|
||||
@ -1158,7 +1158,7 @@ void MVKGraphicsPipeline::initMVKShaderConverterContext(SPIRVToMSLConversionConf
|
||||
_tessCtlPatchOutputBufferIndex = layout->getTessCtlPatchOutputBufferIndex();
|
||||
_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.shouldFlipVertexY = _device->_pMVKConfig->shaderConversionFlipVertexY;
|
||||
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.texture_buffer_native = _device->_pMetalFeatures->textureBuffers;
|
||||
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;
|
||||
layout->populateShaderConverterContext(shaderContext);
|
||||
|
@ -259,7 +259,7 @@ void MVKOcclusionQueryPool::resetResults(uint32_t firstQuery, uint32_t queryCoun
|
||||
} else { // Host-side reset
|
||||
id<MTLBuffer> vizBuff = getVisibilityResultMTLBuffer();
|
||||
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
|
||||
static VkExtensionProperties mvkMakeExtProps(const char* extensionName, uint32_t specVersion) {
|
||||
VkExtensionProperties extProps;
|
||||
memset(extProps.extensionName, 0, sizeof(extProps.extensionName));
|
||||
mvkClear(extProps.extensionName);
|
||||
if (extensionName) { strcpy(extProps.extensionName, extensionName); }
|
||||
extProps.specVersion = specVersion;
|
||||
return extProps;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "MVKLayers.h"
|
||||
#include "MVKEnvironment.h"
|
||||
#include "MVKFoundation.h"
|
||||
#include "vk_mvk_moltenvk.h"
|
||||
#include <mutex>
|
||||
|
||||
@ -40,9 +41,9 @@ VkResult MVKLayer::getInstanceExtensionProperties(uint32_t* pCount, VkExtensionP
|
||||
MVKLayer::MVKLayer() : _supportedInstanceExtensions(nullptr, true) {
|
||||
|
||||
// The core driver layer
|
||||
memset(_layerProperties.layerName, 0, sizeof(_layerProperties.layerName));
|
||||
mvkClear(_layerProperties.layerName);
|
||||
strcpy(_layerProperties.layerName, "MoltenVK");
|
||||
memset(_layerProperties.description, 0, sizeof(_layerProperties.description));
|
||||
mvkClear(_layerProperties.description);
|
||||
strcpy(_layerProperties.description, "MoltenVK driver layer");
|
||||
_layerProperties.specVersion = MVK_VULKAN_API_VERSION;
|
||||
_layerProperties.implementationVersion = MVK_VERSION;
|
||||
|
@ -36,14 +36,17 @@ using namespace std;
|
||||
#endif
|
||||
|
||||
static uint32_t _mvkLogLevel = MVK_CONFIG_LOG_LEVEL;
|
||||
|
||||
// Initialize log level from environment
|
||||
static bool _mvkLoggingInitialized = false;
|
||||
__attribute__((constructor)) static void MVKInitLogging() {
|
||||
if (_mvkLoggingInitialized ) { return; }
|
||||
_mvkLoggingInitialized = true;
|
||||
|
||||
MVK_SET_FROM_ENV_OR_BUILD_INT32(_mvkLogLevel, MVK_CONFIG_LOG_LEVEL);
|
||||
// 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);
|
||||
}
|
||||
return _mvkLogLevel;
|
||||
}
|
||||
|
||||
static const char* getReportingLevelString(int aslLvl) {
|
||||
@ -99,7 +102,7 @@ void MVKBaseObject::reportMessage(MVKBaseObject* mvkObj, int aslLvl, const char*
|
||||
MVKVulkanAPIObject* mvkAPIObj = mvkObj ? mvkObj->getVulkanAPIObject() : nullptr;
|
||||
MVKInstance* mvkInst = mvkAPIObj ? mvkAPIObj->getInstance() : nullptr;
|
||||
bool hasDebugCallbacks = mvkInst && mvkInst->hasDebugCallbacks();
|
||||
bool shouldLog = (aslLvl < (_mvkLogLevel << 2));
|
||||
bool shouldLog = (aslLvl < (getMVKLogLevel() << 2));
|
||||
|
||||
// Fail fast to avoid further unnecessary processing.
|
||||
if ( !(shouldLog || hasDebugCallbacks) ) { return; }
|
||||
|
@ -416,18 +416,25 @@ void mvkRemoveAllOccurances(C& container, T val) {
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
template<typename S>
|
||||
size_t mvkCopyStruct(S* pDst, const S* pSrc, size_t copySize = sizeof(S)) {
|
||||
size_t bytesCopied = 0;
|
||||
if (pSrc && pDst) {
|
||||
bytesCopied = std::min(copySize, sizeof(S));
|
||||
memcpy(pDst, pSrc, bytesCopied);
|
||||
}
|
||||
size_t mvkCopy(S* pDst, const S* pSrc, size_t copySize = sizeof(S)) {
|
||||
if ( !(pSrc && pDst) ) { return 0; }
|
||||
|
||||
size_t bytesCopied = std::min(copySize, sizeof(S));
|
||||
memcpy(pDst, pSrc, bytesCopied);
|
||||
return bytesCopied;
|
||||
}
|
||||
|
||||
@ -449,7 +456,7 @@ bool mvkSetOrClear(T* pDest, const T* pSrc) {
|
||||
*pDest = *pSrc;
|
||||
return true;
|
||||
}
|
||||
if (pDest) { memset(pDest, 0, sizeof(T)); }
|
||||
if (pDest) { mvkClear(pDest); }
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -31,10 +31,6 @@ class MVKBaseObject;
|
||||
* 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 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. */
|
||||
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
|
||||
|
@ -499,9 +499,9 @@ static uint16_t _fmtDescIndicesByMTLVertexFormats[_mtlVertexFormatCount];
|
||||
static void MVKInitFormatMaps() {
|
||||
|
||||
// Set all VkFormats and MTLPixelFormats to undefined/invalid
|
||||
memset(_fmtDescIndicesByVkFormatsCore, 0, sizeof(_fmtDescIndicesByVkFormatsCore));
|
||||
memset(_fmtDescIndicesByMTLPixelFormats, 0, sizeof(_fmtDescIndicesByMTLPixelFormats));
|
||||
memset(_fmtDescIndicesByMTLVertexFormats, 0, sizeof(_fmtDescIndicesByMTLVertexFormats));
|
||||
mvkClear(_fmtDescIndicesByVkFormatsCore);
|
||||
mvkClear(_fmtDescIndicesByMTLPixelFormats);
|
||||
mvkClear(_fmtDescIndicesByMTLVertexFormats);
|
||||
|
||||
_pFmtDescIndicesByVkFormatsExt = new MVKFormatIndexByVkFormatMap();
|
||||
|
||||
@ -822,7 +822,7 @@ MVK_PUBLIC_SYMBOL MTLTextureType mvkMTLTextureTypeFromVkImageType(VkImageType vk
|
||||
bool isMultisample) {
|
||||
switch (vkImageType) {
|
||||
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)
|
||||
: (arraySize > 1 ? MTLTextureType1DArray : MTLTextureType1D));
|
||||
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_CUBE: return MTLTextureTypeCube;
|
||||
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_ARRAY: return _mvkTexture1DAs2D ? mvkMTLTextureTypeFromVkImageViewType(VK_IMAGE_VIEW_TYPE_2D_ARRAY, isMultisample) : MTLTextureType1DArray;
|
||||
case VK_IMAGE_VIEW_TYPE_1D: return mvkTreatTexture1DAs2D() ? mvkMTLTextureTypeFromVkImageViewType(VK_IMAGE_VIEW_TYPE_2D, isMultisample) : MTLTextureType1D;
|
||||
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:
|
||||
#if MVK_MACOS
|
||||
@ -1450,12 +1450,24 @@ MVK_PUBLIC_SYMBOL MTLResourceOptions mvkMTLResourceOptions(MTLStorageMode mtlSto
|
||||
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 Library initialization
|
||||
|
||||
bool _mvkTexture1DAs2D = MVK_CONFIG_TEXTURE_1D_AS_2D;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
__attribute__((constructor)) static void MVKInitDataTypes() {
|
||||
if (_mvkDataTypesInitialized ) { return; }
|
||||
_mvkDataTypesInitialized = true;
|
||||
|
||||
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.
|
||||
// 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>
|
||||
VkResult mvkCopyStruct(S* pDst, const S* pSrc, size_t* pCopySize) {
|
||||
VkResult mvkCopy(S* pDst, const S* pSrc, size_t* pCopySize) {
|
||||
if (pSrc && pDst) {
|
||||
size_t origSize = *pCopySize;
|
||||
*pCopySize = mvkCopyStruct(pDst, pSrc, origSize);
|
||||
*pCopySize = mvkCopy(pDst, pSrc, origSize);
|
||||
return (*pCopySize == origSize) ? VK_SUCCESS : VK_INCOMPLETE;
|
||||
} else {
|
||||
*pCopySize = sizeof(S);
|
||||
@ -51,7 +51,7 @@ MVK_PUBLIC_SYMBOL VkResult vkGetMoltenVKConfigurationMVK(
|
||||
size_t* pConfigurationSize) {
|
||||
|
||||
MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance);
|
||||
return mvkCopyStruct(pConfiguration, mvkInst->getMoltenVKConfiguration(), pConfigurationSize);
|
||||
return mvkCopy(pConfiguration, mvkInst->getMoltenVKConfiguration(), pConfigurationSize);
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL VkResult vkSetMoltenVKConfigurationMVK(
|
||||
@ -60,7 +60,7 @@ MVK_PUBLIC_SYMBOL VkResult vkSetMoltenVKConfigurationMVK(
|
||||
size_t* pConfigurationSize) {
|
||||
|
||||
MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance);
|
||||
return mvkCopyStruct((MVKConfiguration*)mvkInst->getMoltenVKConfiguration(), pConfiguration, pConfigurationSize);
|
||||
return mvkCopy((MVKConfiguration*)mvkInst->getMoltenVKConfiguration(), pConfiguration, pConfigurationSize);
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL VkResult vkGetPhysicalDeviceMetalFeaturesMVK(
|
||||
@ -69,7 +69,7 @@ MVK_PUBLIC_SYMBOL VkResult vkGetPhysicalDeviceMetalFeaturesMVK(
|
||||
size_t* pMetalFeaturesSize) {
|
||||
|
||||
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
|
||||
return mvkCopyStruct(pMetalFeatures, mvkPD->getMetalFeatures(), pMetalFeaturesSize);
|
||||
return mvkCopy(pMetalFeatures, mvkPD->getMetalFeatures(), pMetalFeaturesSize);
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL VkResult vkGetSwapchainPerformanceMVK(
|
||||
@ -79,7 +79,7 @@ MVK_PUBLIC_SYMBOL VkResult vkGetSwapchainPerformanceMVK(
|
||||
size_t* pSwapchainPerfSize) {
|
||||
|
||||
MVKSwapchain* mvkSC = (MVKSwapchain*)swapchain;
|
||||
return mvkCopyStruct(pSwapchainPerf, mvkSC->getPerformanceStatistics(), pSwapchainPerfSize);
|
||||
return mvkCopy(pSwapchainPerf, mvkSC->getPerformanceStatistics(), pSwapchainPerfSize);
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL VkResult vkGetPerformanceStatisticsMVK(
|
||||
@ -89,7 +89,7 @@ MVK_PUBLIC_SYMBOL VkResult vkGetPerformanceStatisticsMVK(
|
||||
|
||||
MVKPerformanceStatistics mvkPerf;
|
||||
MVKDevice::getMVKDevice(device)->getPerformanceStatistics(&mvkPerf);
|
||||
return mvkCopyStruct(pPerf, &mvkPerf, pPerfSize);
|
||||
return mvkCopy(pPerf, &mvkPerf, pPerfSize);
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL void vkGetVersionStringsMVK(
|
||||
|
@ -51,19 +51,24 @@
|
||||
# define MVK_CONFIG_TRACE_VULKAN_CALLS 0
|
||||
#endif
|
||||
|
||||
static uint32_t _mvkTraceVulkanCalls = 0;
|
||||
static uint32_t _mvkTraceVulkanCalls = MVK_CONFIG_TRACE_VULKAN_CALLS;
|
||||
static bool _mvkVulkanCallTracingInitialized = false;
|
||||
__attribute__((constructor)) static void MVKInitVulkanCallTracing() {
|
||||
if (_mvkVulkanCallTracingInitialized ) { return; }
|
||||
_mvkVulkanCallTracingInitialized = true;
|
||||
|
||||
MVK_SET_FROM_ENV_OR_BUILD_INT32(_mvkTraceVulkanCalls, MVK_CONFIG_TRACE_VULKAN_CALLS);
|
||||
// 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);
|
||||
}
|
||||
return _mvkTraceVulkanCalls;
|
||||
}
|
||||
|
||||
// Optionally log start of function calls to stderr
|
||||
static inline uint64_t MVKTraceVulkanCallStartImpl(const char* funcName) {
|
||||
uint64_t timestamp = 0;
|
||||
switch(_mvkTraceVulkanCalls) {
|
||||
switch(getCallTraceLevel()) {
|
||||
case 3: // Fall through
|
||||
timestamp = mvkGetTimestamp();
|
||||
case 2:
|
||||
@ -81,7 +86,7 @@ static inline uint64_t MVKTraceVulkanCallStartImpl(const char* funcName) {
|
||||
|
||||
// Optionally log end of function calls and timings to stderr
|
||||
static inline void MVKTraceVulkanCallEndImpl(const char* funcName, uint64_t startTime) {
|
||||
switch(_mvkTraceVulkanCalls) {
|
||||
switch(getCallTraceLevel()) {
|
||||
case 3:
|
||||
fprintf(stderr, "[mvk-trace] } %s() (%.4f ms)\n", funcName, mvkGetElapsedMilliseconds(startTime));
|
||||
break;
|
||||
|
@ -248,7 +248,7 @@
|
||||
A90B2B1D1A9B6170008EE819 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1120;
|
||||
LastUpgradeCheck = 1130;
|
||||
TargetAttributes = {
|
||||
A9FEADBC1F3517480010240E = {
|
||||
DevelopmentTeam = VU3TCKU48B;
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "NO"
|
||||
|
@ -415,7 +415,7 @@
|
||||
A9F55D25198BE6A7004EC31B /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1120;
|
||||
LastUpgradeCheck = 1130;
|
||||
ORGANIZATIONNAME = "The Brenwill Workshop Ltd.";
|
||||
TargetAttributes = {
|
||||
A9092A8C1A81717B00051823 = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1120"
|
||||
LastUpgradeVersion = "1130"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
Loading…
x
Reference in New Issue
Block a user