Merge pull request #588 from billhollings/master
Add support for the VK_EXT_debug_report extension
diff --git a/Common/MVKLogging.cpp b/Common/MVKLogging.cpp
deleted file mode 100644
index 0b53aee..0000000
--- a/Common/MVKLogging.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * MVKLogging.cpp
- *
- * Copyright (c) 2014-2019 The Brenwill Workshop Ltd. (http://www.brenwill.com)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "MVKLogging.h"
-
-
-// The logging level
-// 0 = None
-// 1 = Errors only
-// 2 = All
-#ifndef MVK_CONFIG_LOG_LEVEL
-# define MVK_CONFIG_LOG_LEVEL 2
-#endif
-
-static uint32_t _mvkLogLevel = MVK_CONFIG_LOG_LEVEL;
-
-void MVKLogImplV(bool logToPrintf, bool /*logToASL*/, int aslLvl, const char* lvlStr, const char* format, va_list args) {
-
- if (aslLvl > (_mvkLogLevel << 2)) { return; }
-
- // Combine the level and format string
- char lvlFmt[strlen(lvlStr) + strlen(format) + 5];
- sprintf(lvlFmt, "[%s] %s\n", lvlStr, format);
-
- if (logToPrintf) { vfprintf(stderr, lvlFmt, args); }
-// if (logToASL) { asl_vlog(NULL, NULL, aslLvl, lvlFmt, args); } // Multi-threaded ASL support requires a separate ASL client to be opened per thread!
-}
-
-void MVKLogImpl(bool logToPrintf, bool logToASL, int aslLvl, const char* lvlStr, const char* format, ...) {
- va_list args;
- va_start(args, format);
- MVKLogImplV(logToPrintf, logToASL, aslLvl, lvlStr, format, args);
- va_end(args);
-}
-
-#ifdef MVK_ENV_LOG_LEVEL
-#include "MVKOSExtensions.h"
-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);
-}
-#endif
diff --git a/Common/MVKLogging.h b/Common/MVKLogging.h
index 0fc70c4..ddf2933 100644
--- a/Common/MVKLogging.h
+++ b/Common/MVKLogging.h
@@ -23,7 +23,6 @@
extern "C" {
#endif // __cplusplus
-#include "MVKCommonEnvironment.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
@@ -93,12 +92,6 @@
* from the compiled code, thus eliminating both the memory and CPU overhead that the assertion
* calls would add
*
- * A special MVKAssertUnimplemented(name) and MVKAssertCUnimplemented(name) assertion functions
- * are provided to conveniently raise an assertion exception when some expected functionality
- * is unimplemented. Either functions may be used as a temporary placeholder for functionalty
- * that will be added at a later time. MVKAssertUnimplemented(name) may also be used in a method
- * body by a superclass that requires each subclass to implement that method
- *
* Although you can directly edit this file to turn on or off the switches below, the preferred
* technique is to set these switches via the compiler build setting GCC_PREPROCESSOR_DEFINITIONS
* in your build configuration.
@@ -172,22 +165,10 @@
# define MVKLogDebugIf(cond, fmt, ...)
#endif
-/**
- * Combine the specified log level and format string, then log
- * the specified args to one or both of ASL and printf.
- */
-void MVKLogImplV(bool logToPrintf, bool logToASL, int aslLvl, const char* lvlStr, const char* format, va_list args) __printflike(5, 0);
-
-/**
- * Combine the specified log level and format string, then log
- * the specified args to one or both of ASL and printf.
- */
-void MVKLogImpl(bool logToPrintf, bool logToASL, int aslLvl, const char* lvlStr, const char* format, ...) __printflike(5, 6);
-
-#define MVKLogErrorImpl(fmt, ...) MVKLogImpl(true, !(MVK_DEBUG), ASL_LEVEL_ERR, "***MoltenVK ERROR***", fmt, ##__VA_ARGS__)
-#define MVKLogInfoImpl(fmt, ...) MVKLogImpl(true, !(MVK_DEBUG), ASL_LEVEL_NOTICE, "mvk-info", fmt, ##__VA_ARGS__)
-#define MVKLogTraceImpl(fmt, ...) MVKLogImpl(true, !(MVK_DEBUG), ASL_LEVEL_DEBUG, "mvk-trace", fmt, ##__VA_ARGS__)
-#define MVKLogDebugImpl(fmt, ...) MVKLogImpl(true, !(MVK_DEBUG), ASL_LEVEL_DEBUG, "mvk-debug", fmt, ##__VA_ARGS__)
+#define MVKLogErrorImpl(fmt, ...) reportMessage(ASL_LEVEL_ERR, fmt, ##__VA_ARGS__)
+#define MVKLogInfoImpl(fmt, ...) reportMessage(ASL_LEVEL_NOTICE, fmt, ##__VA_ARGS__)
+#define MVKLogTraceImpl(fmt, ...) reportMessage(ASL_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
+#define MVKLogDebugImpl(fmt, ...) reportMessage(ASL_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
// Assertions
#ifdef NS_BLOCK_ASSERTIONS
@@ -203,8 +184,6 @@
assert(!isErr || MVK_BLOCK_ASSERTIONS); \
} while(0)
-#define MVKAssertUnimplemented(name) MVKAssert(false, "%s is not implemented!", name)
-
// Use this macro to open a break-point programmatically.
#ifndef MVK_DEBUGGER
# define MVK_DEBUGGER() { kill( getpid(), SIGINT ) ; }
diff --git a/Common/MVKOSExtensions.mm b/Common/MVKOSExtensions.mm
index 698393c..7759e48 100644
--- a/Common/MVKOSExtensions.mm
+++ b/Common/MVKOSExtensions.mm
@@ -18,7 +18,6 @@
#include "MVKOSExtensions.h"
-#include "MVKLogging.h"
#include <mach/mach_time.h>
#import <Foundation/Foundation.h>
@@ -51,10 +50,8 @@
return (double)(endTimestamp - startTimestamp) * _mvkTimestampPeriod / 1e6;
}
-/**
- * Initialize timestamping capabilities on app startup.
- * Called automatically when the framework is loaded and initialized.
- */
+// Initialize timestamping capabilities on app startup.
+//Called automatically when the framework is loaded and initialized.
static bool _mvkTimestampsInitialized = false;
__attribute__((constructor)) static void MVKInitTimestamps() {
if (_mvkTimestampsInitialized ) { return; }
@@ -64,8 +61,6 @@
mach_timebase_info_data_t timebase;
mach_timebase_info(&timebase);
_mvkTimestampPeriod = (double)timebase.numer / (double)timebase.denom;
- MVKLogDebug("Initializing MoltenVK timestamping. Mach time: %llu. Time period: %d / %d = %.6f.",
- _mvkTimestampBase, timebase.numer, timebase.denom, _mvkTimestampPeriod);
}
void mvkDispatchToMainAndWait(dispatch_block_t block) {
diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md
index 47eb00d..24274e2 100644
--- a/Docs/MoltenVK_Runtime_UserGuide.md
+++ b/Docs/MoltenVK_Runtime_UserGuide.md
@@ -248,6 +248,7 @@
- `VK_KHR_swapchain`
- `VK_KHR_swapchain_mutable_format`
- `VK_KHR_variable_pointers`
+- `VK_EXT_debug_report`
- `VK_EXT_host_query_reset`
- `VK_EXT_memory_budget`
- `VK_EXT_shader_viewport_index_layer`
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index 547cb4b..9e4d059 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -18,6 +18,9 @@
Released TBD
+- Support the `VK_EXT_debug_report` extension.
+- Change log indication of error in logs from `[***MoltenVK ERROR***]` to
+ `[mvk-error]`, for consistency with other log level indications.
- Tessellation fixes:
- Don't use setVertexBytes() for passing tessellation vertex counts.
- Fix intermediate Metal renderpasses load and store actions maintaining
diff --git a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj
index 9d9e0b6..b41d81b 100644
--- a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj
+++ b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj
@@ -187,8 +187,8 @@
A9C96DD11DDC20C20053187F /* MVKMTLBufferAllocation.h in Headers */ = {isa = PBXBuildFile; fileRef = A9C96DCE1DDC20C20053187F /* MVKMTLBufferAllocation.h */; };
A9C96DD21DDC20C20053187F /* MVKMTLBufferAllocation.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9C96DCF1DDC20C20053187F /* MVKMTLBufferAllocation.mm */; };
A9C96DD31DDC20C20053187F /* MVKMTLBufferAllocation.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9C96DCF1DDC20C20053187F /* MVKMTLBufferAllocation.mm */; };
- A9E337B5220129DD00363D2A /* MVKLogging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9E337B1220129DD00363D2A /* MVKLogging.cpp */; };
- A9E337B6220129DD00363D2A /* MVKLogging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9E337B1220129DD00363D2A /* MVKLogging.cpp */; };
+ A9CEAAD5227378D400FAF779 /* mvk_datatypes.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A9CEAAD1227378D400FAF779 /* mvk_datatypes.hpp */; };
+ A9CEAAD6227378D400FAF779 /* mvk_datatypes.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A9CEAAD1227378D400FAF779 /* mvk_datatypes.hpp */; };
A9E4B7891E1D8AF10046A4CE /* MVKMTLResourceBindings.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E4B7881E1D8AF10046A4CE /* MVKMTLResourceBindings.h */; };
A9E4B78A1E1D8AF10046A4CE /* MVKMTLResourceBindings.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E4B7881E1D8AF10046A4CE /* MVKMTLResourceBindings.h */; };
A9E53DD72100B197002781DD /* MTLSamplerDescriptor+MoltenVK.m in Sources */ = {isa = PBXBuildFile; fileRef = A9E53DCD2100B197002781DD /* MTLSamplerDescriptor+MoltenVK.m */; };
@@ -370,8 +370,8 @@
A9C96DCE1DDC20C20053187F /* MVKMTLBufferAllocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKMTLBufferAllocation.h; sourceTree = "<group>"; };
A9C96DCF1DDC20C20053187F /* MVKMTLBufferAllocation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKMTLBufferAllocation.mm; sourceTree = "<group>"; };
A9CBEE011B6299D800E45FDC /* libMoltenVK.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMoltenVK.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ A9CEAAD1227378D400FAF779 /* mvk_datatypes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = mvk_datatypes.hpp; sourceTree = "<group>"; };
A9DE1083200598C500F18F80 /* icd */ = {isa = PBXFileReference; lastKnownFileType = folder; path = icd; sourceTree = "<group>"; };
- A9E337B1220129DD00363D2A /* MVKLogging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MVKLogging.cpp; sourceTree = "<group>"; };
A9E4B7881E1D8AF10046A4CE /* MVKMTLResourceBindings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKMTLResourceBindings.h; sourceTree = "<group>"; };
A9E53DCD2100B197002781DD /* MTLSamplerDescriptor+MoltenVK.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MTLSamplerDescriptor+MoltenVK.m"; sourceTree = "<group>"; };
A9E53DD02100B197002781DD /* MTLTextureDescriptor+MoltenVK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MTLTextureDescriptor+MoltenVK.h"; sourceTree = "<group>"; };
@@ -504,6 +504,7 @@
A94FB7A81C7DFB4800632CA3 /* Vulkan */ = {
isa = PBXGroup;
children = (
+ A9CEAAD1227378D400FAF779 /* mvk_datatypes.hpp */,
A94FB7A91C7DFB4800632CA3 /* mvk_datatypes.mm */,
A94FB7AC1C7DFB4800632CA3 /* vk_mvk_moltenvk.mm */,
A94FB7AD1C7DFB4800632CA3 /* vulkan.mm */,
@@ -581,7 +582,6 @@
isa = PBXGroup;
children = (
A9F0429D1FB4CF82009FCCB8 /* MVKCommonEnvironment.h */,
- A9E337B1220129DD00363D2A /* MVKLogging.cpp */,
A9F0429E1FB4CF82009FCCB8 /* MVKLogging.h */,
A9B51BD6225E986A00AC74D2 /* MVKOSExtensions.h */,
A9B51BD2225E986A00AC74D2 /* MVKOSExtensions.mm */,
@@ -672,6 +672,7 @@
A94FB7E81C7DFB4800632CA3 /* MVKDeviceMemory.h in Headers */,
A9E4B7891E1D8AF10046A4CE /* MVKMTLResourceBindings.h in Headers */,
45003E73214AD4E500E989CB /* MVKExtensions.def in Headers */,
+ A9CEAAD5227378D400FAF779 /* mvk_datatypes.hpp in Headers */,
A90C8DEA1F45354D009CB32C /* MVKCommandEncodingPool.h in Headers */,
A94FB8081C7DFB4800632CA3 /* MVKResource.h in Headers */,
A9E53DDD2100B197002781DD /* MTLTextureDescriptor+MoltenVK.h in Headers */,
@@ -737,6 +738,7 @@
A94FB7E91C7DFB4800632CA3 /* MVKDeviceMemory.h in Headers */,
A9E4B78A1E1D8AF10046A4CE /* MVKMTLResourceBindings.h in Headers */,
45003E74214AD4E600E989CB /* MVKExtensions.def in Headers */,
+ A9CEAAD6227378D400FAF779 /* mvk_datatypes.hpp in Headers */,
A90C8DEB1F45354D009CB32C /* MVKCommandEncodingPool.h in Headers */,
A94FB8091C7DFB4800632CA3 /* MVKResource.h in Headers */,
A9E53DDE2100B197002781DD /* MTLTextureDescriptor+MoltenVK.h in Headers */,
@@ -974,7 +976,6 @@
A94FB8301C7DFB4800632CA3 /* vk_mvk_moltenvk.mm in Sources */,
A94FB8161C7DFB4800632CA3 /* MVKSwapchain.mm in Sources */,
A95B7D6B1D3EE486003183D3 /* MVKCommandEncoderState.mm in Sources */,
- A9E337B5220129DD00363D2A /* MVKLogging.cpp in Sources */,
A93E83352121F0C8001FEBD4 /* MVKGPUCapture.mm in Sources */,
A9B51BD7225E986A00AC74D2 /* MVKOSExtensions.mm in Sources */,
A94FB7CE1C7DFB4800632CA3 /* MVKCommand.mm in Sources */,
@@ -1029,7 +1030,6 @@
A94FB8311C7DFB4800632CA3 /* vk_mvk_moltenvk.mm in Sources */,
A94FB8171C7DFB4800632CA3 /* MVKSwapchain.mm in Sources */,
A95B7D6C1D3EE486003183D3 /* MVKCommandEncoderState.mm in Sources */,
- A9E337B6220129DD00363D2A /* MVKLogging.cpp in Sources */,
A93E83362121F0C8001FEBD4 /* MVKGPUCapture.mm in Sources */,
A9B51BD8225E986A00AC74D2 /* MVKOSExtensions.mm in Sources */,
A94FB7CF1C7DFB4800632CA3 /* MVKCommand.mm in Sources */,
@@ -1134,7 +1134,6 @@
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
- MVK_ENV_LOG_LEVEL,
"SPIRV_CROSS_NAMESPACE_OVERRIDE=MVK_spirv_cross",
);
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
@@ -1194,10 +1193,7 @@
GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = fast;
- GCC_PREPROCESSOR_DEFINITIONS = (
- MVK_ENV_LOG_LEVEL,
- "SPIRV_CROSS_NAMESPACE_OVERRIDE=MVK_spirv_cross",
- );
+ GCC_PREPROCESSOR_DEFINITIONS = "SPIRV_CROSS_NAMESPACE_OVERRIDE=MVK_spirv_cross";
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
diff --git a/MoltenVK/MoltenVK/API/mvk_datatypes.h b/MoltenVK/MoltenVK/API/mvk_datatypes.h
index eeeef02..41cbf7a 100644
--- a/MoltenVK/MoltenVK/API/mvk_datatypes.h
+++ b/MoltenVK/MoltenVK/API/mvk_datatypes.h
@@ -299,7 +299,7 @@
*/
MTLSamplerAddressMode mvkMTLSamplerAddressModeFromVkSamplerAddressMode(VkSamplerAddressMode vkMode);
-#if MVK_MACOS
+#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
/**
* Returns the Metal MTLSamplerBorderColor corresponding to the specified Vulkan VkBorderColor,
* or returns MTLSamplerBorderColorTransparentBlack if no corresponding MTLSamplerBorderColor exists.
diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
index d236b58..381fd4e 100644
--- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
+++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
@@ -50,7 +50,7 @@
*/
#define MVK_VERSION_MAJOR 1
#define MVK_VERSION_MINOR 0
-#define MVK_VERSION_PATCH 34
+#define MVK_VERSION_PATCH 35
#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)
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdDispatch.mm b/MoltenVK/MoltenVK/Commands/MVKCmdDispatch.mm
index beaa5d9..dc03d47 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdDispatch.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdDispatch.mm
@@ -21,7 +21,7 @@
#include "MVKCommandPool.h"
#include "MVKBuffer.h"
#include "MVKFoundation.h"
-#include "mvk_datatypes.h"
+#include "mvk_datatypes.hpp"
#pragma mark -
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.h b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.h
index f31c465..da4567f 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.h
@@ -70,7 +70,7 @@
#pragma mark MVKCmdDraw
/** Vulkan command to draw vertices. */
-class MVKCmdDraw : public MVKCommand, public MVKLoadStoreOverride {
+class MVKCmdDraw : public MVKCommand, public MVKLoadStoreOverrideMixin {
public:
void setContent(uint32_t vertexCount,
@@ -94,7 +94,7 @@
#pragma mark MVKCmdDrawIndexed
/** Vulkan command to draw indexed vertices. */
-class MVKCmdDrawIndexed : public MVKCommand, public MVKLoadStoreOverride {
+class MVKCmdDrawIndexed : public MVKCommand, public MVKLoadStoreOverrideMixin {
public:
void setContent(uint32_t indexCount,
@@ -120,7 +120,7 @@
#pragma mark MVKCmdDrawIndirect
/** Vulkan command to draw vertices indirectly. */
-class MVKCmdDrawIndirect : public MVKCommand, public MVKLoadStoreOverride {
+class MVKCmdDrawIndirect : public MVKCommand, public MVKLoadStoreOverrideMixin {
public:
void setContent(VkBuffer buffer,
@@ -144,7 +144,7 @@
#pragma mark MVKCmdDrawIndexedIndirect
/** Vulkan command to draw indexed vertices indirectly. */
-class MVKCmdDrawIndexedIndirect : public MVKCommand, public MVKLoadStoreOverride {
+class MVKCmdDrawIndexedIndirect : public MVKCommand, public MVKLoadStoreOverrideMixin {
public:
void setContent(VkBuffer buffer,
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm
index f1404b1..0f986d5 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm
@@ -22,7 +22,7 @@
#include "MVKBuffer.h"
#include "MVKPipeline.h"
#include "MVKFoundation.h"
-#include "mvk_datatypes.h"
+#include "mvk_datatypes.hpp"
#pragma mark -
@@ -88,9 +88,8 @@
_storeOverride = false;
// Validate
- clearConfigurationResult();
if ((_firstInstance != 0) && !(getDevice()->_pMetalFeatures->baseVertexInstanceDrawing)) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDraw(): The current device does not support drawing with a non-zero base instance."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDraw(): The current device does not support drawing with a non-zero base instance."));
}
}
@@ -276,12 +275,11 @@
_storeOverride = false;
// Validate
- clearConfigurationResult();
if ((_firstInstance != 0) && !(getDevice()->_pMetalFeatures->baseVertexInstanceDrawing)) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexed(): The current device does not support drawing with a non-zero base instance."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexed(): The current device does not support drawing with a non-zero base instance."));
}
if ((_vertexOffset != 0) && !(getDevice()->_pMetalFeatures->baseVertexInstanceDrawing)) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexed(): The current device does not support drawing with a non-zero base vertex."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexed(): The current device does not support drawing with a non-zero base vertex."));
}
}
@@ -507,9 +505,8 @@
_storeOverride = false;
// Validate
- clearConfigurationResult();
if ( !(getDevice()->_pMetalFeatures->indirectDrawing) ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndirect(): The current device does not support indirect drawing."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndirect(): The current device does not support indirect drawing."));
}
}
@@ -749,9 +746,8 @@
_storeOverride = false;
// Validate
- clearConfigurationResult();
if ( !(getDevice()->_pMetalFeatures->indirectDrawing) ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexedIndirect(): The current device does not support indirect drawing."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexedIndirect(): The current device does not support indirect drawing."));
}
}
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm
index 3ed90af..5ce849e 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm
@@ -23,7 +23,8 @@
#include "MVKBuffer.h"
#include "MVKPipeline.h"
#include "MVKFoundation.h"
-#include "mvk_datatypes.h"
+#include "MVKEnvironment.h"
+#include "mvk_datatypes.hpp"
#pragma mark -
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdQueries.mm b/MoltenVK/MoltenVK/Commands/MVKCmdQueries.mm
index 4ff8679..a15d241 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdQueries.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdQueries.mm
@@ -37,6 +37,7 @@
#pragma mark MVKCmdBeginQuery
void MVKCmdBeginQuery::added(MVKCommandBuffer* cmdBuffer) {
+ MVKCommand::added(cmdBuffer);
_queryPool->beginQueryAddedTo(_query, cmdBuffer);
};
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h
index 4f9b3c9..519e196 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.h
@@ -33,7 +33,7 @@
#pragma mark MVKCmdBeginRenderPass
/** Vulkan command to begin a render pass. */
-class MVKCmdBeginRenderPass : public MVKCommand, public MVKLoadStoreOverride {
+class MVKCmdBeginRenderPass : public MVKCommand, public MVKLoadStoreOverrideMixin {
public:
void setContent(const VkRenderPassBeginInfo* pRenderPassBegin,
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm
index 6911aa2..3646abf 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdRenderPass.mm
@@ -22,7 +22,7 @@
#include "MVKRenderPass.h"
#include "MVKPipeline.h"
#include "MVKFoundation.h"
-#include "mvk_datatypes.h"
+#include "mvk_datatypes.hpp"
#pragma mark -
@@ -149,9 +149,8 @@
_lineWidth = lineWidth;
// Validate
- clearConfigurationResult();
if (_lineWidth != 1.0 || getDevice()->_enabledFeatures.wideLines) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdSetLineWidth(): The current device does not support wide lines."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdSetLineWidth(): The current device does not support wide lines."));
}
}
@@ -208,9 +207,8 @@
_maxDepthBounds = maxDepthBounds;
// Validate
- clearConfigurationResult();
if (getDevice()->_enabledFeatures.depthBounds) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdSetDepthBounds(): The current device does not support setting depth bounds."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdSetDepthBounds(): The current device does not support setting depth bounds."));
}
}
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm
index 56cd2a5..242a908 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm
@@ -25,7 +25,9 @@
#include "MVKFramebuffer.h"
#include "MVKRenderPass.h"
#include "MTLRenderPassDescriptor+MoltenVK.h"
-#include "mvk_datatypes.h"
+#include "MVKEnvironment.h"
+#include "MVKLogging.h"
+#include "mvk_datatypes.hpp"
#pragma mark -
@@ -58,9 +60,8 @@
}
// Validate
- clearConfigurationResult();
if ((_srcImage->getMTLTextureType() == MTLTextureType3D) != (_dstImage->getMTLTextureType() == MTLTextureType3D)) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdCopyImage(): Metal does not support copying to or from slices of a 3D texture."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdCopyImage(): Metal does not support copying to or from slices of a 3D texture."));
}
}
@@ -171,12 +172,11 @@
}
// Validate
- clearConfigurationResult();
if (_blitKey.isDepthFormat() && renderRegionCount > 0) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdBlitImage(): Scaling of depth/stencil images is not supported."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdBlitImage(): Scaling of depth/stencil images is not supported."));
}
if ( !_mtlTexBlitRenders.empty() && mvkMTLPixelFormatIsStencilFormat(_mtlPixFmt)) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdBlitImage(): Stencil image formats cannot be scaled or inverted."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdBlitImage(): Stencil image formats cannot be scaled or inverted."));
}
}
@@ -648,10 +648,9 @@
}
// Validate
- clearConfigurationResult();
if ( !_image->hasExpectedTexelSize() ) {
const char* cmdName = _toImage ? "vkCmdCopyBufferToImage" : "vkCmdCopyImageToBuffer";
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "%s(): The image is using Metal format %s as a substitute for Vulkan format %s. Since the pixel size is different, content for the image cannot be copied to or from a buffer.", cmdName, mvkMTLPixelFormatName(_image->getMTLPixelFormat()), mvkVkFormatName(_image->getVkFormat())));
+ setConfigurationResult(reportError(VK_ERROR_FORMAT_NOT_SUPPORTED, "%s(): The image is using Metal format %s as a substitute for Vulkan format %s. Since the pixel size is different, content for the image cannot be copied to or from a buffer.", cmdName, mvkMTLPixelFormatName(_image->getMTLPixelFormat()), mvkVkFormatName(_image->getVkFormat())));
}
}
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommand.h b/MoltenVK/MoltenVK/Commands/MVKCommand.h
index 0bb2ff0..ce32b91 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommand.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommand.h
@@ -37,8 +37,11 @@
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override;
+
/** Called when this command is added to a command buffer. */
- virtual void added(MVKCommandBuffer* cmdBuffer) {};
+ virtual void added(MVKCommandBuffer* cmdBuffer) { _commandBuffer = cmdBuffer; };
/** Indicates that this command has a valid configuration and can be encoded. */
inline bool canEncode() { return _configurationResult == VK_SUCCESS; }
@@ -84,18 +87,31 @@
protected:
MVKCommandTypePool<MVKCommand>* _pool;
+ MVKCommandBuffer* _commandBuffer = nullptr;
};
#pragma mark -
#pragma mark MVKCommandTypePool
+/**
+ * Static function for MVKCommandTypePool template to call to resolve getVulkanAPIObject().
+ * Needed because MVKCommandTypePool template cannot have function implementation outside
+ * the template, and MVKCommandPool is not completely defined in this header file.
+ */
+MVKVulkanAPIObject* mvkCommandTypePoolGetVulkanAPIObject(MVKCommandPool* cmdPool);
+
+
/** A pool of MVKCommand instances of a particular type. */
template <class T>
class MVKCommandTypePool : public MVKObjectPool<T> {
public:
+
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return mvkCommandTypePoolGetVulkanAPIObject(_commandPool); };
+
/** Some commands require access to the command pool to access resources. */
MVKCommandPool* getCommandPool() { return _commandPool; }
@@ -114,10 +130,16 @@
#pragma mark -
-#pragma mark MVKLoadStoreOverride
+#pragma mark MVKLoadStoreOverrideMixin
-/** Shared state with all draw commands */
-class MVKLoadStoreOverride {
+/**
+ * Shared state mixin for draw commands.
+ *
+ * As a mixin, this class should only be used as a component of multiple inheritance.
+ * Any class that inherits from this class should also inherit from MVKBaseObject.
+ * This requirement is to avoid the diamond problem of multiple inheritance.
+ */
+class MVKLoadStoreOverrideMixin {
public:
void setLoadOverride(bool loadOverride);
void setStoreOverride(bool storeOverride);
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommand.mm b/MoltenVK/MoltenVK/Commands/MVKCommand.mm
index ee43371..d05a68d 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommand.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommand.mm
@@ -27,7 +27,13 @@
// Opt 1: Leave arrays & rezs allocated in command, per current practice
// Opt 2: Allocate arrays & rezs from pools in Command pool, and return in returnToPool
-void MVKCommand::returnToPool() { _pool->returnObject(this); }
+void MVKCommand::returnToPool() {
+ clearConfigurationResult();
+ _commandBuffer = nullptr;
+ _pool->returnObject(this);
+}
+
+MVKVulkanAPIObject* MVKCommand::getVulkanAPIObject() { return _commandBuffer ? _commandBuffer->getVulkanAPIObject() : getCommandPool()->getVulkanAPIObject(); };
MVKCommandPool* MVKCommand::getCommandPool() { return _pool->getCommandPool(); }
@@ -39,13 +45,19 @@
#pragma mark -
-#pragma mark MVKLoadStoreOverride
+#pragma mark MVKCommandTypePool
-void MVKLoadStoreOverride::setLoadOverride(bool loadOverride) {
+MVKVulkanAPIObject* mvkCommandTypePoolGetVulkanAPIObject(MVKCommandPool* cmdPool) { return cmdPool->getVulkanAPIObject(); }
+
+
+#pragma mark -
+#pragma mark MVKLoadStoreOverrideMixin
+
+void MVKLoadStoreOverrideMixin::setLoadOverride(bool loadOverride) {
_loadOverride = loadOverride;
}
-void MVKLoadStoreOverride::setStoreOverride(bool storeOverride) {
+void MVKLoadStoreOverrideMixin::setStoreOverride(bool storeOverride) {
_storeOverride = storeOverride;
}
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
index 36e7061..8e2fa9b 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
@@ -19,7 +19,6 @@
#pragma once
#include "MVKDevice.h"
-#include "MVKSync.h"
#include "MVKCommand.h"
#include "MVKCommandEncoderState.h"
#include "MVKMTLBufferAllocation.h"
@@ -42,7 +41,7 @@
class MVKComputePipeline;
class MVKCmdBeginRenderPass;
class MVKCmdEndRenderPass;
-class MVKLoadStoreOverride;
+class MVKLoadStoreOverrideMixin;
typedef uint64_t MVKMTLCommandBufferID;
@@ -51,10 +50,16 @@
#pragma mark MVKCommandBuffer
/** Represents a Vulkan command pool. */
-class MVKCommandBuffer : public MVKDispatchableDeviceObject {
+class MVKCommandBuffer : public MVKDispatchableVulkanAPIObject, public MVKDeviceTrackingMixin {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT; }
+
+ /** Returns a pointer to the Vulkan instance. */
+ MVKInstance* getInstance() override { return _device->getInstance(); }
+
/** Prepares this instance to receive commands. */
VkResult begin(const VkCommandBufferBeginInfo* pBeginInfo);
@@ -73,12 +78,6 @@
/** Submit the commands in this buffer as part of the queue submission. */
void submit(MVKQueueCommandBufferSubmission* cmdBuffSubmit);
- /*** If no error has occured yet, records the specified result. */
- inline void recordResult(VkResult vkResult) { if (_recordingResult == VK_SUCCESS) { _recordingResult = vkResult; } }
-
- /** Returns the first abnormal VkResult that occured during command recording. */
- inline VkResult getRecordingResult() { return _recordingResult; }
-
/** Returns whether this command buffer can be submitted to a queue more than once. */
inline bool getIsReusable() { return _isReusable; }
@@ -113,7 +112,7 @@
void recordBindPipeline(MVKCmdBindPipeline* mvkBindPipeline);
/** Update the last recorded drawcall to determine load/store actions */
- void recordDraw(MVKLoadStoreOverride* mvkDraw);
+ void recordDraw(MVKLoadStoreOverrideMixin* mvkDraw);
/** The most recent recorded begin renderpass */
MVKCmdBeginRenderPass* _lastBeginRenderPass;
@@ -122,12 +121,12 @@
MVKCmdBindPipeline* _lastTessellationPipeline;
/** The most recent recorded multi-pass (ie, tessellation) draw */
- MVKLoadStoreOverride* _lastTessellationDraw;
+ MVKLoadStoreOverrideMixin* _lastTessellationDraw;
#pragma mark Construction
- MVKCommandBuffer(MVKDevice* device) : MVKDispatchableDeviceObject(device) {}
+ MVKCommandBuffer(MVKDevice* device) : MVKDeviceTrackingMixin(device) {}
~MVKCommandBuffer() override;
@@ -149,6 +148,7 @@
friend class MVKCommandEncoder;
friend class MVKCommandPool;
+ MVKBaseObject* getBaseObject() override { return this; };
void init(const VkCommandBufferAllocateInfo* pAllocateInfo);
bool canExecute();
bool canPrefill();
@@ -159,7 +159,6 @@
MVKCommand* _tail = nullptr;
uint32_t _commandCount;
std::atomic_flag _isExecutingNonConcurrently;
- VkResult _recordingResult;
VkCommandBufferInheritanceInfo _secondaryInheritanceInfo;
id<MTLCommandBuffer> _prefilledMTLCmdBuffer = nil;
bool _isSecondary;
@@ -256,6 +255,9 @@
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _cmdBuffer->getVulkanAPIObject(); };
+
/** Encode commands from the command buffer onto the Metal command buffer. */
void encode(id<MTLCommandBuffer> mtlCmdBuff);
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
index 4c68f3d..4ccfe52 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm
@@ -24,6 +24,7 @@
#include "MVKFramebuffer.h"
#include "MVKQueryPool.h"
#include "MVKFoundation.h"
+#include "MVKLogging.h"
#include "MTLRenderPassDescriptor+MoltenVK.h"
#include "MVKCmdDraw.h"
@@ -37,7 +38,7 @@
reset(0);
- _recordingResult = VK_SUCCESS;
+ clearConfigurationResult();
_canAcceptCommands = true;
VkCommandBufferUsageFlags usage = pBeginInfo->flags;
@@ -50,7 +51,7 @@
bool hasInheritInfo = mvkSetOrClear(&_secondaryInheritanceInfo, pInheritInfo);
_doesContinueRenderPass = mvkAreFlagsEnabled(usage, VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) && hasInheritInfo;
- return _recordingResult;
+ return getConfigurationResult();
}
VkResult MVKCommandBuffer::reset(VkCommandBufferResetFlags flags) {
@@ -71,9 +72,9 @@
_supportsConcurrentExecution = false;
_wasExecuted = false;
_isExecutingNonConcurrently.clear();
- _recordingResult = VK_NOT_READY;
_commandCount = 0;
_initialVisibilityResultMTLBuffer = nil; // not retained
+ setConfigurationResult(VK_NOT_READY);
if (mvkAreFlagsEnabled(flags, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT)) {
// TODO: what are we releasing or returning here?
@@ -85,12 +86,12 @@
VkResult MVKCommandBuffer::end() {
_canAcceptCommands = false;
prefill();
- return _recordingResult;
+ return getConfigurationResult();
}
void MVKCommandBuffer::addCommand(MVKCommand* command) {
if ( !_canAcceptCommands ) {
- recordResult(mvkNotifyErrorWithText(VK_NOT_READY, "Command buffer cannot accept commands before vkBeginCommandBuffer() is called."));
+ setConfigurationResult(reportError(VK_NOT_READY, "Command buffer cannot accept commands before vkBeginCommandBuffer() is called."));
return;
}
@@ -102,7 +103,7 @@
command->added(this);
- recordResult(command->getConfigurationResult());
+ setConfigurationResult(command->getConfigurationResult());
}
void MVKCommandBuffer::submit(MVKQueueCommandBufferSubmission* cmdBuffSubmit) {
@@ -121,17 +122,17 @@
bool MVKCommandBuffer::canExecute() {
if (_isSecondary) {
- recordResult(mvkNotifyErrorWithText(VK_NOT_READY, "Secondary command buffers may not be submitted directly to a queue."));
+ setConfigurationResult(reportError(VK_NOT_READY, "Secondary command buffers may not be submitted directly to a queue."));
return false;
}
if ( !_isReusable && _wasExecuted ) {
- recordResult(mvkNotifyErrorWithText(VK_NOT_READY, "Command buffer does not support execution more that once."));
+ setConfigurationResult(reportError(VK_NOT_READY, "Command buffer does not support execution more that once."));
return false;
}
// Do this test last so that _isExecutingNonConcurrently is only set if everything else passes
if ( !_supportsConcurrentExecution && _isExecutingNonConcurrently.test_and_set()) {
- recordResult(mvkNotifyErrorWithText(VK_NOT_READY, "Command buffer does not support concurrent execution."));
+ setConfigurationResult(reportError(VK_NOT_READY, "Command buffer does not support concurrent execution."));
return false;
}
@@ -217,7 +218,7 @@
_lastTessellationPipeline = nullptr;
}
-void MVKCommandBuffer::recordDraw(MVKLoadStoreOverride* mvkDraw) {
+void MVKCommandBuffer::recordDraw(MVKLoadStoreOverrideMixin* mvkDraw) {
if (_lastTessellationPipeline != nullptr) {
// If a multi-pass pipeline is bound and we've already drawn something, need to override load actions
mvkDraw->setLoadOverride(true);
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
index eb72f48..87646d2 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
@@ -20,6 +20,7 @@
#include "MVKMTLResourceBindings.h"
#include "MVKCommandResourceFactory.h"
+#include "MVKDevice.h"
#include "MVKVector.h"
class MVKCommandEncoder;
@@ -43,6 +44,9 @@
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override;
+
/**
* Marks the content of this instance as dirty, relative to the
* current or next Metal render pass, and in need of submission to Metal.
@@ -399,6 +403,9 @@
}
}
+ void updateSwizzle(MVKVector<uint32_t> &constants, uint32_t index, uint32_t swizzle);
+ void assertMissingSwizzles(bool needsSwizzle, const char* stageName, MVKVector<MVKMTLTextureBinding>& texBindings);
+
};
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
index 7afca5a..92888b1 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
@@ -23,12 +23,17 @@
#include "MVKPipeline.h"
#include "MVKQueryPool.h"
#include "MVKLogging.h"
-#include "mvk_datatypes.h"
using namespace std;
#pragma mark -
+#pragma mark MVKCommandEncoderState
+
+MVKVulkanAPIObject* MVKCommandEncoderState::getVulkanAPIObject() { return _cmdEncoder->getVulkanAPIObject(); };
+
+
+#pragma mark -
#pragma mark MVKPipelineCommandEncoderState
void MVKPipelineCommandEncoderState::setPipeline(MVKPipeline* pipeline) {
@@ -443,13 +448,13 @@
#pragma mark MVKResourcesCommandEncoderState
// Updates the swizzle for an image in the given vector.
-static void updateSwizzle(MVKVector<uint32_t> &constants, uint32_t index, uint32_t swizzle) {
+void MVKResourcesCommandEncoderState::updateSwizzle(MVKVector<uint32_t> &constants, uint32_t index, uint32_t swizzle) {
if (index >= constants.size()) { constants.resize(index + 1); }
constants[index] = swizzle;
}
// If a swizzle is needed for this stage, iterates all the bindings and logs errors for those that need texture swizzling.
-static void assertMissingSwizzles(bool needsSwizzle, const char* stageName, MVKVector<MVKMTLTextureBinding>& texBindings) {
+void MVKResourcesCommandEncoderState::assertMissingSwizzles(bool needsSwizzle, const char* stageName, MVKVector<MVKMTLTextureBinding>& texBindings) {
if (needsSwizzle) {
for (MVKMTLTextureBinding& tb : texBindings) {
VkComponentMapping vkcm = mvkUnpackSwizzle(tb.swizzle);
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.h b/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.h
index 72e3fcb..53dab25 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.h
@@ -18,7 +18,6 @@
#pragma once
-#include "MVKDevice.h"
#include "MVKCommandResourceFactory.h"
#include "MVKMTLBufferAllocation.h"
#include <unordered_map>
@@ -27,6 +26,9 @@
#import <Metal/Metal.h>
+class MVKCommandPool;
+
+
#pragma mark -
#pragma mark MVKCommandEncodingPool
@@ -37,12 +39,15 @@
*
* Access to the content within this pool is thread-safe.
*/
-class MVKCommandEncodingPool : public MVKBaseDeviceObject {
+class MVKCommandEncodingPool : public MVKBaseObject {
public:
#pragma mark Command resources
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override;
+
/** Returns a MTLRenderPipelineState to support certain Vulkan BLIT commands. */
id<MTLRenderPipelineState> getCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey);
@@ -127,13 +132,14 @@
#pragma mark Construction
- MVKCommandEncodingPool(MVKDevice* device);
+ MVKCommandEncodingPool(MVKCommandPool* commandPool);
~MVKCommandEncodingPool() override;
-private:
+protected:
void destroyMetalResources();
+ MVKCommandPool* _commandPool;
std::mutex _lock;
std::unordered_map<MVKRPSKeyBlitImg, id<MTLRenderPipelineState>> _cmdBlitImageMTLRenderPipelineStates;
std::unordered_map<MVKRPSKeyClearAtt, id<MTLRenderPipelineState>> _cmdClearMTLRenderPipelineStates;
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.mm b/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.mm
index afede7e..82ed5a1 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncodingPool.mm
@@ -17,13 +17,18 @@
*/
#include "MVKCommandEncodingPool.h"
+#include "MVKCommandPool.h"
#include "MVKImage.h"
using namespace std;
+
#pragma mark -
#pragma mark MVKCommandEncodingPool
+MVKVulkanAPIObject* MVKCommandEncodingPool::getVulkanAPIObject() { return _commandPool->getVulkanAPIObject(); };
+
+
// In order to provide thread-safety with minimal performance impact, each of these access
// functions follows a 3-step pattern:
//
@@ -34,25 +39,25 @@
// Step 1 handles the common case where the resource exists, without the expense of a lock.
// Step 2 guards against a potential race condition where two threads get past Step 1 at
// the same time, and then both barrel ahead onto Step 3.
-#define MVK_ENC_REZ_ACCESS(rezAccess, rezFactoryFunc) \
- auto rez = rezAccess; \
- if (rez) { return rez; } \
- \
- lock_guard<mutex> lock(_lock); \
- rez = rezAccess; \
- if (rez) { return rez; } \
- \
- rez = _device->getCommandResourceFactory()->rezFactoryFunc; \
- rezAccess = rez; \
+#define MVK_ENC_REZ_ACCESS(rezAccess, rezFactoryFunc) \
+ auto rez = rezAccess; \
+ if (rez) { return rez; } \
+ \
+ lock_guard<mutex> lock(_lock); \
+ rez = rezAccess; \
+ if (rez) { return rez; } \
+ \
+ rez = _commandPool->getDevice()->getCommandResourceFactory()->rezFactoryFunc; \
+ rezAccess = rez; \
return rez
id<MTLRenderPipelineState> MVKCommandEncodingPool::getCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey) {
- MVK_ENC_REZ_ACCESS(_cmdClearMTLRenderPipelineStates[attKey], newCmdClearMTLRenderPipelineState(attKey));
+ MVK_ENC_REZ_ACCESS(_cmdClearMTLRenderPipelineStates[attKey], newCmdClearMTLRenderPipelineState(attKey, _commandPool));
}
id<MTLRenderPipelineState> MVKCommandEncodingPool::getCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey) {
- MVK_ENC_REZ_ACCESS(_cmdBlitImageMTLRenderPipelineStates[blitKey], newCmdBlitImageMTLRenderPipelineState(blitKey));
+ MVK_ENC_REZ_ACCESS(_cmdBlitImageMTLRenderPipelineStates[blitKey], newCmdBlitImageMTLRenderPipelineState(blitKey, _commandPool));
}
id<MTLSamplerState> MVKCommandEncodingPool::getCmdBlitImageMTLSamplerState(MTLSamplerMinMagFilter mtlFilter) {
@@ -102,27 +107,27 @@
}
id<MTLComputePipelineState> MVKCommandEncodingPool::getCmdCopyBufferBytesMTLComputePipelineState() {
- MVK_ENC_REZ_ACCESS(_mtlCopyBufferBytesComputePipelineState, newCmdCopyBufferBytesMTLComputePipelineState());
+ MVK_ENC_REZ_ACCESS(_mtlCopyBufferBytesComputePipelineState, newCmdCopyBufferBytesMTLComputePipelineState(_commandPool));
}
id<MTLComputePipelineState> MVKCommandEncodingPool::getCmdFillBufferMTLComputePipelineState() {
- MVK_ENC_REZ_ACCESS(_mtlFillBufferComputePipelineState, newCmdFillBufferMTLComputePipelineState());
+ MVK_ENC_REZ_ACCESS(_mtlFillBufferComputePipelineState, newCmdFillBufferMTLComputePipelineState(_commandPool));
}
id<MTLComputePipelineState> MVKCommandEncodingPool::getCmdCopyBufferToImage3DDecompressMTLComputePipelineState(bool needsTempBuff) {
- MVK_ENC_REZ_ACCESS(_mtlCopyBufferToImage3DDecompressComputePipelineState[needsTempBuff ? 1 : 0], newCmdCopyBufferToImage3DDecompressMTLComputePipelineState(needsTempBuff));
+ MVK_ENC_REZ_ACCESS(_mtlCopyBufferToImage3DDecompressComputePipelineState[needsTempBuff ? 1 : 0], newCmdCopyBufferToImage3DDecompressMTLComputePipelineState(needsTempBuff, _commandPool));
}
id<MTLComputePipelineState> MVKCommandEncodingPool::getCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed) {
- MVK_ENC_REZ_ACCESS(_mtlDrawIndirectConvertBuffersComputePipelineState[indexed ? 1 : 0], newCmdDrawIndirectConvertBuffersMTLComputePipelineState(indexed));
+ MVK_ENC_REZ_ACCESS(_mtlDrawIndirectConvertBuffersComputePipelineState[indexed ? 1 : 0], newCmdDrawIndirectConvertBuffersMTLComputePipelineState(indexed, _commandPool));
}
id<MTLComputePipelineState> MVKCommandEncodingPool::getCmdDrawIndexedCopyIndexBufferMTLComputePipelineState(MTLIndexType type) {
- MVK_ENC_REZ_ACCESS(_mtlDrawIndexedCopyIndexBufferComputePipelineState[type == MTLIndexTypeUInt16 ? 1 : 0], newCmdDrawIndexedCopyIndexBufferMTLComputePipelineState(type));
+ MVK_ENC_REZ_ACCESS(_mtlDrawIndexedCopyIndexBufferComputePipelineState[type == MTLIndexTypeUInt16 ? 1 : 0], newCmdDrawIndexedCopyIndexBufferMTLComputePipelineState(type, _commandPool));
}
id<MTLComputePipelineState> MVKCommandEncodingPool::getCmdCopyQueryPoolResultsMTLComputePipelineState() {
- MVK_ENC_REZ_ACCESS(_mtlCopyQueryPoolResultsComputePipelineState, newCmdCopyQueryPoolResultsMTLComputePipelineState());
+ MVK_ENC_REZ_ACCESS(_mtlCopyQueryPoolResultsComputePipelineState, newCmdCopyQueryPoolResultsMTLComputePipelineState(_commandPool));
}
void MVKCommandEncodingPool::clear() {
@@ -133,8 +138,8 @@
#pragma mark Construction
-MVKCommandEncodingPool::MVKCommandEncodingPool(MVKDevice* device) : MVKBaseDeviceObject(device),
- _mtlBufferAllocator(device, device->_pMetalFeatures->maxMTLBufferSize, true) {
+MVKCommandEncodingPool::MVKCommandEncodingPool(MVKCommandPool* commandPool) : _commandPool(commandPool),
+ _mtlBufferAllocator(commandPool->getDevice(), commandPool->getDevice()->_pMetalFeatures->maxMTLBufferSize, true) {
}
MVKCommandEncodingPool::~MVKCommandEncodingPool() {
@@ -143,6 +148,8 @@
/** Ensure all cached Metal components are released. */
void MVKCommandEncodingPool::destroyMetalResources() {
+ MVKDevice* mvkDev = _commandPool->getDevice();
+
for (auto& pair : _cmdBlitImageMTLRenderPipelineStates) { [pair.second release]; }
_cmdBlitImageMTLRenderPipelineStates.clear();
@@ -152,13 +159,13 @@
for (auto& pair : _mtlDepthStencilStates) { [pair.second release]; }
_mtlDepthStencilStates.clear();
- for (auto& pair : _transferImages) { _device->destroyImage(pair.second, nullptr); }
+ for (auto& pair : _transferImages) { mvkDev->destroyImage(pair.second, nullptr); }
_transferImages.clear();
- for (auto& pair : _transferBuffers) { _device->destroyBuffer(pair.second, nullptr); }
+ for (auto& pair : _transferBuffers) { mvkDev->destroyBuffer(pair.second, nullptr); }
_transferBuffers.clear();
- for (auto& pair : _transferBufferMemory) { _device->freeMemory(pair.second, nullptr); }
+ for (auto& pair : _transferBufferMemory) { mvkDev->freeMemory(pair.second, nullptr); }
_transferBufferMemory.clear();
[_cmdBlitImageLinearMTLSamplerState release];
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPool.h b/MoltenVK/MoltenVK/Commands/MVKCommandPool.h
index 41971ec..efabe55 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandPool.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandPool.h
@@ -49,10 +49,13 @@
* of this pool should be done during the setContent() function of each MVKCommand, and NOT
* during the execution of the command via the MVKCommand::encode() member function.
*/
-class MVKCommandPool : public MVKBaseDeviceObject {
+class MVKCommandPool : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT; }
+
#pragma mark Command type pools
MVKCommandTypePool<MVKCmdPipelineBarrier> _cmdPipelineBarrierPool;
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm b/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm
index cfac20a..273da53 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm
@@ -22,7 +22,7 @@
#include "MVKQueue.h"
#include "MVKDeviceMemory.h"
#include "MVKFoundation.h"
-#include "mvk_datatypes.h"
+#include "mvk_datatypes.hpp"
#include "MVKLogging.h"
using namespace std;
@@ -56,7 +56,10 @@
mvkCmdBuff->init(pAllocateInfo);
_allocatedCommandBuffers.insert(mvkCmdBuff);
pCmdBuffer[cbIdx] = mvkCmdBuff->getVkCommandBuffer();
- if (rslt == VK_SUCCESS) { rslt = mvkCmdBuff->getConfigurationResult(); }
+
+ // Command buffers start out in a VK_NOT_READY config result
+ VkResult cbRslt = mvkCmdBuff->getConfigurationResult();
+ if (rslt == VK_SUCCESS && cbRslt != VK_NOT_READY) { rslt = cbRslt; }
}
return rslt;
}
@@ -127,9 +130,9 @@
MVKCommandPool::MVKCommandPool(MVKDevice* device,
const VkCommandPoolCreateInfo* pCreateInfo) :
- MVKBaseDeviceObject(device),
+ MVKVulkanAPIDeviceObject(device),
_commandBufferPool(device),
- _commandEncodingPool(device),
+ _commandEncodingPool(this),
_queueFamilyIndex(pCreateInfo->queueFamilyIndex),
_cmdPipelineBarrierPool(this, true),
_cmdBindPipelinePool(this, true),
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h
index ee0051d..a9ddfb0 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.h
@@ -20,7 +20,7 @@
#include "MVKDevice.h"
#include "MVKFoundation.h"
-#include "mvk_datatypes.h"
+#include "mvk_datatypes.hpp"
#include <string>
#import <Metal/Metal.h>
@@ -306,10 +306,14 @@
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _device->getVulkanAPIObject(); };
+
#pragma mark Command resources
/** Returns a new MTLRenderPipelineState to support certain Vulkan BLIT commands. */
- id<MTLRenderPipelineState> newCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey);
+ id<MTLRenderPipelineState> newCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey,
+ MVKVulkanAPIDeviceObject* owner);
/**
* Returns a new MTLSamplerState dedicated to rendering to a texture using the
@@ -321,7 +325,8 @@
* Returns a new MTLRenderPipelineState dedicated to rendering to several
* attachments to support clearing regions of those attachments.
*/
- id<MTLRenderPipelineState> newCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey);
+ id<MTLRenderPipelineState> newCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey,
+ MVKVulkanAPIDeviceObject* owner);
/**
* Returns a new MTLDepthStencilState dedicated to rendering to several
@@ -353,22 +358,25 @@
MVKBuffer* newMVKBuffer(MVKBufferDescriptorData& buffData, MVKDeviceMemory*& buffMem);
/** Returns a new MTLComputePipelineState for copying between two buffers with byte-aligned copy regions. */
- id<MTLComputePipelineState> newCmdCopyBufferBytesMTLComputePipelineState();
+ id<MTLComputePipelineState> newCmdCopyBufferBytesMTLComputePipelineState(MVKVulkanAPIDeviceObject* owner);
/** Returns a new MTLComputePipelineState for filling a buffer. */
- id<MTLComputePipelineState> newCmdFillBufferMTLComputePipelineState();
+ id<MTLComputePipelineState> newCmdFillBufferMTLComputePipelineState(MVKVulkanAPIDeviceObject* owner);
/** Returns a new MTLComputePipelineState for copying between a buffer holding compressed data and a 3D image. */
- id<MTLComputePipelineState> newCmdCopyBufferToImage3DDecompressMTLComputePipelineState(bool needTempBuf);
+ id<MTLComputePipelineState> newCmdCopyBufferToImage3DDecompressMTLComputePipelineState(bool needTempBuf,
+ MVKVulkanAPIDeviceObject* owner);
/** Returns a new MTLComputePipelineState for converting an indirect buffer for use in a tessellated draw. */
- id<MTLComputePipelineState> newCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed);
+ id<MTLComputePipelineState> newCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed,
+ MVKVulkanAPIDeviceObject* owner);
/** Returns a new MTLComputePipelineState for copying an index buffer for use in a tessellated draw. */
- id<MTLComputePipelineState> newCmdDrawIndexedCopyIndexBufferMTLComputePipelineState(MTLIndexType type);
+ id<MTLComputePipelineState> newCmdDrawIndexedCopyIndexBufferMTLComputePipelineState(MTLIndexType type,
+ MVKVulkanAPIDeviceObject* owner);
/** Returns a new MTLComputePipelineState for copying query results to a buffer. */
- id<MTLComputePipelineState> newCmdCopyQueryPoolResultsMTLComputePipelineState();
+ id<MTLComputePipelineState> newCmdCopyQueryPoolResultsMTLComputePipelineState(MVKVulkanAPIDeviceObject* owner);
#pragma mark Construction
@@ -386,8 +394,10 @@
NSString* getMTLFormatTypeString(MTLPixelFormat mtlPixFmt);
id<MTLFunction> getFunctionNamed(const char* funcName);
id<MTLFunction> newMTLFunction(NSString* mslSrcCode, NSString* funcName);
- id<MTLRenderPipelineState> newMTLRenderPipelineState(MTLRenderPipelineDescriptor* plDesc);
- id<MTLComputePipelineState> newMTLComputePipelineState(id<MTLFunction> mtlFunction);
+ id<MTLRenderPipelineState> newMTLRenderPipelineState(MTLRenderPipelineDescriptor* plDesc,
+ MVKVulkanAPIDeviceObject* owner);
+ id<MTLComputePipelineState> newMTLComputePipelineState(id<MTLFunction> mtlFunction,
+ MVKVulkanAPIDeviceObject* owner);
id<MTLLibrary> _mtlLibrary;
MVKDeviceMemory* _transferImageMemory;
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm
index 3ff0399..28d2327 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandResourceFactory.mm
@@ -31,7 +31,8 @@
#pragma mark -
#pragma mark MVKCommandResourceFactory
-id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey) {
+id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey,
+ MVKVulkanAPIDeviceObject* owner) {
MTLRenderPipelineDescriptor* plDesc = [[[MTLRenderPipelineDescriptor alloc] init] autorelease];
plDesc.label = @"CmdBlitImage";
@@ -69,7 +70,7 @@
vbDesc.stepRate = 1;
vbDesc.stride = vtxStride;
- return newMTLRenderPipelineState(plDesc);
+ return newMTLRenderPipelineState(plDesc, owner);
}
id<MTLSamplerState> MVKCommandResourceFactory::newCmdBlitImageMTLSamplerState(MTLSamplerMinMagFilter mtlFilter) {
@@ -85,7 +86,8 @@
return [getMTLDevice() newSamplerStateWithDescriptor: sDesc];
}
-id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey) {
+id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey,
+ MVKVulkanAPIDeviceObject* owner) {
MTLRenderPipelineDescriptor* plDesc = [[[MTLRenderPipelineDescriptor alloc] init] autorelease];
plDesc.label = @"CmdClearAttachments";
plDesc.vertexFunction = getClearVertFunction(attKey);
@@ -124,7 +126,7 @@
vbDesc.stepRate = 1;
vbDesc.stride = vtxStride;
- return newMTLRenderPipelineState(plDesc);
+ return newMTLRenderPipelineState(plDesc, owner);
}
id<MTLFunction> MVKCommandResourceFactory::getBlitFragFunction(MVKRPSKeyBlitImg& blitKey) {
@@ -372,31 +374,37 @@
return mvkBuff;
}
-id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdCopyBufferBytesMTLComputePipelineState() {
- return newMTLComputePipelineState(getFunctionNamed("cmdCopyBufferBytes"));
+id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdCopyBufferBytesMTLComputePipelineState(MVKVulkanAPIDeviceObject* owner) {
+ return newMTLComputePipelineState(getFunctionNamed("cmdCopyBufferBytes"), owner);
}
-id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdFillBufferMTLComputePipelineState() {
- return newMTLComputePipelineState(getFunctionNamed("cmdFillBuffer"));
+id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdFillBufferMTLComputePipelineState(MVKVulkanAPIDeviceObject* owner) {
+ return newMTLComputePipelineState(getFunctionNamed("cmdFillBuffer"), owner);
}
-id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdCopyBufferToImage3DDecompressMTLComputePipelineState(bool needTempBuf) {
- return newMTLComputePipelineState(getFunctionNamed(needTempBuf ? "cmdCopyBufferToImage3DDecompressTempBufferDXTn" :
- "cmdCopyBufferToImage3DDecompressDXTn"));
+id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdCopyBufferToImage3DDecompressMTLComputePipelineState(bool needTempBuf,
+ MVKVulkanAPIDeviceObject* owner) {
+ return newMTLComputePipelineState(getFunctionNamed(needTempBuf
+ ? "cmdCopyBufferToImage3DDecompressTempBufferDXTn"
+ : "cmdCopyBufferToImage3DDecompressDXTn"), owner);
}
-id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed) {
- return newMTLComputePipelineState(getFunctionNamed(indexed ? "cmdDrawIndexedIndirectConvertBuffers" :
- "cmdDrawIndirectConvertBuffers"));
+id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed,
+ MVKVulkanAPIDeviceObject* owner) {
+ return newMTLComputePipelineState(getFunctionNamed(indexed
+ ? "cmdDrawIndexedIndirectConvertBuffers"
+ : "cmdDrawIndirectConvertBuffers"), owner);
}
-id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdDrawIndexedCopyIndexBufferMTLComputePipelineState(MTLIndexType type) {
- return newMTLComputePipelineState(getFunctionNamed(type == MTLIndexTypeUInt16 ? "cmdDrawIndexedCopyIndex16Buffer" :
- "cmdDrawIndexedCopyIndex32Buffer"));
+id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdDrawIndexedCopyIndexBufferMTLComputePipelineState(MTLIndexType type,
+ MVKVulkanAPIDeviceObject* owner) {
+ return newMTLComputePipelineState(getFunctionNamed(type == MTLIndexTypeUInt16
+ ? "cmdDrawIndexedCopyIndex16Buffer"
+ : "cmdDrawIndexedCopyIndex32Buffer"), owner);
}
-id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdCopyQueryPoolResultsMTLComputePipelineState() {
- return newMTLComputePipelineState(getFunctionNamed("cmdCopyQueryPoolResultsToBuffer"));
+id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdCopyQueryPoolResultsMTLComputePipelineState(MVKVulkanAPIDeviceObject* owner) {
+ return newMTLComputePipelineState(getFunctionNamed("cmdCopyQueryPoolResultsToBuffer"), owner);
}
@@ -418,9 +426,9 @@
error: &err] autorelease];
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.mslCompile, startTime);
if (err) {
- mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED,
- "Could not compile support shader from MSL source (Error code %li):\n%s\n%s",
- (long)err.code, mslSrcCode.UTF8String, err.localizedDescription.UTF8String);
+ reportError(VK_ERROR_INITIALIZATION_FAILED,
+ "Could not compile support shader from MSL source (Error code %li):\n%s\n%s",
+ (long)err.code, mslSrcCode.UTF8String, err.localizedDescription.UTF8String);
return nil;
}
@@ -431,15 +439,17 @@
}
}
-id<MTLRenderPipelineState> MVKCommandResourceFactory::newMTLRenderPipelineState(MTLRenderPipelineDescriptor* plDesc) {
- MVKRenderPipelineCompiler* plc = new MVKRenderPipelineCompiler(_device);
+id<MTLRenderPipelineState> MVKCommandResourceFactory::newMTLRenderPipelineState(MTLRenderPipelineDescriptor* plDesc,
+ MVKVulkanAPIDeviceObject* owner) {
+ MVKRenderPipelineCompiler* plc = new MVKRenderPipelineCompiler(owner);
id<MTLRenderPipelineState> rps = plc->newMTLRenderPipelineState(plDesc); // retained
plc->destroy();
return rps;
}
-id<MTLComputePipelineState> MVKCommandResourceFactory::newMTLComputePipelineState(id<MTLFunction> mtlFunction) {
- MVKComputePipelineCompiler* plc = new MVKComputePipelineCompiler(_device);
+id<MTLComputePipelineState> MVKCommandResourceFactory::newMTLComputePipelineState(id<MTLFunction> mtlFunction,
+ MVKVulkanAPIDeviceObject* owner) {
+ MVKComputePipelineCompiler* plc = new MVKComputePipelineCompiler(owner);
id<MTLComputePipelineState> cps = plc->newMTLComputePipelineState(mtlFunction); // retained
plc->destroy();
return cps;
diff --git a/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.h b/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.h
index 9b52dc9..822dac8 100644
--- a/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.h
+++ b/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.h
@@ -38,6 +38,9 @@
NSUInteger _offset;
NSUInteger _length;
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override;
+
/**
* Returns a pointer to the begining of this allocation memory, taking into
* consideration this allocation's offset into the underlying MTLBuffer.
@@ -83,6 +86,9 @@
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _device->getVulkanAPIObject(); };
+
/** Returns a new MVKMTLBufferAllocation instance. */
MVKMTLBufferAllocation* newObject() override;
@@ -119,6 +125,9 @@
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _device->getVulkanAPIObject(); };
+
/**
* Returns a MVKMTLBufferAllocation instance with a size that is the next
* power-of-two value that is at least as big as the requested size.
diff --git a/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.mm b/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.mm
index 3f73a54..4b708e1 100644
--- a/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKMTLBufferAllocation.mm
@@ -23,6 +23,8 @@
#pragma mark -
#pragma mark MVKMTLBufferAllocation
+MVKVulkanAPIObject* MVKMTLBufferAllocation::getVulkanAPIObject() { return _pool->getVulkanAPIObject(); };
+
void MVKMTLBufferAllocation::returnToPool() { _pool->returnObjectSafely(this); }
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h
index 6839df1..f88a504 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h
@@ -31,6 +31,9 @@
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT; }
+
#pragma mark Resource memory
/** Returns the memory requirements of this resource by populating the specified structure. */
@@ -89,10 +92,13 @@
#pragma mark MVKBufferView
/** Represents a Vulkan buffer view. */
-class MVKBufferView : public MVKRefCountedDeviceObject {
+class MVKBufferView : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT; }
+
#pragma mark Metal
/** Returns a Metal texture that overlays this buffer view. */
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
index c022e2a..858d30f 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
@@ -19,7 +19,8 @@
#include "MVKBuffer.h"
#include "MVKCommandBuffer.h"
#include "MVKFoundation.h"
-#include "mvk_datatypes.h"
+#include "MVKEnvironment.h"
+#include "mvk_datatypes.hpp"
using namespace std;
@@ -167,7 +168,7 @@
#pragma mark Construction
-MVKBufferView::MVKBufferView(MVKDevice* device, const VkBufferViewCreateInfo* pCreateInfo) : MVKRefCountedDeviceObject(device) {
+MVKBufferView::MVKBufferView(MVKDevice* device, const VkBufferViewCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
_buffer = (MVKBuffer*)pCreateInfo->buffer;
_mtlBufferOffset = _buffer->getMTLBufferOffset() + pCreateInfo->offset;
_mtlPixelFormat = getMTLPixelFormatFromVkFormat(pCreateInfo->format);
@@ -193,7 +194,7 @@
_textureSize.height = uint32_t(rowCount * fmtBlockSize.height);
if ( !_device->_pMetalFeatures->texelBuffers ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "Texel buffers are not supported on this device."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "Texel buffers are not supported on this device."));
}
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
index 7499208..3570f52 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
@@ -21,7 +21,6 @@
#include "MVKDevice.h"
#include "MVKImage.h"
#include "MVKVector.h"
-#include "mvk_datatypes.h"
#include <MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.h>
#include <unordered_set>
#include <unordered_map>
@@ -76,6 +75,9 @@
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override;
+
/** Encodes this binding layout and the specified descriptor set binding on the specified command encoder. */
void bind(MVKCommandEncoder* cmdEncoder,
MVKDescriptorBinding& descBinding,
@@ -116,6 +118,7 @@
MVKShaderStageResourceBinding* pDescSetCounts,
const VkDescriptorSetLayoutBinding* pBinding);
+ MVKDescriptorSetLayout* _layout;
VkDescriptorSetLayoutBinding _info;
std::vector<MVKSampler*> _immutableSamplers;
MVKShaderResourceBinding _mtlResourceIndexOffsets;
@@ -127,10 +130,13 @@
#pragma mark MVKDescriptorSetLayout
/** Represents a Vulkan descriptor set layout. */
-class MVKDescriptorSetLayout : public MVKBaseDeviceObject {
+class MVKDescriptorSetLayout : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT; }
+
/** Encodes this descriptor set layout and the specified descriptor set on the specified command encoder. */
void bindDescriptorSet(MVKCommandEncoder* cmdEncoder,
MVKDescriptorSet* descSet,
@@ -184,6 +190,9 @@
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override;
+
/**
* Updates the internal element bindings from the specified content.
*
@@ -242,7 +251,7 @@
bool hasBinding(uint32_t binding);
/** Constructs an instance. */
- MVKDescriptorBinding(MVKDescriptorSetLayoutBinding* pBindingLayout);
+ MVKDescriptorBinding(MVKDescriptorSet* pDescSet, MVKDescriptorSetLayoutBinding* pBindingLayout);
/** Destructor. */
~MVKDescriptorBinding();
@@ -252,6 +261,7 @@
void initMTLSamplers(MVKDescriptorSetLayoutBinding* pBindingLayout);
+ MVKDescriptorSet* _pDescSet;
MVKDescriptorSetLayoutBinding* _pBindingLayout;
std::vector<VkDescriptorImageInfo> _imageBindings;
std::vector<VkDescriptorBufferInfo> _bufferBindings;
@@ -268,10 +278,13 @@
#pragma mark MVKDescriptorSet
/** Represents a Vulkan descriptor set. */
-class MVKDescriptorSet : public MVKBaseDeviceObject {
+class MVKDescriptorSet : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT; }
+
/** Updates the resource bindings in this instance from the specified content. */
template<typename DescriptorAction>
void writeDescriptorSets(const DescriptorAction* pDescriptorAction,
@@ -295,7 +308,7 @@
*/
MVKDescriptorSet* _next;
- MVKDescriptorSet(MVKDevice* device) : MVKBaseDeviceObject(device) {}
+ MVKDescriptorSet(MVKDevice* device) : MVKVulkanAPIDeviceObject(device) {}
protected:
friend class MVKDescriptorSetLayout;
@@ -315,10 +328,13 @@
typedef MVKDeviceObjectPool<MVKDescriptorSet> MVKDescriptorSetPool;
/** Represents a Vulkan descriptor pool. */
-class MVKDescriptorPool : public MVKBaseDeviceObject {
+class MVKDescriptorPool : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT; }
+
/** Allocates the specified number of descriptor sets. */
VkResult allocateDescriptorSets(uint32_t count,
const VkDescriptorSetLayout* pSetLayouts,
@@ -349,10 +365,13 @@
#pragma mark MVKDescriptorUpdateTemplate
/** Represents a Vulkan descriptor update template. */
-class MVKDescriptorUpdateTemplate : public MVKConfigurableObject {
+class MVKDescriptorUpdateTemplate : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT; }
+
/** Get the nth update template entry. */
const VkDescriptorUpdateTemplateEntryKHR* getEntry(uint32_t n) const;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
index 12402a8..3a62682 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
@@ -21,6 +21,7 @@
#include "MVKBuffer.h"
#include "MVKFoundation.h"
#include "MVKLogging.h"
+#include "mvk_datatypes.hpp"
#include <stdlib.h>
using namespace std;
@@ -28,7 +29,7 @@
#pragma mark MVKShaderStageResourceBinding
-MVK_PUBLIC_SYMBOL MVKShaderStageResourceBinding MVKShaderStageResourceBinding::operator+ (const MVKShaderStageResourceBinding& rhs) {
+MVKShaderStageResourceBinding MVKShaderStageResourceBinding::operator+ (const MVKShaderStageResourceBinding& rhs) {
MVKShaderStageResourceBinding rslt;
rslt.bufferIndex = this->bufferIndex + rhs.bufferIndex;
rslt.textureIndex = this->textureIndex + rhs.textureIndex;
@@ -36,7 +37,7 @@
return rslt;
}
-MVK_PUBLIC_SYMBOL MVKShaderStageResourceBinding& MVKShaderStageResourceBinding::operator+= (const MVKShaderStageResourceBinding& rhs) {
+MVKShaderStageResourceBinding& MVKShaderStageResourceBinding::operator+= (const MVKShaderStageResourceBinding& rhs) {
this->bufferIndex += rhs.bufferIndex;
this->textureIndex += rhs.textureIndex;
this->samplerIndex += rhs.samplerIndex;
@@ -46,19 +47,19 @@
#pragma mark MVKShaderResourceBinding
-MVK_PUBLIC_SYMBOL uint32_t MVKShaderResourceBinding::getMaxBufferIndex() {
+uint32_t MVKShaderResourceBinding::getMaxBufferIndex() {
return max({stages[kMVKShaderStageVertex].bufferIndex, stages[kMVKShaderStageTessCtl].bufferIndex, stages[kMVKShaderStageTessEval].bufferIndex, stages[kMVKShaderStageFragment].bufferIndex, stages[kMVKShaderStageCompute].bufferIndex});
}
-MVK_PUBLIC_SYMBOL uint32_t MVKShaderResourceBinding::getMaxTextureIndex() {
+uint32_t MVKShaderResourceBinding::getMaxTextureIndex() {
return max({stages[kMVKShaderStageVertex].textureIndex, stages[kMVKShaderStageTessCtl].textureIndex, stages[kMVKShaderStageTessEval].textureIndex, stages[kMVKShaderStageFragment].textureIndex, stages[kMVKShaderStageCompute].textureIndex});
}
-MVK_PUBLIC_SYMBOL uint32_t MVKShaderResourceBinding::getMaxSamplerIndex() {
+uint32_t MVKShaderResourceBinding::getMaxSamplerIndex() {
return max({stages[kMVKShaderStageVertex].samplerIndex, stages[kMVKShaderStageTessCtl].samplerIndex, stages[kMVKShaderStageTessEval].samplerIndex, stages[kMVKShaderStageFragment].samplerIndex, stages[kMVKShaderStageCompute].samplerIndex});
}
-MVK_PUBLIC_SYMBOL MVKShaderResourceBinding MVKShaderResourceBinding::operator+ (const MVKShaderResourceBinding& rhs) {
+MVKShaderResourceBinding MVKShaderResourceBinding::operator+ (const MVKShaderResourceBinding& rhs) {
MVKShaderResourceBinding rslt;
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
rslt.stages[i] = this->stages[i] + rhs.stages[i];
@@ -66,7 +67,7 @@
return rslt;
}
-MVK_PUBLIC_SYMBOL MVKShaderResourceBinding& MVKShaderResourceBinding::operator+= (const MVKShaderResourceBinding& rhs) {
+MVKShaderResourceBinding& MVKShaderResourceBinding::operator+= (const MVKShaderResourceBinding& rhs) {
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
this->stages[i] += rhs.stages[i];
}
@@ -77,6 +78,8 @@
#pragma mark -
#pragma mark MVKDescriptorSetLayoutBinding
+MVKVulkanAPIObject* MVKDescriptorSetLayoutBinding::getVulkanAPIObject() { return _layout; };
+
void MVKDescriptorSetLayoutBinding::bind(MVKCommandEncoder* cmdEncoder,
MVKDescriptorBinding& descBinding,
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
@@ -376,8 +379,9 @@
MVKDescriptorSetLayoutBinding::MVKDescriptorSetLayoutBinding(MVKDevice* device,
MVKDescriptorSetLayout* layout,
- const VkDescriptorSetLayoutBinding* pBinding) : MVKBaseDeviceObject(device) {
- for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
+ const VkDescriptorSetLayoutBinding* pBinding) : MVKBaseDeviceObject(device), _layout(layout) {
+
+ for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
// Determine if this binding is used by this shader stage
_applyToStage[i] = mvkAreFlagsEnabled(pBinding->stageFlags, mvkVkShaderStageFlagBitsFromMVKShaderStage(MVKShaderStage(i)));
// If this binding is used by the shader, set the Metal resource index
@@ -403,9 +407,11 @@
}
MVKDescriptorSetLayoutBinding::MVKDescriptorSetLayoutBinding(const MVKDescriptorSetLayoutBinding& binding) :
- MVKBaseDeviceObject(binding._device), _info(binding._info), _immutableSamplers(binding._immutableSamplers),
+ MVKBaseDeviceObject(binding._device), _layout(binding._layout),
+ _info(binding._info), _immutableSamplers(binding._immutableSamplers),
_mtlResourceIndexOffsets(binding._mtlResourceIndexOffsets) {
- for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
+
+ for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
_applyToStage[i] = binding._applyToStage[i];
}
for (MVKSampler* sampler : _immutableSamplers) {
@@ -430,7 +436,7 @@
pDescSetCounts->samplerIndex += pBinding->descriptorCount;
if (pBinding->descriptorCount > 1 && !_device->_pMetalFeatures->arrayOfSamplers) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "Device %s does not support arrays of samplers.", _device->getName()));
+ _layout->setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "Device %s does not support arrays of samplers.", _device->getName()));
}
break;
@@ -442,10 +448,10 @@
if (pBinding->descriptorCount > 1) {
if ( !_device->_pMetalFeatures->arrayOfTextures ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "Device %s does not support arrays of textures.", _device->getName()));
+ _layout->setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "Device %s does not support arrays of textures.", _device->getName()));
}
if ( !_device->_pMetalFeatures->arrayOfSamplers ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "Device %s does not support arrays of samplers.", _device->getName()));
+ _layout->setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "Device %s does not support arrays of samplers.", _device->getName()));
}
}
break;
@@ -459,7 +465,7 @@
pDescSetCounts->textureIndex += pBinding->descriptorCount;
if (pBinding->descriptorCount > 1 && !_device->_pMetalFeatures->arrayOfTextures) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "Device %s does not support arrays of textures.", _device->getName()));
+ _layout->setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "Device %s does not support arrays of textures.", _device->getName()));
}
break;
@@ -601,14 +607,13 @@
}
MVKDescriptorSetLayout::MVKDescriptorSetLayout(MVKDevice* device,
- const VkDescriptorSetLayoutCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
+ const VkDescriptorSetLayoutCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
_isPushDescriptorLayout = (pCreateInfo->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR) != 0;
// Create the descriptor bindings
_bindings.reserve(pCreateInfo->bindingCount);
for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
_bindings.emplace_back(_device, this, &pCreateInfo->pBindings[i]);
_bindingToIndex[pCreateInfo->pBindings[i].binding] = i;
- setConfigurationResult(_bindings.back().getConfigurationResult());
}
}
@@ -616,6 +621,8 @@
#pragma mark -
#pragma mark MVKDescriptorBinding
+MVKVulkanAPIObject* MVKDescriptorBinding::getVulkanAPIObject() { return _pDescSet->getVulkanAPIObject(); };
+
uint32_t MVKDescriptorBinding::writeBindings(uint32_t srcStartIndex,
uint32_t dstStartIndex,
uint32_t count,
@@ -785,7 +792,7 @@
return _pBindingLayout->_info.binding == binding;
}
-MVKDescriptorBinding::MVKDescriptorBinding(MVKDescriptorSetLayoutBinding* pBindingLayout) : MVKBaseObject() {
+MVKDescriptorBinding::MVKDescriptorBinding(MVKDescriptorSet* pDescSet, MVKDescriptorSetLayoutBinding* pBindingLayout) : _pDescSet(pDescSet) {
uint32_t descCnt = pBindingLayout->_info.descriptorCount;
@@ -941,7 +948,7 @@
_bindings.clear();
_bindings.reserve(bindCnt);
for (uint32_t i = 0; i < bindCnt; i++) {
- _bindings.emplace_back(&layout->_bindings[i]);
+ _bindings.emplace_back(this, &layout->_bindings[i]);
}
}
}
@@ -957,7 +964,7 @@
if (_device->_enabledExtensions.vk_KHR_maintenance1.enabled) {
return VK_ERROR_OUT_OF_POOL_MEMORY; // Failure is an acceptable test...don't log as error.
} else {
- return mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "The maximum number of descriptor sets that can be allocated by this descriptor pool is %d.", _maxSets);
+ return reportError(VK_ERROR_INITIALIZATION_FAILED, "The maximum number of descriptor sets that can be allocated by this descriptor pool is %d.", _maxSets);
}
}
@@ -1004,7 +1011,7 @@
}
MVKDescriptorPool::MVKDescriptorPool(MVKDevice* device,
- const VkDescriptorPoolCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
+ const VkDescriptorPoolCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
_maxSets = pCreateInfo->maxSets;
}
@@ -1030,8 +1037,9 @@
return _type;
}
-MVKDescriptorUpdateTemplate::MVKDescriptorUpdateTemplate(MVKDevice* device, const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo) :
- MVKConfigurableObject(), _type(pCreateInfo->templateType) {
+MVKDescriptorUpdateTemplate::MVKDescriptorUpdateTemplate(MVKDevice* device,
+ const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo) :
+ MVKVulkanAPIDeviceObject(device), _type(pCreateInfo->templateType) {
for (uint32_t i = 0; i < pCreateInfo->descriptorUpdateEntryCount; i++)
_entries.push_back(pCreateInfo->pDescriptorUpdateEntries[i]);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
index 45c438d..aef11ea 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
@@ -22,7 +22,7 @@
#include "MVKBaseObject.h"
#include "MVKLayers.h"
#include "MVKObjectPool.h"
-#include "mvk_datatypes.h"
+#include "mvk_datatypes.hpp"
#include "vk_mvk_moltenvk.h"
#include <vector>
#include <string>
@@ -75,10 +75,16 @@
#pragma mark MVKPhysicalDevice
/** Represents a Vulkan physical GPU device. */
-class MVKPhysicalDevice : public MVKDispatchableObject {
+class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT; }
+
+ /** Returns a pointer to the Vulkan instance. */
+ MVKInstance* getInstance() override { return _mvkInstance; }
+
/** Populates the specified structure with the features of this device. */
void getFeatures(VkPhysicalDeviceFeatures* features);
@@ -224,12 +230,6 @@
*/
VkResult getQueueFamilyProperties(uint32_t* pCount, VkQueueFamilyProperties2KHR* pQueueFamilyProperties);
- /** Returns a pointer to the Vulkan instance. */
- inline MVKInstance* getInstance() { return _mvkInstance; }
-
- /** Returns a pointer to the layer manager. */
- inline MVKLayerManager* getLayerManager() { return MVKLayerManager::globalManager(); }
-
#pragma mark Memory models
@@ -339,12 +339,15 @@
#pragma mark MVKDevice
/** Represents a Vulkan logical GPU device, associated with a physical device. */
-class MVKDevice : public MVKDispatchableObject {
+class MVKDevice : public MVKDispatchableVulkanAPIObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT; }
+
/** Returns a pointer to the Vulkan instance. */
- inline MVKInstance* getInstance() { return _physicalDevice->_mvkInstance; }
+ MVKInstance* getInstance() override { return _physicalDevice->getInstance(); }
/** Returns the physical device underlying this logical device. */
inline MVKPhysicalDevice* getPhysicalDevice() { return _physicalDevice; }
@@ -658,13 +661,17 @@
#pragma mark -
-#pragma mark MVKBaseDeviceObject
+#pragma mark MVKDeviceTrackingMixin
/**
- * Represents an object that is spawned from a Vulkan device, and tracks that device.
+ * This mixin class adds the ability for an object to track the device that created it.
* Implementation supports an instance where the device is null.
+ *
+ * As a mixin, this class should only be used as a component of multiple inheritance.
+ * Any class that inherits from this class should also inherit from MVKBaseObject.
+ * This requirement is to avoid the diamond problem of multiple inheritance.
*/
-class MVKBaseDeviceObject : public MVKConfigurableObject {
+class MVKDeviceTrackingMixin {
public:
@@ -682,91 +689,54 @@
* See the notes for that function for more information about how MTLPixelFormats
* are managed for each platform device.
*/
- inline MTLPixelFormat getMTLPixelFormatFromVkFormat(VkFormat vkFormat) {
- return _device ? _device->getMTLPixelFormatFromVkFormat(vkFormat) : mvkMTLPixelFormatFromVkFormat(vkFormat);
- }
+ inline MTLPixelFormat getMTLPixelFormatFromVkFormat(VkFormat vkFormat) {
+ return _device ? _device->getMTLPixelFormatFromVkFormat(vkFormat)
+ : mvkMTLPixelFormatFromVkFormatInObj(vkFormat, getBaseObject());
+ }
/** Constructs an instance for the specified device. */
- MVKBaseDeviceObject(MVKDevice* device) : _device(device) {}
+ MVKDeviceTrackingMixin(MVKDevice* device) : _device(device) {}
+
+ virtual ~MVKDeviceTrackingMixin() {}
protected:
+ virtual MVKBaseObject* getBaseObject() = 0;
MVKDevice* _device;
};
#pragma mark -
-#pragma mark MVKDispatchableDeviceObject
+#pragma mark MVKBaseDeviceObject
-/**
- * Represents a dispatchable object that is spawned from a Vulkan device, and tracks that device.
- * Implementation supports an instance where the device is null.
- */
-class MVKDispatchableDeviceObject : public MVKDispatchableObject {
+/** Represents an object that is spawned from a Vulkan device, and tracks that device. */
+class MVKBaseDeviceObject : public MVKBaseObject, public MVKDeviceTrackingMixin {
public:
- /** Returns the device for which this object was created. */
- inline MVKDevice* getDevice() { return _device; }
-
- /** Returns the underlying Metal device. */
- inline id<MTLDevice> getMTLDevice() { return _device ? _device->getMTLDevice() : nil; }
-
- /** Constructs an instance for the specified device. */
- MVKDispatchableDeviceObject(MVKDevice* device) : _device(device) {}
+ /** Constructs an instance for the specified device. */
+ MVKBaseDeviceObject(MVKDevice* device) : MVKDeviceTrackingMixin(device) {}
protected:
- MVKDevice* _device;
+ MVKBaseObject* getBaseObject() override { return this; };
};
#pragma mark -
-#pragma mark MVKRefCountedDeviceObject
+#pragma mark MVKVulkanAPIDeviceObject
-/**
- * Represents a device-spawned object that supports basic reference counting.
- *
- * An object of this type will automatically be deleted iff it has been destroyed
- * by the client, and all references have been released. An object of this type is
- * therefore allowed to live past its destruction by the client, until it is no
- * longer referenced by other objects.
- */
-class MVKRefCountedDeviceObject : public MVKBaseDeviceObject {
+/** Abstract class that represents an opaque Vulkan API handle object spawned from a Vulkan device. */
+class MVKVulkanAPIDeviceObject : public MVKVulkanAPIObject, public MVKDeviceTrackingMixin {
public:
- /**
- * Called when this instance has been retained as a reference by another object,
- * indicating that this instance will not be deleted until that reference is released.
- */
- void retain();
+ /** Returns a pointer to the Vulkan instance. */
+ MVKInstance* getInstance() override { return _device ? _device->getInstance() : nullptr; }
- /**
- * Called when this instance has been released as a reference from another object.
- * Once all references have been released, this object is free to be deleted.
- * If the destroy() function has already been called on this instance by the time
- * this function is called, this instance will be deleted.
- */
- void release();
+ /** Constructs an instance for the specified device. */
+ MVKVulkanAPIDeviceObject(MVKDevice* device) : MVKDeviceTrackingMixin(device) {}
- /**
- * Marks this instance as destroyed. If all previous references to this instance
- * have been released, this instance will be deleted, otherwise deletion of this
- * instance will automatically be deferred until all references have been released.
- */
- void destroy() override;
-
-#pragma mark Construction
-
- MVKRefCountedDeviceObject(MVKDevice* device) : MVKBaseDeviceObject(device) {}
-
-private:
-
- bool decrementRetainCount();
- bool markDestroyed();
-
- std::mutex _refLock;
- unsigned _refCount = 0;
- bool _isDestroyed = false;
+protected:
+ MVKBaseObject* getBaseObject() override { return this; };
};
@@ -779,6 +749,10 @@
public:
+
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _device; };
+
/** Returns a new instance. */
T* newObject() override { return new T(_device); }
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index be3fbba..58fd374 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -32,6 +32,7 @@
#include "MVKFoundation.h"
#include "MVKCodec.h"
#include "MVKEnvironment.h"
+#include "MVKLogging.h"
#include "MVKOSExtensions.h"
#include <MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.h>
#include "vk_mvk_moltenvk.h"
@@ -2033,7 +2034,7 @@
_globalVisibilityQueryCount = uint32_t(newBuffLen / kMVKQuerySlotSizeInBytes);
if (reqBuffLen > maxBuffLen) {
- mvkNotifyErrorWithText(VK_ERROR_OUT_OF_DEVICE_MEMORY, "vkCreateQueryPool(): A maximum of %d total queries are available on this device in its current configuration. See the API notes for the MVKConfiguration.supportLargeQueryPools configuration parameter for more info.", _globalVisibilityQueryCount);
+ reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "vkCreateQueryPool(): A maximum of %d total queries are available on this device in its current configuration. See the API notes for the MVKConfiguration.supportLargeQueryPools configuration parameter for more info.", _globalVisibilityQueryCount);
}
NSUInteger mtlBuffLen = mvkAlignByteOffset(newBuffLen, _pMetalFeatures->mtlBufferAlignment);
@@ -2055,7 +2056,8 @@
_enabledVarPtrFeatures(),
_enabledHostQryResetFeatures(),
_enabledVtxAttrDivFeatures(),
- _enabledPortabilityFeatures()
+ _enabledPortabilityFeatures(),
+ _enabledExtensions(this)
{
initPerformanceTracking();
@@ -2070,9 +2072,10 @@
initQueues(pCreateInfo);
- string logMsg = "Created VkDevice to run on GPU %s with the following Vulkan extensions enabled:";
- logMsg += _enabledExtensions.enabledNamesString("\n\t\t", true);
- MVKLogInfo(logMsg.c_str(), _pProperties->deviceName);
+ MVKLogInfo("Created VkDevice to run on GPU %s with the following %d Vulkan extensions enabled:%s",
+ _pProperties->deviceName,
+ _enabledExtensions.getEnabledCount(),
+ _enabledExtensions.enabledNamesString("\n\t\t", true).c_str());
}
void MVKDevice::initPerformanceTracking() {
@@ -2243,7 +2246,7 @@
for (uint32_t i = 0; i < count; i++) {
((VkBool32*)pEnable)[i] = pRequested[i] && pAvailable[i];
if (pRequested[i] && !pAvailable[i]) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateDevice(): Requested feature is not available on this device."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateDevice(): Requested feature is not available on this device."));
}
}
}
@@ -2285,40 +2288,6 @@
#pragma mark -
-#pragma mark MVKRefCountedDeviceObject
-
-void MVKRefCountedDeviceObject::retain() {
- lock_guard<mutex> lock(_refLock);
-
- _refCount++;
-}
-
-void MVKRefCountedDeviceObject::release() {
- if (decrementRetainCount()) { destroy(); }
-}
-
-// Decrements the reference count, and returns whether it's time to destroy this object.
-bool MVKRefCountedDeviceObject::decrementRetainCount() {
- lock_guard<mutex> lock(_refLock);
-
- if (_refCount > 0) { _refCount--; }
- return (_isDestroyed && _refCount == 0);
-}
-
-void MVKRefCountedDeviceObject::destroy() {
- if (markDestroyed()) { MVKBaseDeviceObject::destroy(); }
-}
-
-// Marks this object as destroyed, and returns whether no references are left outstanding.
-bool MVKRefCountedDeviceObject::markDestroyed() {
- lock_guard<mutex> lock(_refLock);
-
- _isDestroyed = true;
- return _refCount == 0;
-}
-
-
-#pragma mark -
#pragma mark Support functions
uint64_t mvkRecommendedMaxWorkingSetSize(id<MTLDevice> mtlDevice) {
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h
index ced14e9..da0a2dd 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h
@@ -20,6 +20,7 @@
#include "MVKDevice.h"
#include <vector>
+#include <mutex>
#import <Metal/Metal.h>
@@ -30,10 +31,13 @@
#pragma mark MVKDeviceMemory
/** Represents a Vulkan device-space memory allocation. */
-class MVKDeviceMemory : public MVKBaseDeviceObject {
+class MVKDeviceMemory : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT; }
+
/** Returns whether the memory is accessible from the host. */
inline bool isMemoryHostAccessible() {
#if MVK_IOS
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
index 224f651..e3be6ba 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
@@ -19,8 +19,10 @@
#include "MVKDeviceMemory.h"
#include "MVKBuffer.h"
#include "MVKImage.h"
-#include "mvk_datatypes.h"
+#include "MVKEnvironment.h"
+#include "mvk_datatypes.hpp"
#include "MVKFoundation.h"
+#include "MVKLogging.h"
#include <cstdlib>
#include <stdlib.h>
@@ -31,15 +33,15 @@
VkResult MVKDeviceMemory::map(VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) {
if ( !isMemoryHostAccessible() ) {
- return mvkNotifyErrorWithText(VK_ERROR_MEMORY_MAP_FAILED, "Private GPU-only memory cannot be mapped to host memory.");
+ return reportError(VK_ERROR_MEMORY_MAP_FAILED, "Private GPU-only memory cannot be mapped to host memory.");
}
if (_isMapped) {
- return mvkNotifyErrorWithText(VK_ERROR_MEMORY_MAP_FAILED, "Memory is already mapped. Call vkUnmapMemory() first.");
+ return reportError(VK_ERROR_MEMORY_MAP_FAILED, "Memory is already mapped. Call vkUnmapMemory() first.");
}
if ( !ensureMTLBuffer() && !ensureHostMemory() ) {
- return mvkNotifyErrorWithText(VK_ERROR_OUT_OF_HOST_MEMORY, "Could not allocate %llu bytes of host-accessible device memory.", _allocationSize);
+ return reportError(VK_ERROR_OUT_OF_HOST_MEMORY, "Could not allocate %llu bytes of host-accessible device memory.", _allocationSize);
}
_mapOffset = offset;
@@ -57,7 +59,7 @@
void MVKDeviceMemory::unmap() {
if ( !_isMapped ) {
- mvkNotifyErrorWithText(VK_ERROR_MEMORY_MAP_FAILED, "Memory is not mapped. Call vkMapMemory() first.");
+ reportError(VK_ERROR_MEMORY_MAP_FAILED, "Memory is not mapped. Call vkMapMemory() first.");
return;
}
@@ -108,11 +110,11 @@
// If a dedicated alloc, ensure this buffer is the one and only buffer
// I am dedicated to.
if (_isDedicated && (_buffers.empty() || _buffers[0] != mvkBuff) ) {
- return mvkNotifyErrorWithText(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not bind VkBuffer %p to a VkDeviceMemory dedicated to resource %p. A dedicated allocation may only be used with the resource it was dedicated to.", mvkBuff, getDedicatedResource() );
+ return reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not bind VkBuffer %p to a VkDeviceMemory dedicated to resource %p. A dedicated allocation may only be used with the resource it was dedicated to.", mvkBuff, getDedicatedResource() );
}
if (!ensureMTLBuffer() ) {
- return mvkNotifyErrorWithText(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not bind a VkBuffer to a VkDeviceMemory of size %llu bytes. The maximum memory-aligned size of a VkDeviceMemory that supports a VkBuffer is %llu bytes.", _allocationSize, _device->_pMetalFeatures->maxMTLBufferSize);
+ return reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not bind a VkBuffer to a VkDeviceMemory of size %llu bytes. The maximum memory-aligned size of a VkDeviceMemory that supports a VkBuffer is %llu bytes.", _allocationSize, _device->_pMetalFeatures->maxMTLBufferSize);
}
// In the dedicated case, we already saved the buffer we're going to use.
@@ -133,7 +135,7 @@
// If a dedicated alloc, ensure this image is the one and only image
// I am dedicated to.
if (_isDedicated && (_images.empty() || _images[0] != mvkImg) ) {
- return mvkNotifyErrorWithText(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not bind VkImage %p to a VkDeviceMemory dedicated to resource %p. A dedicated allocation may only be used with the resource it was dedicated to.", mvkImg, getDedicatedResource() );
+ return reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not bind VkImage %p to a VkDeviceMemory dedicated to resource %p. A dedicated allocation may only be used with the resource it was dedicated to.", mvkImg, getDedicatedResource() );
}
if (!_isDedicated)
@@ -201,7 +203,7 @@
MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
const VkMemoryAllocateInfo* pAllocateInfo,
- const VkAllocationCallbacks* pAllocator) : MVKBaseDeviceObject(device) {
+ const VkAllocationCallbacks* pAllocator) : MVKVulkanAPIDeviceObject(device) {
// Set Metal memory parameters
VkMemoryPropertyFlags vkMemProps = _device->_pMemoryProperties->memoryTypes[pAllocateInfo->memoryTypeIndex].propertyFlags;
_mtlResourceOptions = mvkMTLResourceOptionsFromVkMemoryPropertyFlags(vkMemProps);
@@ -233,13 +235,13 @@
#if MVK_MACOS
if (isMemoryHostCoherent() ) {
if (!((MVKImage*)dedicatedImage)->_isLinear) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Host-coherent VkDeviceMemory objects cannot be associated with optimal-tiling images."));
+ setConfigurationResult(reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Host-coherent VkDeviceMemory objects cannot be associated with optimal-tiling images."));
} else {
// Need to use the managed mode for images.
_mtlStorageMode = MTLStorageModeManaged;
// Nonetheless, we need a buffer to be able to map the memory at will.
if (!ensureMTLBuffer() ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not allocate a host-coherent VkDeviceMemory of size %llu bytes. The maximum memory-aligned size of a host-coherent VkDeviceMemory is %llu bytes.", _allocationSize, _device->_pMetalFeatures->maxMTLBufferSize));
+ setConfigurationResult(reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not allocate a host-coherent VkDeviceMemory of size %llu bytes. The maximum memory-aligned size of a host-coherent VkDeviceMemory is %llu bytes.", _allocationSize, _device->_pMetalFeatures->maxMTLBufferSize));
}
}
}
@@ -251,7 +253,7 @@
// If memory needs to be coherent it must reside in an MTLBuffer, since an open-ended map() must work.
if (isMemoryHostCoherent() && !ensureMTLBuffer() ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not allocate a host-coherent VkDeviceMemory of size %llu bytes. The maximum memory-aligned size of a host-coherent VkDeviceMemory is %llu bytes.", _allocationSize, _device->_pMetalFeatures->maxMTLBufferSize));
+ setConfigurationResult(reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not allocate a host-coherent VkDeviceMemory of size %llu bytes. The maximum memory-aligned size of a host-coherent VkDeviceMemory is %llu bytes.", _allocationSize, _device->_pMetalFeatures->maxMTLBufferSize));
}
if (dedicatedBuffer) {
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h
index b109348..1f91afc 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.h
@@ -26,10 +26,13 @@
#pragma mark MVKFramebuffer
/** Represents a Vulkan framebuffer. */
-class MVKFramebuffer : public MVKBaseDeviceObject {
+class MVKFramebuffer : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT; }
+
/** Returns the dimensions of this framebuffer. */
inline VkExtent2D getExtent2D() { return _extent; }
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm
index 57dd79d..c37c977 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKFramebuffer.mm
@@ -24,7 +24,7 @@
#pragma mark Construction
MVKFramebuffer::MVKFramebuffer(MVKDevice* device,
- const VkFramebufferCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
+ const VkFramebufferCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
_extent = { .width = pCreateInfo->width, .height = pCreateInfo->height };
_layerCount = pCreateInfo->layers;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
index ab68ab4..c3735ad 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
@@ -48,6 +48,9 @@
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT; }
+
/** Returns the Vulkan image type of this image. */
VkImageType getImageType();
@@ -246,10 +249,12 @@
#pragma mark MVKImageView
/** Represents a Vulkan image view. */
-class MVKImageView : public MVKRefCountedDeviceObject {
+class MVKImageView : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT; }
#pragma mark Metal
@@ -311,10 +316,13 @@
#pragma mark MVKSampler
/** Represents a Vulkan sampler. */
-class MVKSampler : public MVKRefCountedDeviceObject {
+class MVKSampler : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT; }
+
/** Returns the Metal sampler state. */
inline id<MTLSamplerState> getMTLSamplerState() { return _mtlSamplerState; }
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index d7b6891..2092f45 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -20,8 +20,9 @@
#include "MVKQueue.h"
#include "MVKSwapchain.h"
#include "MVKCommandBuffer.h"
-#include "mvk_datatypes.h"
+#include "mvk_datatypes.hpp"
#include "MVKFoundation.h"
+#include "MVKLogging.h"
#include "MVKEnvironment.h"
#include "MVKLogging.h"
#include "MVKCodec.h"
@@ -330,7 +331,7 @@
VkResult MVKImage::useIOSurface(IOSurfaceRef ioSurface) {
- if (!_device->_pMetalFeatures->ioSurfaces) { return mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkUseIOSurfaceMVK() : IOSurfaces are not supported on this platform."); }
+ if (!_device->_pMetalFeatures->ioSurfaces) { return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkUseIOSurfaceMVK() : IOSurfaces are not supported on this platform."); }
#if MVK_SUPPORT_IOSURFACE_BOOL
@@ -338,11 +339,11 @@
resetIOSurface();
if (ioSurface) {
- if (IOSurfaceGetWidth(ioSurface) != _extent.width) { return mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface width %zu does not match VkImage width %d.", IOSurfaceGetWidth(ioSurface), _extent.width); }
- if (IOSurfaceGetHeight(ioSurface) != _extent.height) { return mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface height %zu does not match VkImage height %d.", IOSurfaceGetHeight(ioSurface), _extent.height); }
- if (IOSurfaceGetBytesPerElement(ioSurface) != mvkMTLPixelFormatBytesPerBlock(_mtlPixelFormat)) { return mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface bytes per element %zu does not match VkImage bytes per element %d.", IOSurfaceGetBytesPerElement(ioSurface), mvkMTLPixelFormatBytesPerBlock(_mtlPixelFormat)); }
- if (IOSurfaceGetElementWidth(ioSurface) != mvkMTLPixelFormatBlockTexelSize(_mtlPixelFormat).width) { return mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface element width %zu does not match VkImage element width %d.", IOSurfaceGetElementWidth(ioSurface), mvkMTLPixelFormatBlockTexelSize(_mtlPixelFormat).width); }
- if (IOSurfaceGetElementHeight(ioSurface) != mvkMTLPixelFormatBlockTexelSize(_mtlPixelFormat).height) { return mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface element height %zu does not match VkImage element height %d.", IOSurfaceGetElementHeight(ioSurface), mvkMTLPixelFormatBlockTexelSize(_mtlPixelFormat).height); }
+ if (IOSurfaceGetWidth(ioSurface) != _extent.width) { return reportError(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface width %zu does not match VkImage width %d.", IOSurfaceGetWidth(ioSurface), _extent.width); }
+ if (IOSurfaceGetHeight(ioSurface) != _extent.height) { return reportError(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface height %zu does not match VkImage height %d.", IOSurfaceGetHeight(ioSurface), _extent.height); }
+ if (IOSurfaceGetBytesPerElement(ioSurface) != mvkMTLPixelFormatBytesPerBlock(_mtlPixelFormat)) { return reportError(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface bytes per element %zu does not match VkImage bytes per element %d.", IOSurfaceGetBytesPerElement(ioSurface), mvkMTLPixelFormatBytesPerBlock(_mtlPixelFormat)); }
+ if (IOSurfaceGetElementWidth(ioSurface) != mvkMTLPixelFormatBlockTexelSize(_mtlPixelFormat).width) { return reportError(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface element width %zu does not match VkImage element width %d.", IOSurfaceGetElementWidth(ioSurface), mvkMTLPixelFormatBlockTexelSize(_mtlPixelFormat).width); }
+ if (IOSurfaceGetElementHeight(ioSurface) != mvkMTLPixelFormatBlockTexelSize(_mtlPixelFormat).height) { return reportError(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface element height %zu does not match VkImage element height %d.", IOSurfaceGetElementHeight(ioSurface), mvkMTLPixelFormatBlockTexelSize(_mtlPixelFormat).height); }
_ioSurface = ioSurface;
CFRetain(_ioSurface);
@@ -473,7 +474,7 @@
// can upload the decompressed image data.
std::unique_ptr<MVKCodec> codec = mvkCreateCodec(getVkFormat());
if (!codec) {
- mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "A 3D texture used a compressed format that MoltenVK does not yet support.");
+ reportError(VK_ERROR_FORMAT_NOT_SUPPORTED, "A 3D texture used a compressed format that MoltenVK does not yet support.");
return;
}
VkSubresourceLayout destLayout;
@@ -545,20 +546,20 @@
MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MVKResource(device) {
if (pCreateInfo->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Metal does not allow uncompressed views of compressed images."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Metal does not allow uncompressed views of compressed images."));
}
#if MVK_IOS
if ( (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) && (mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatCompressed) ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, compressed formats may only be used with 2D images."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, compressed formats may only be used with 2D images."));
}
#else
if ( (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) && (mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatCompressed) && !mvkCanDecodeFormat(pCreateInfo->format) ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, compressed formats may only be used with 2D images."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, compressed formats may only be used with 2D images."));
}
#endif
if ( (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) && (mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatDepthStencil) ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, depth/stencil formats may only be used with 2D images."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, depth/stencil formats may only be used with 2D images."));
}
// Adjust the info components to be compatible with Metal, then use the modified versions
@@ -573,7 +574,7 @@
_mipLevels = max(pCreateInfo->mipLevels, minDim);
if ( (_mipLevels > 1) && (pCreateInfo->imageType == VK_IMAGE_TYPE_1D) ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, 1D images cannot use mipmaps. Setting mip levels to 1."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, 1D images cannot use mipmaps. Setting mip levels to 1."));
_mipLevels = 1;
}
@@ -587,9 +588,9 @@
if ( (_samples > 1) && (_mtlTextureType != MTLTextureType2DMultisample) &&
(pCreateInfo->imageType != VK_IMAGE_TYPE_2D || !_device->_pMetalFeatures->multisampleArrayTextures) ) {
if (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) {
- setConfigurationResult(mvkNotifyErrorWithText(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."));
} else {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : This version of Metal does not support multisampled array textures. Setting sample count to 1."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : This version of Metal does not support multisampled array textures. Setting sample count to 1."));
}
_samples = VK_SAMPLE_COUNT_1_BIT;
if (pCreateInfo->imageType == VK_IMAGE_TYPE_2D) {
@@ -597,7 +598,7 @@
}
}
if ( (_samples > 1) && (mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatCompressed) ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, multisampling cannot be used with compressed images. Setting sample count to 1."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, multisampling cannot be used with compressed images. Setting sample count to 1."));
_samples = VK_SAMPLE_COUNT_1_BIT;
}
@@ -623,33 +624,33 @@
if (pCreateInfo->tiling != VK_IMAGE_TILING_LINEAR) { return false; }
if (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, imageType must be VK_IMAGE_TYPE_2D."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, imageType must be VK_IMAGE_TYPE_2D."));
return false;
}
if (_isDepthStencilAttachment) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, format must not be a depth/stencil format."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, format must not be a depth/stencil format."));
return false;
}
if (_mipLevels > 1) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, mipLevels must be 1."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, mipLevels must be 1."));
return false;
}
if (_arrayLayers > 1) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, arrayLayers must be 1."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, arrayLayers must be 1."));
return false;
}
if (_samples > 1) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, samples must be VK_SAMPLE_COUNT_1_BIT."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, samples must be VK_SAMPLE_COUNT_1_BIT."));
return false;
}
#if MVK_MACOS
if ( mvkIsAnyFlagEnabled(_usage, (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, usage must not include VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, and/or VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, usage must not include VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, and/or VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT."));
return false;
}
#endif
@@ -775,7 +776,7 @@
// is constructed to validate image view capabilities
MVKImageView::MVKImageView(MVKDevice* device,
const VkImageViewCreateInfo* pCreateInfo,
- const MVKConfiguration* pAltMVKConfig) : MVKRefCountedDeviceObject(device) {
+ const MVKConfiguration* pAltMVKConfig) : MVKVulkanAPIDeviceObject(device) {
_image = (MVKImage*)pCreateInfo->image;
_usage = _image ? _image->_usage : 0;
@@ -830,12 +831,12 @@
// VK_KHR_maintenance1 supports taking 2D image views of 3D slices. No dice in Metal.
if ((viewType == VK_IMAGE_VIEW_TYPE_2D || viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY) && (imgType == VK_IMAGE_TYPE_3D)) {
if (pCreateInfo->subresourceRange.layerCount != image->_extent.depth) {
- mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImageView(): Metal does not fully support views on a subset of a 3D texture.");
+ reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImageView(): Metal does not fully support views on a subset of a 3D texture.");
}
if (!mvkAreFlagsEnabled(_usage, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImageView(): 2D views on 3D images are only supported for color attachments."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImageView(): 2D views on 3D images are only supported for color attachments."));
} else if (mvkIsAnyFlagEnabled(_usage, ~VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
- mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImageView(): 2D views on 3D images are only supported for color attachments.");
+ reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImageView(): 2D views on 3D images are only supported for color attachments.");
}
}
}
@@ -932,9 +933,9 @@
const char* errMsg = ("The value of %s::components) (%s, %s, %s, %s), when applied to a VkImageView, requires full component swizzling to be enabled both at the"
" time when the VkImageView is created and at the time any pipeline that uses that VkImageView is compiled. Full component swizzling can"
" be enabled via the MVKConfiguration::fullImageViewSwizzle config parameter or MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE environment variable.");
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, errMsg, vkCmd,
- mvkVkComponentSwizzleName(components.r), mvkVkComponentSwizzleName(components.g),
- mvkVkComponentSwizzleName(components.b), mvkVkComponentSwizzleName(components.a)));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, errMsg, vkCmd,
+ mvkVkComponentSwizzleName(components.r), mvkVkComponentSwizzleName(components.g),
+ mvkVkComponentSwizzleName(components.b), mvkVkComponentSwizzleName(components.a)));
}
}
@@ -999,7 +1000,7 @@
if (_device->_pMetalFeatures->depthSampleCompare) {
mtlSampDesc.compareFunctionMVK = mvkMTLCompareFunctionFromVkCompareOp(pCreateInfo->compareOp);
} else {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateSampler(): Depth texture samplers do not support the comparison of the pixel value against a reference value."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateSampler(): Depth texture samplers do not support the comparison of the pixel value against a reference value."));
}
}
@@ -1021,7 +1022,7 @@
}
// Constructs an instance on the specified image.
-MVKSampler::MVKSampler(MVKDevice* device, const VkSamplerCreateInfo* pCreateInfo) : MVKRefCountedDeviceObject(device) {
+MVKSampler::MVKSampler(MVKDevice* device, const VkSamplerCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
_mtlSamplerState = [getMTLDevice() newSamplerStateWithDescriptor: getMTLSamplerDescriptor(pCreateInfo)];
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.h b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.h
index ebed273..22551cd 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.h
@@ -18,16 +18,19 @@
#pragma once
+#include "MVKEnvironment.h"
#include "MVKLayers.h"
-#include "MVKSurface.h"
#include "MVKBaseObject.h"
#include "vk_mvk_moltenvk.h"
#include <vector>
#include <unordered_map>
#include <string>
+#include <mutex>
class MVKPhysicalDevice;
class MVKDevice;
+class MVKSurface;
+class MVKDebugReportCallback;
/** Tracks info about entry point function pointer addresses. */
@@ -48,10 +51,19 @@
#pragma mark MVKInstance
/** Represents a Vulkan instance. */
-class MVKInstance : public MVKDispatchableObject {
+class MVKInstance : public MVKDispatchableVulkanAPIObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; }
+
+ /** Returns a pointer to the Vulkan instance. */
+ MVKInstance* getInstance() override { return this; }
+
+ /** Returns a pointer to the layer manager. */
+ inline MVKLayerManager* getLayerManager() { return MVKLayerManager::globalManager(); }
+
/** Returns the function pointer corresponding to the named entry point, or NULL if it doesn't exist. */
PFN_vkVoidFunction getProcAddr(const char* pName);
@@ -72,14 +84,31 @@
/** Returns the driver layer. */
MVKLayer* getDriverLayer() { return MVKLayerManager::globalManager()->getDriverLayer(); }
- /** Creates and returns a new object. */
MVKSurface* createSurface(const Vk_PLATFORM_SurfaceCreateInfoMVK* pCreateInfo,
const VkAllocationCallbacks* pAllocator);
- /** Destroys the specified object. */
void destroySurface(MVKSurface* mvkSrfc,
const VkAllocationCallbacks* pAllocator);
+ MVKDebugReportCallback* createDebugReportCallback(const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator);
+
+ void destroyDebugReportCallback(MVKDebugReportCallback* mvkDRCB,
+ const VkAllocationCallbacks* pAllocator);
+
+ void debugReportMessage(VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objectType,
+ uint64_t object,
+ size_t location,
+ int32_t messageCode,
+ const char* pLayerPrefix,
+ const char* pMessage);
+
+ void debugReportMessage(MVKVulkanAPIObject* mvkAPIObj, int aslLvl, const char* pMessage);
+
+ /** Returns whether debug report callbacks are being used. */
+ bool hasDebugReportCallbacks() { return _hasDebugReportCallbacks; }
+
/** Returns the MoltenVK configuration settings. */
const MVKConfiguration* getMoltenVKConfiguration() { return &_mvkConfig; }
@@ -115,6 +144,8 @@
friend MVKDevice;
void initProcAddrs();
+ void initCreationDebugReportCallbacks(const VkInstanceCreateInfo* pCreateInfo);
+ VkDebugReportFlagsEXT getVkDebugReportFlagsFromASLLevel(int aslLvl);
MVKEntryPoint* getEntryPoint(const char* pName);
void initConfig();
void logVersions();
@@ -124,5 +155,40 @@
VkApplicationInfo _appInfo;
std::vector<MVKPhysicalDevice*> _physicalDevices;
std::unordered_map<std::string, MVKEntryPoint> _entryPoints;
+ std::vector<MVKDebugReportCallback*> _debugReportCallbacks;
+ std::mutex _drcbLock;
+ bool _hasDebugReportCallbacks;
+ bool _useCreationCallbacks;
+ const char* _debugReportCallbackLayerPrefix;
+};
+
+
+#pragma mark -
+#pragma mark MVKDebugReportCallback
+
+/** Represents a Vulkan Debug Report callback. */
+class MVKDebugReportCallback : public MVKVulkanAPIObject {
+
+public:
+
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT; }
+
+ /** Returns a pointer to the Vulkan instance. */
+ MVKInstance* getInstance() override { return _mvkInstance; }
+
+ MVKDebugReportCallback(MVKInstance* mvkInstance,
+ const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
+ bool isCreationCallback) :
+ _mvkInstance(mvkInstance), _info(*pCreateInfo), _isCreationCallback(isCreationCallback) {
+ _info.pNext = nullptr;
+ }
+
+protected:
+ friend MVKInstance;
+
+ MVKInstance* _mvkInstance;
+ VkDebugReportCallbackCreateInfoEXT _info;
+ bool _isCreationCallback;
};
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
index e0a3d4b..a27d8eb 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
@@ -23,6 +23,7 @@
#include "MVKEnvironment.h"
#include "MVKSurface.h"
#include "MVKOSExtensions.h"
+#include "MVKLogging.h"
using namespace std;
@@ -79,6 +80,78 @@
mvkSrfc->destroy();
}
+MVKDebugReportCallback* MVKInstance::createDebugReportCallback(const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator) {
+ lock_guard<mutex> lock(_drcbLock);
+
+ MVKDebugReportCallback* mvkDRCB = new MVKDebugReportCallback(this, pCreateInfo, _useCreationCallbacks);
+ _debugReportCallbacks.push_back(mvkDRCB);
+ _hasDebugReportCallbacks = true;
+ return mvkDRCB;
+}
+
+void MVKInstance::destroyDebugReportCallback(MVKDebugReportCallback* mvkDRCB,
+ const VkAllocationCallbacks* pAllocator) {
+ lock_guard<mutex> lock(_drcbLock);
+
+ mvkRemoveAllOccurances(_debugReportCallbacks, mvkDRCB);
+ _hasDebugReportCallbacks = (_debugReportCallbacks.size() != 0);
+ mvkDRCB->destroy();
+}
+
+void MVKInstance::debugReportMessage(VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objectType,
+ uint64_t object,
+ size_t location,
+ int32_t messageCode,
+ const char* pLayerPrefix,
+ const char* pMessage) {
+
+ // Fail fast to avoid further unnecessary processing and locking.
+ if ( !(_hasDebugReportCallbacks) ) { return; }
+
+ lock_guard<mutex> lock(_drcbLock);
+
+ for (auto mvkDRCB : _debugReportCallbacks) {
+ auto& drbcInfo = mvkDRCB->_info;
+ if (drbcInfo.pfnCallback && mvkIsAnyFlagEnabled(drbcInfo.flags, flags) && (mvkDRCB->_isCreationCallback == _useCreationCallbacks)) {
+ drbcInfo.pfnCallback(flags, objectType, object, location, messageCode, pLayerPrefix, pMessage, drbcInfo.pUserData);
+ }
+ }
+}
+
+void MVKInstance::debugReportMessage(MVKVulkanAPIObject* mvkAPIObj, int aslLvl, const char* pMessage) {
+
+ // Fail fast to avoid further unnecessary processing and locking.
+ if ( !(_hasDebugReportCallbacks) ) { return; }
+
+ VkDebugReportFlagsEXT flags = getVkDebugReportFlagsFromASLLevel(aslLvl);
+ uint64_t object = (uint64_t)(mvkAPIObj ? mvkAPIObj->getVkHandle() : nullptr);
+ VkDebugReportObjectTypeEXT objectType = mvkAPIObj ? mvkAPIObj->getVkDebugReportObjectType() : VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
+ debugReportMessage(flags, objectType, object, 0, 0, _debugReportCallbackLayerPrefix, pMessage);
+}
+
+VkDebugReportFlagsEXT MVKInstance::getVkDebugReportFlagsFromASLLevel(int aslLvl) {
+ switch (aslLvl) {
+ case ASL_LEVEL_DEBUG:
+ return VK_DEBUG_REPORT_DEBUG_BIT_EXT;
+
+ case ASL_LEVEL_INFO:
+ case ASL_LEVEL_NOTICE:
+ return VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+
+ case ASL_LEVEL_WARNING:
+ return VK_DEBUG_REPORT_WARNING_BIT_EXT;
+
+ case ASL_LEVEL_ERR:
+ case ASL_LEVEL_CRIT:
+ case ASL_LEVEL_ALERT:
+ case ASL_LEVEL_EMERG:
+ default:
+ return VK_DEBUG_REPORT_ERROR_BIT_EXT;
+ }
+}
+
#pragma mark Object Creation
@@ -130,7 +203,9 @@
#endif // MVK_IOS
}
-MVKInstance::MVKInstance(const VkInstanceCreateInfo* pCreateInfo) {
+MVKInstance::MVKInstance(const VkInstanceCreateInfo* pCreateInfo) : _enabledExtensions(this) {
+
+ initCreationDebugReportCallbacks(pCreateInfo); // Do before any creation activities
_appInfo.apiVersion = MVK_VULKAN_API_VERSION; // Default
mvkSetOrClear(&_appInfo, pCreateInfo->pApplicationInfo);
@@ -147,10 +222,10 @@
if (MVK_VULKAN_API_VERSION_CONFORM(MVK_VULKAN_API_VERSION) <
MVK_VULKAN_API_VERSION_CONFORM(_appInfo.apiVersion)) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INCOMPATIBLE_DRIVER,
- "Request for Vulkan version %s is not compatible with supported version %s.",
- mvkGetVulkanVersionString(_appInfo.apiVersion).c_str(),
- mvkGetVulkanVersionString(MVK_VULKAN_API_VERSION).c_str()));
+ setConfigurationResult(reportError(VK_ERROR_INCOMPATIBLE_DRIVER,
+ "Request for Vulkan version %s is not compatible with supported version %s.",
+ mvkGetVulkanVersionString(_appInfo.apiVersion).c_str(),
+ mvkGetVulkanVersionString(MVK_VULKAN_API_VERSION).c_str()));
}
// Populate the array of physical GPU devices
@@ -160,18 +235,38 @@
_physicalDevices.push_back(new MVKPhysicalDevice(this, mtlDev));
}
if (_physicalDevices.empty()) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INCOMPATIBLE_DRIVER, "Vulkan is not supported on this device. MoltenVK requires Metal, which is not available on this device."));
+ setConfigurationResult(reportError(VK_ERROR_INCOMPATIBLE_DRIVER, "Vulkan is not supported on this device. MoltenVK requires Metal, which is not available on this device."));
}
- string logMsg = "Created VkInstance with the following Vulkan extensions enabled:";
- logMsg += _enabledExtensions.enabledNamesString("\n\t\t", true);
- MVKLogInfo("%s", logMsg.c_str());
+ MVKLogInfo("Created VkInstance with the following %d Vulkan extensions enabled:%s",
+ _enabledExtensions.getEnabledCount(),
+ _enabledExtensions.enabledNamesString("\n\t\t", true).c_str());
+
+ _useCreationCallbacks = false;
+}
+
+void MVKInstance::initCreationDebugReportCallbacks(const VkInstanceCreateInfo* pCreateInfo) {
+ _useCreationCallbacks = true;
+ _hasDebugReportCallbacks = false;
+ _debugReportCallbackLayerPrefix = getDriverLayer()->getName();
+
+ MVKVkAPIStructHeader* next = (MVKVkAPIStructHeader*)pCreateInfo->pNext;
+ while (next) {
+ switch (next->sType) {
+ case VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT:
+ createDebugReportCallback((VkDebugReportCallbackCreateInfoEXT*)next, nullptr);
+ break;
+ default:
+ break;
+ }
+ next = (MVKVkAPIStructHeader*)next->pNext;
+ }
}
#define ADD_ENTRY_POINT(func, ext1, ext2, isDev) _entryPoints[""#func] = { (PFN_vkVoidFunction)&func, ext1, ext2, isDev }
#define ADD_INST_ENTRY_POINT(func) ADD_ENTRY_POINT(func, nullptr, nullptr, false)
-#define ADD_DVC_ENTRY_POINT(func) ADD_ENTRY_POINT(func, nullptr, nullptr, true)
+#define ADD_DVC_ENTRY_POINT(func) ADD_ENTRY_POINT(func, nullptr, nullptr, true)
#define ADD_INST_EXT_ENTRY_POINT(func, EXT) ADD_ENTRY_POINT(func, VK_ ##EXT ##_EXTENSION_NAME, nullptr, false)
#define ADD_DVC_EXT_ENTRY_POINT(func, EXT) ADD_ENTRY_POINT(func, VK_ ##EXT ##_EXTENSION_NAME, nullptr, true)
@@ -179,7 +274,7 @@
#define ADD_INST_EXT2_ENTRY_POINT(func, EXT1, EXT2) ADD_ENTRY_POINT(func, VK_ ##EXT1 ##_EXTENSION_NAME, VK_ ##EXT2 ##_EXTENSION_NAME, false)
#define ADD_DVC_EXT2_ENTRY_POINT(func, EXT1, EXT2) ADD_ENTRY_POINT(func, VK_ ##EXT1 ##_EXTENSION_NAME, VK_ ##EXT2 ##_EXTENSION_NAME, true)
-/** Initializes the function pointer map. */
+// Initializes the function pointer map.
void MVKInstance::initProcAddrs() {
// Instance functions
@@ -335,6 +430,9 @@
ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfacePresentModesKHR, KHR_SURFACE);
ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceCapabilities2KHR, KHR_GET_SURFACE_CAPABILITIES_2);
ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceFormats2KHR, KHR_GET_SURFACE_CAPABILITIES_2);
+ ADD_INST_EXT_ENTRY_POINT(vkCreateDebugReportCallbackEXT, EXT_DEBUG_REPORT);
+ ADD_INST_EXT_ENTRY_POINT(vkDestroyDebugReportCallbackEXT, EXT_DEBUG_REPORT);
+ ADD_INST_EXT_ENTRY_POINT(vkDebugReportMessageEXT, EXT_DEBUG_REPORT);
#ifdef VK_USE_PLATFORM_IOS_MVK
ADD_INST_EXT_ENTRY_POINT(vkCreateIOSSurfaceMVK, MVK_IOS_SURFACE);
@@ -382,16 +480,14 @@
}
void MVKInstance::logVersions() {
- string logMsg = "MoltenVK version ";
- logMsg += mvkGetMoltenVKVersionString(MVK_VERSION);
- logMsg += ". Vulkan version ";
- logMsg += mvkGetVulkanVersionString(MVK_VULKAN_API_VERSION);
- logMsg += ".\n\tThe following Vulkan extensions are supported:";
- logMsg += getDriverLayer()->getSupportedExtensions()->enabledNamesString("\n\t\t", true);
- MVKLogInfo("%s", logMsg.c_str());
+ MVKExtensionList* pExtns = getDriverLayer()->getSupportedExtensions();
+ MVKLogInfo("MoltenVK version %s. Vulkan version %s.\n\tThe following %d Vulkan extensions are supported:%s",
+ mvkGetMoltenVKVersionString(MVK_VERSION).c_str(),
+ mvkGetVulkanVersionString(MVK_VULKAN_API_VERSION).c_str(),
+ pExtns->getEnabledCount(),
+ pExtns->enabledNamesString("\n\t\t", true).c_str());
}
-// Init config.
void MVKInstance::initConfig() {
MVK_SET_FROM_ENV_OR_BUILD_BOOL( _mvkConfig.debugMode, MVK_DEBUG);
MVK_SET_FROM_ENV_OR_BUILD_BOOL( _mvkConfig.shaderConversionFlipVertexY, MVK_CONFIG_SHADER_CONVERSION_FLIP_VERTEX_Y);
@@ -416,13 +512,17 @@
VkResult result = VK_SUCCESS;
for (uint32_t i = 0; i < count; i++) {
if ( !MVKLayerManager::globalManager()->getLayerNamed(names[i]) ) {
- result = mvkNotifyErrorWithText(VK_ERROR_LAYER_NOT_PRESENT, "Vulkan layer %s is not supported.", names[i]);
+ result = reportError(VK_ERROR_LAYER_NOT_PRESENT, "Vulkan layer %s is not supported.", names[i]);
}
}
return result;
}
MVKInstance::~MVKInstance() {
+ _useCreationCallbacks = true;
mvkDestroyContainerContents(_physicalDevices);
+
+ lock_guard<mutex> lock(_drcbLock);
+ mvkDestroyContainerContents(_debugReportCallbacks);
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
index 6f76d07..a685e4c 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
@@ -42,10 +42,13 @@
};
/** Represents a Vulkan pipeline layout. */
-class MVKPipelineLayout : public MVKBaseDeviceObject {
+class MVKPipelineLayout : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT; }
+
/** Binds descriptor sets to a command encoder. */
void bindDescriptorSets(MVKCommandEncoder* cmdEncoder,
MVKVector<MVKDescriptorSet*>& descriptorSets,
@@ -113,10 +116,13 @@
static const uint32_t kMVKTessEvalNumReservedBuffers = 3;
/** Represents an abstract Vulkan pipeline. */
-class MVKPipeline : public MVKBaseDeviceObject {
+class MVKPipeline : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT; }
+
/** Returns the order of stages in this pipeline. Draws and dispatches must encode this pipeline once per stage. */
virtual void getStages(MVKVector<uint32_t>& stages) = 0;
@@ -130,7 +136,7 @@
bool fullImageViewSwizzle() const { return _fullImageViewSwizzle; }
/** Constructs an instance for the device. layout, and parent (which may be NULL). */
- MVKPipeline(MVKDevice* device, MVKPipelineCache* pipelineCache, MVKPipeline* parent) : MVKBaseDeviceObject(device),
+ MVKPipeline(MVKDevice* device, MVKPipelineCache* pipelineCache, MVKPipeline* parent) : MVKVulkanAPIDeviceObject(device),
_pipelineCache(pipelineCache),
_fullImageViewSwizzle(device->_pMVKConfig->fullImageViewSwizzle) {}
@@ -301,10 +307,13 @@
#pragma mark MVKPipelineCache
/** Represents a Vulkan pipeline cache. */
-class MVKPipelineCache : public MVKBaseDeviceObject {
+class MVKPipelineCache : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT; }
+
/**
* If pData is not null, serializes at most pDataSize bytes of the contents of the cache into that
* memory location, and returns the number of bytes serialized in pDataSize. If pData is null,
@@ -360,9 +369,9 @@
#pragma mark Construction
- MVKRenderPipelineCompiler(MVKDevice* device) : MVKMetalCompiler(device) {
+ MVKRenderPipelineCompiler(MVKVulkanAPIDeviceObject* owner) : MVKMetalCompiler(owner) {
_compilerType = "Render pipeline";
- _pPerformanceTracker = &_device->_performanceStatistics.shaderCompilation.pipelineCompile;
+ _pPerformanceTracker = &_owner->getDevice()->_performanceStatistics.shaderCompilation.pipelineCompile;
}
~MVKRenderPipelineCompiler() override;
@@ -405,9 +414,9 @@
#pragma mark Construction
- MVKComputePipelineCompiler(MVKDevice* device) : MVKMetalCompiler(device) {
+ MVKComputePipelineCompiler(MVKVulkanAPIDeviceObject* owner) : MVKMetalCompiler(owner) {
_compilerType = "Compute pipeline";
- _pPerformanceTracker = &_device->_performanceStatistics.shaderCompilation.pipelineCompile;
+ _pPerformanceTracker = &_owner->getDevice()->_performanceStatistics.shaderCompilation.pipelineCompile;
}
~MVKComputePipelineCompiler() override;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
index 78ce185..6f307b1 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
@@ -24,7 +24,7 @@
#include "MVKOSExtensions.h"
#include "MVKStrings.h"
#include "MTLRenderPipelineDescriptor+MoltenVK.h"
-#include "mvk_datatypes.h"
+#include "mvk_datatypes.hpp"
#include <cereal/archives/binary.hpp>
#include <cereal/types/string.hpp>
@@ -107,7 +107,7 @@
}
MVKPipelineLayout::MVKPipelineLayout(MVKDevice* device,
- const VkPipelineLayoutCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
+ const VkPipelineLayoutCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
// Add descriptor set layouts, accumulating the resource index offsets used by the
// corresponding DSL, and associating the current accumulated resource index offsets
@@ -277,12 +277,12 @@
std::string reflectErrorLog;
if (_pTessCtlSS && _pTessEvalSS) {
if (!getTessReflectionData(((MVKShaderModule*)_pTessCtlSS->module)->getSPIRV(), _pTessCtlSS->pName, ((MVKShaderModule*)_pTessEvalSS->module)->getSPIRV(), _pTessEvalSS->pName, reflectData, reflectErrorLog) ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Failed to reflect tessellation shaders: %s", reflectErrorLog.c_str()));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Failed to reflect tessellation shaders: %s", reflectErrorLog.c_str()));
return;
}
// Unfortunately, we can't support line tessellation at this time.
if (reflectData.patchKind == spv::ExecutionModeIsolines) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "Metal does not support isoline tessellation."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "Metal does not support isoline tessellation."));
return;
}
}
@@ -326,7 +326,7 @@
if (_device->_enabledFeatures.depthClamp) {
_mtlDepthClipMode = MTLDepthClipModeClamp;
} else {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "This device does not support depth clamping."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "This device does not support depth clamping."));
}
}
}
@@ -363,9 +363,8 @@
// Either returns an existing pipeline state or compiles a new one.
id<MTLRenderPipelineState> MVKGraphicsPipeline::getOrCompilePipeline(MTLRenderPipelineDescriptor* plDesc, id<MTLRenderPipelineState>& plState) {
if (!plState) {
- MVKRenderPipelineCompiler* plc = new MVKRenderPipelineCompiler(_device);
+ MVKRenderPipelineCompiler* plc = new MVKRenderPipelineCompiler(this);
plState = plc->newMTLRenderPipelineState(plDesc); // retained
- setConfigurationResult(plc->getConfigurationResult());
plc->destroy();
}
return plState;
@@ -374,9 +373,8 @@
// Either returns an existing pipeline state or compiles a new one.
id<MTLComputePipelineState> MVKGraphicsPipeline::getOrCompilePipeline(MTLComputePipelineDescriptor* plDesc, id<MTLComputePipelineState>& plState) {
if (!plState) {
- MVKComputePipelineCompiler* plc = new MVKComputePipelineCompiler(_device);
+ MVKComputePipelineCompiler* plc = new MVKComputePipelineCompiler(this);
plState = plc->newMTLComputePipelineState(plDesc); // retained
- setConfigurationResult(plc->getConfigurationResult());
plc->destroy();
}
return plState;
@@ -551,7 +549,7 @@
std::string errorLog;
// Unfortunately, MoltenVKShaderConverter doesn't know about MVKVector, so we can't use that here.
if (!getShaderOutputs(((MVKShaderModule*)_pVertexSS->module)->getSPIRV(), spv::ExecutionModelVertex, _pVertexSS->pName, vtxOutputs, errorLog) ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Failed to get vertex outputs: %s", errorLog.c_str()));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Failed to get vertex outputs: %s", errorLog.c_str()));
return nil;
}
@@ -590,7 +588,7 @@
std::vector<SPIRVShaderOutput> tcOutputs;
std::string errorLog;
if (!getShaderOutputs(((MVKShaderModule*)_pTessCtlSS->module)->getSPIRV(), spv::ExecutionModelTessellationControl, _pTessCtlSS->pName, tcOutputs, errorLog) ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Failed to get tessellation control outputs: %s", errorLog.c_str()));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Failed to get tessellation control outputs: %s", errorLog.c_str()));
return nil;
}
@@ -705,7 +703,7 @@
addVertexInputToShaderConverterContext(shaderContext, pCreateInfo);
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pVertexSS->module)->getMTLFunction(&shaderContext, _pVertexSS->pSpecializationInfo, _pipelineCache).mtlFunction;
if ( !mtlFunction ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader function could not be compiled into pipeline. See previous logged error."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader function could not be compiled into pipeline. See previous logged error."));
return false;
}
plDesc.vertexFunction = mtlFunction;
@@ -714,16 +712,16 @@
_needsVertexOutputBuffer = shaderContext.options.needsOutputBuffer;
// If we need the auxiliary buffer and there's no place to put it, we're in serious trouble.
if (_needsVertexAuxBuffer && _auxBufferIndex.stages[kMVKShaderStageVertex] >= _device->_pMetalFeatures->maxPerStageBufferCount - vbCnt) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader requires auxiliary buffer, but there is no free slot to pass it."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader requires auxiliary buffer, but there is no free slot to pass it."));
return false;
}
// Ditto captured output buffer.
if (_needsVertexOutputBuffer && _outputBufferIndex.stages[kMVKShaderStageVertex] >= _device->_pMetalFeatures->maxPerStageBufferCount - vbCnt) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader requires output buffer, but there is no free slot to pass it."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader requires output buffer, but there is no free slot to pass it."));
return false;
}
if (_needsVertexOutputBuffer && _indirectParamsIndex.stages[kMVKShaderStageVertex] >= _device->_pMetalFeatures->maxPerStageBufferCount - vbCnt) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader requires indirect parameters buffer, but there is no free slot to pass it."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader requires indirect parameters buffer, but there is no free slot to pass it."));
return false;
}
return true;
@@ -741,7 +739,7 @@
addPrevStageOutputToShaderConverterContext(shaderContext, vtxOutputs);
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pTessCtlSS->module)->getMTLFunction(&shaderContext, _pTessCtlSS->pSpecializationInfo, _pipelineCache).mtlFunction;
if ( !mtlFunction ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader function could not be compiled into pipeline. See previous logged error."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader function could not be compiled into pipeline. See previous logged error."));
return false;
}
plDesc.computeFunction = mtlFunction;
@@ -750,23 +748,23 @@
_needsTessCtlPatchOutputBuffer = shaderContext.options.needsPatchOutputBuffer;
_needsTessCtlInput = shaderContext.options.needsInputThreadgroupMem;
if (_needsTessCtlAuxBuffer && _auxBufferIndex.stages[kMVKShaderStageTessCtl] >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires auxiliary buffer, but there is no free slot to pass it."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires auxiliary buffer, but there is no free slot to pass it."));
return false;
}
if (_indirectParamsIndex.stages[kMVKShaderStageTessCtl] >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires indirect parameters buffer, but there is no free slot to pass it."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires indirect parameters buffer, but there is no free slot to pass it."));
return false;
}
if (_needsTessCtlOutputBuffer && _outputBufferIndex.stages[kMVKShaderStageTessCtl] >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires per-vertex output buffer, but there is no free slot to pass it."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires per-vertex output buffer, but there is no free slot to pass it."));
return false;
}
if (_needsTessCtlPatchOutputBuffer && _tessCtlPatchOutputBufferIndex >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires per-patch output buffer, but there is no free slot to pass it."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires per-patch output buffer, but there is no free slot to pass it."));
return false;
}
if (_tessCtlLevelBufferIndex >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires tessellation level output buffer, but there is no free slot to pass it."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires tessellation level output buffer, but there is no free slot to pass it."));
return false;
}
return true;
@@ -781,7 +779,7 @@
addPrevStageOutputToShaderConverterContext(shaderContext, tcOutputs);
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pTessEvalSS->module)->getMTLFunction(&shaderContext, _pTessEvalSS->pSpecializationInfo, _pipelineCache).mtlFunction;
if ( !mtlFunction ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Tessellation evaluation shader function could not be compiled into pipeline. See previous logged error."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation evaluation shader function could not be compiled into pipeline. See previous logged error."));
return false;
}
// Yeah, you read that right. Tess. eval functions are a kind of vertex function in Metal.
@@ -790,7 +788,7 @@
_needsTessEvalAuxBuffer = shaderContext.options.needsAuxBuffer;
// If we need the auxiliary buffer and there's no place to put it, we're in serious trouble.
if (_needsTessEvalAuxBuffer && _auxBufferIndex.stages[kMVKShaderStageTessEval] >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessEvalNumReservedBuffers) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Tessellation evaluation shader requires auxiliary buffer, but there is no free slot to pass it."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation evaluation shader requires auxiliary buffer, but there is no free slot to pass it."));
return false;
}
return true;
@@ -804,13 +802,13 @@
shaderContext.options.shouldCaptureOutput = false;
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pFragmentSS->module)->getMTLFunction(&shaderContext, _pFragmentSS->pSpecializationInfo, _pipelineCache).mtlFunction;
if ( !mtlFunction ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Fragment shader function could not be compiled into pipeline. See previous logged error."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Fragment shader function could not be compiled into pipeline. See previous logged error."));
return false;
}
plDesc.fragmentFunction = mtlFunction;
_needsFragmentAuxBuffer = shaderContext.options.needsAuxBuffer;
if (_needsFragmentAuxBuffer && _auxBufferIndex.stages[kMVKShaderStageFragment] >= _device->_pMetalFeatures->maxPerStageBufferCount) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Fragment shader requires auxiliary buffer, but there is no free slot to pass it."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Fragment shader requires auxiliary buffer, but there is no free slot to pass it."));
return false;
}
}
@@ -847,7 +845,7 @@
for (uint32_t j = 0; j < vbCnt; j++, pVKVB++) {
if (pVKVB->binding == pVKVA->binding) {
if (pVKVA->offset >= pVKVB->stride) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Under Metal, vertex attribute offsets must not exceed the vertex buffer stride."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Under Metal, vertex attribute offsets must not exceed the vertex buffer stride."));
return false;
}
break;
@@ -871,7 +869,7 @@
// Vulkan allows any stride, but Metal only allows multiples of 4.
// TODO: We should try to expand the buffer to the required alignment in that case.
if ((pVKVB->stride % 4) != 0) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Under Metal, vertex buffer strides must be aligned to four bytes."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Under Metal, vertex buffer strides must be aligned to four bytes."));
return false;
}
@@ -1168,16 +1166,15 @@
_mtlPipelineState = nil;
if (shaderFunc.mtlFunction) {
- MVKComputePipelineCompiler* plc = new MVKComputePipelineCompiler(_device);
+ MVKComputePipelineCompiler* plc = new MVKComputePipelineCompiler(this);
_mtlPipelineState = plc->newMTLComputePipelineState(shaderFunc.mtlFunction); // retained
- setConfigurationResult(plc->getConfigurationResult());
plc->destroy();
} else {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Compute shader function could not be compiled into pipeline. See previous logged error."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Compute shader function could not be compiled into pipeline. See previous logged error."));
}
if (_needsAuxBuffer && _auxBufferIndex.stages[kMVKShaderStageCompute] > _device->_pMetalFeatures->maxPerStageBufferCount) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Compute shader requires auxiliary buffer, but there is no free slot to pass it."));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Compute shader requires auxiliary buffer, but there is no free slot to pass it."));
}
}
@@ -1227,7 +1224,7 @@
MVKShaderLibraryCache* MVKPipelineCache::getShaderLibraryCache(MVKShaderModuleKey smKey) {
MVKShaderLibraryCache* slCache = _shaderCache[smKey];
if ( !slCache ) {
- slCache = new MVKShaderLibraryCache(_device);
+ slCache = new MVKShaderLibraryCache(this);
_shaderCache[smKey] = slCache;
}
return slCache;
@@ -1311,7 +1308,11 @@
// Helper class to iterate through the shader libraries in a shader library cache in order to serialize them.
// Needs to support input of null shader library cache.
-class MVKShaderCacheIterator : MVKBaseObject {
+class MVKShaderCacheIterator : public MVKBaseObject {
+
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _pSLCache->getVulkanAPIObject(); };
+
protected:
friend MVKPipelineCache;
@@ -1361,7 +1362,7 @@
} catch (cereal::Exception& ex) {
*pDataSize = 0;
- return mvkNotifyErrorWithText(VK_INCOMPLETE, "Error writing pipeline cache data: %s", ex.what());
+ return reportError(VK_INCOMPLETE, "Error writing pipeline cache data: %s", ex.what());
}
}
@@ -1475,7 +1476,7 @@
}
} catch (cereal::Exception& ex) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_SUCCESS, "Error reading pipeline cache data: %s", ex.what()));
+ setConfigurationResult(reportError(VK_SUCCESS, "Error reading pipeline cache data: %s", ex.what()));
}
}
@@ -1499,7 +1500,7 @@
#pragma mark Construction
-MVKPipelineCache::MVKPipelineCache(MVKDevice* device, const VkPipelineCacheCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
+MVKPipelineCache::MVKPipelineCache(MVKDevice* device, const VkPipelineCacheCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
readData(pCreateInfo);
}
@@ -1516,11 +1517,11 @@
unique_lock<mutex> lock(_completionLock);
compile(lock, ^{
- [getMTLDevice() newRenderPipelineStateWithDescriptor: mtlRPLDesc
- completionHandler: ^(id<MTLRenderPipelineState> ps, NSError* error) {
- bool isLate = compileComplete(ps, error);
- if (isLate) { destroy(); }
- }];
+ [_owner->getMTLDevice() newRenderPipelineStateWithDescriptor: mtlRPLDesc
+ completionHandler: ^(id<MTLRenderPipelineState> ps, NSError* error) {
+ bool isLate = compileComplete(ps, error);
+ if (isLate) { destroy(); }
+ }];
});
return [_mtlRenderPipelineState retain];
@@ -1547,11 +1548,11 @@
unique_lock<mutex> lock(_completionLock);
compile(lock, ^{
- [getMTLDevice() newComputePipelineStateWithFunction: mtlFunction
- completionHandler: ^(id<MTLComputePipelineState> ps, NSError* error) {
- bool isLate = compileComplete(ps, error);
- if (isLate) { destroy(); }
- }];
+ [_owner->getMTLDevice() newComputePipelineStateWithFunction: mtlFunction
+ completionHandler: ^(id<MTLComputePipelineState> ps, NSError* error) {
+ bool isLate = compileComplete(ps, error);
+ if (isLate) { destroy(); }
+ }];
});
return [_mtlComputePipelineState retain];
@@ -1561,12 +1562,12 @@
unique_lock<mutex> lock(_completionLock);
compile(lock, ^{
- [getMTLDevice() newComputePipelineStateWithDescriptor: plDesc
- options: MTLPipelineOptionNone
- completionHandler: ^(id<MTLComputePipelineState> ps, MTLComputePipelineReflection*, NSError* error) {
- bool isLate = compileComplete(ps, error);
- if (isLate) { destroy(); }
- }];
+ [_owner->getMTLDevice() newComputePipelineStateWithDescriptor: plDesc
+ options: MTLPipelineOptionNone
+ completionHandler: ^(id<MTLComputePipelineState> ps, MTLComputePipelineReflection*, NSError* error) {
+ bool isLate = compileComplete(ps, error);
+ if (isLate) { destroy(); }
+ }];
});
return [_mtlComputePipelineState retain];
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.h b/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.h
index b6e337e..cf77c01 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.h
@@ -40,10 +40,13 @@
* Subclasses are specialized for specific query types.
* Subclasses will generally override the beginQuery(), endQuery(), and getResult(uint32_t, void*, bool) member functions.
*/
-class MVKQueryPool : public MVKBaseDeviceObject {
+class MVKQueryPool : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT; }
+
/** Begins the specified query. */
virtual void beginQuery(uint32_t query, VkQueryControlFlags flags, MVKCommandEncoder* cmdEncoder) {}
@@ -94,7 +97,7 @@
MVKQueryPool(MVKDevice* device,
const VkQueryPoolCreateInfo* pCreateInfo,
- const uint32_t queryElementCount) : MVKBaseDeviceObject(device),
+ const uint32_t queryElementCount) : MVKVulkanAPIDeviceObject(device),
_availability(pCreateInfo->queryCount),
_queryElementCount(queryElementCount) {}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm
index e068b47..0cdfd93 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueryPool.mm
@@ -286,7 +286,7 @@
NSUInteger offset = getVisibilityResultOffset(query);
NSUInteger maxOffset = getDevice()->_pMetalFeatures->maxQueryBufferSize - kMVKQuerySlotSizeInBytes;
if (offset > maxOffset) {
- cmdBuffer->recordResult(mvkNotifyErrorWithText(VK_ERROR_OUT_OF_DEVICE_MEMORY, "vkCmdBeginQuery(): The query offset value %lu is larger than the maximum offset value %lu available on this device.", offset, maxOffset));
+ cmdBuffer->setConfigurationResult(reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "vkCmdBeginQuery(): The query offset value %lu is larger than the maximum offset value %lu available on this device.", offset, maxOffset));
}
if (cmdBuffer->_initialVisibilityResultMTLBuffer == nil) {
@@ -311,7 +311,7 @@
queryCount = uint32_t(newBuffLen / kMVKQuerySlotSizeInBytes);
if (reqBuffLen > maxBuffLen) {
- mvkNotifyErrorWithText(VK_ERROR_OUT_OF_DEVICE_MEMORY, "vkCreateQueryPool(): Each query pool can support a maximum of %d queries.", queryCount);
+ reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "vkCreateQueryPool(): Each query pool can support a maximum of %d queries.", queryCount);
}
NSUInteger mtlBuffLen = mvkAlignByteOffset(newBuffLen, _device->_pMetalFeatures->mtlBufferAlignment);
@@ -335,7 +335,7 @@
MVKPipelineStatisticsQueryPool::MVKPipelineStatisticsQueryPool(MVKDevice* device,
const VkQueryPoolCreateInfo* pCreateInfo) : MVKQueryPool(device, pCreateInfo, 1) {
if ( !_device->_enabledFeatures.pipelineStatisticsQuery ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateQueryPool: VK_QUERY_TYPE_PIPELINE_STATISTICS is not supported."));
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateQueryPool: VK_QUERY_TYPE_PIPELINE_STATISTICS is not supported."));
}
}
@@ -345,5 +345,5 @@
MVKUnsupportedQueryPool::MVKUnsupportedQueryPool(MVKDevice* device,
const VkQueryPoolCreateInfo* pCreateInfo) : MVKQueryPool(device, pCreateInfo, 1) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "vkCreateQueryPool: Unsupported query pool type: %d.", pCreateInfo->queryType));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "vkCreateQueryPool: Unsupported query pool type: %d.", pCreateInfo->queryType));
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
index 6ef0f08..e30d5ff 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
@@ -38,10 +38,13 @@
#pragma mark MVKQueueFamily
/** Represents a Vulkan queue family. */
-class MVKQueueFamily : public MVKConfigurableObject {
+class MVKQueueFamily : public MVKBaseObject {
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _physicalDevice->getVulkanAPIObject(); }
+
/** Returns the index of this queue family. */
inline uint32_t getIndex() { return _queueFamilyIndex; }
@@ -71,10 +74,16 @@
#pragma mark MVKQueue
/** Represents a Vulkan queue. */
-class MVKQueue : public MVKDispatchableDeviceObject {
+class MVKQueue : public MVKDispatchableVulkanAPIObject, public MVKDeviceTrackingMixin {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT; }
+
+ /** Returns a pointer to the Vulkan instance. */
+ MVKInstance* getInstance() override { return _device->getInstance(); }
+
#pragma mark Queue submissions
/** Submits the specified command buffers to the queue. */
@@ -122,6 +131,7 @@
friend class MVKQueueCommandBufferSubmission;
friend class MVKQueuePresentSurfaceSubmission;
+ MVKBaseObject* getBaseObject() override { return this; };
void initName();
void initExecQueue();
void initMTLCommandQueue();
@@ -145,31 +155,30 @@
#pragma mark MVKQueueSubmission
/** This is an abstract class for an operation that can be submitted to an MVKQueue. */
-class MVKQueueSubmission : public MVKBaseDeviceObject {
+class MVKQueueSubmission : public MVKConfigurableObject {
public:
- /**
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _queue->getVulkanAPIObject(); }
+
+ /**
* Executes this action on the queue and then disposes of this instance.
*
* Upon completion of this function, no further calls should be made to this instance.
*/
virtual void execute() = 0;
- MVKQueueSubmission(MVKDevice* device,
- MVKQueue* queue,
+ MVKQueueSubmission(MVKQueue* queue,
uint32_t waitSemaphoreCount,
const VkSemaphore* pWaitSemaphores);
protected:
friend class MVKQueue;
- void recordResult(VkResult vkResult);
-
MVKQueue* _queue;
MVKQueueSubmission* _prev;
MVKQueueSubmission* _next;
- VkResult _submissionResult;
MVKVectorInline<MVKSemaphore*, 8> _waitSemaphores;
bool _isAwaitingSemaphores;
};
@@ -184,11 +193,8 @@
public:
void execute() override;
- /**
- * Constructs an instance for the device and queue.
- */
- MVKQueueCommandBufferSubmission(MVKDevice* device,
- MVKQueue* queue,
+ /** Constructs an instance for the queue. */
+ MVKQueueCommandBufferSubmission(MVKQueue* queue,
const VkSubmitInfo* pSubmit,
VkFence fence,
MVKCommandUse cmdBuffUse);
@@ -219,9 +225,7 @@
public:
void execute() override;
- /** Constructs an instance for the device and queue. */
- MVKQueuePresentSurfaceSubmission(MVKDevice* device,
- MVKQueue* queue,
+ MVKQueuePresentSurfaceSubmission(MVKQueue* queue,
const VkPresentInfoKHR* pPresentInfo);
protected:
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
index e6ad5cf..4efac25 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
@@ -74,7 +74,7 @@
VkResult MVKQueue::submit(MVKQueueSubmission* qSubmit) {
if ( !qSubmit ) { return VK_SUCCESS; } // Ignore nils
- VkResult rslt = qSubmit->_submissionResult; // Extract result before submission to avoid race condition with early destruction
+ VkResult rslt = qSubmit->getConfigurationResult(); // Extract result before submission to avoid race condition with early destruction
if (_execQueue) {
dispatch_async(_execQueue, ^{ execute(qSubmit); } );
} else {
@@ -88,20 +88,20 @@
// Fence-only submission
if (submitCount == 0 && fence) {
- return submit(new MVKQueueCommandBufferSubmission(_device, this, nullptr, fence, cmdBuffUse));
+ return submit(new MVKQueueCommandBufferSubmission(this, nullptr, fence, cmdBuffUse));
}
VkResult rslt = VK_SUCCESS;
for (uint32_t sIdx = 0; sIdx < submitCount; sIdx++) {
VkFence fenceOrNil = (sIdx == (submitCount - 1)) ? fence : VK_NULL_HANDLE; // last one gets the fence
- VkResult subRslt = submit(new MVKQueueCommandBufferSubmission(_device, this, &pSubmits[sIdx], fenceOrNil, cmdBuffUse));
+ VkResult subRslt = submit(new MVKQueueCommandBufferSubmission(this, &pSubmits[sIdx], fenceOrNil, cmdBuffUse));
if (rslt == VK_SUCCESS) { rslt = subRslt; }
}
return rslt;
}
VkResult MVKQueue::submit(const VkPresentInfoKHR* pPresentInfo) {
- return submit(new MVKQueuePresentSurfaceSubmission(_device, this, pPresentInfo));
+ return submit(new MVKQueuePresentSurfaceSubmission(this, pPresentInfo));
}
// Create an empty submit struct and fence, submit to queue and wait on fence.
@@ -116,7 +116,7 @@
MVKFence mvkFence(_device, &vkFenceInfo);
VkFence fence = (VkFence)&mvkFence;
submit(0, nullptr, fence, cmdBuffUse);
- return mvkWaitForFences(1, &fence, false);
+ return mvkWaitForFences(_device, 1, &fence, false);
}
@@ -125,7 +125,7 @@
#define MVK_DISPATCH_QUEUE_QOS_CLASS QOS_CLASS_USER_INITIATED
MVKQueue::MVKQueue(MVKDevice* device, MVKQueueFamily* queueFamily, uint32_t index, float priority)
- : MVKDispatchableDeviceObject(device) {
+ : MVKDeviceTrackingMixin(device) {
_queueFamily = queueFamily;
_index = index;
@@ -167,7 +167,7 @@
// Initializes Xcode GPU capture scopes
void MVKQueue::initGPUCaptureScopes() {
- const MVKConfiguration* pMVKConfig = _device->getInstance()->getMoltenVKConfiguration();
+ const MVKConfiguration* pMVKConfig = getInstance()->getMoltenVKConfiguration();
_submissionCaptureScope = new MVKGPUCaptureScope(this, "CommandBuffer-Submission");
@@ -197,14 +197,12 @@
#pragma mark -
#pragma mark MVKQueueSubmission
-MVKQueueSubmission::MVKQueueSubmission(MVKDevice* device,
- MVKQueue* queue,
+MVKQueueSubmission::MVKQueueSubmission(MVKQueue* queue,
uint32_t waitSemaphoreCount,
- const VkSemaphore* pWaitSemaphores) : MVKBaseDeviceObject(device) {
+ const VkSemaphore* pWaitSemaphores) {
_queue = queue;
_prev = VK_NULL_HANDLE;
_next = VK_NULL_HANDLE;
- _submissionResult = VK_SUCCESS;
_isAwaitingSemaphores = waitSemaphoreCount > 0;
_waitSemaphores.reserve(waitSemaphoreCount);
@@ -213,10 +211,6 @@
}
}
-void MVKQueueSubmission::recordResult(VkResult vkResult) {
- if (_submissionResult == VK_SUCCESS) { _submissionResult = vkResult; }
-}
-
#pragma mark -
#pragma mark MVKQueueCommandBufferSubmission
@@ -227,8 +221,10 @@
_queue->_submissionCaptureScope->beginScope();
+ MVKDevice* mvkDev = _queue->getDevice();
+
// If the device supports it, wait for any semaphores on the device.
- if (_device->_pMetalFeatures->events && _isAwaitingSemaphores) {
+ if (mvkDev->_pMetalFeatures->events && _isAwaitingSemaphores) {
_isAwaitingSemaphores = false;
for (auto* ws : _waitSemaphores) {
ws->encodeWait(getActiveMTLCommandBuffer());
@@ -243,7 +239,7 @@
if (_fence || _isSignalingSemaphores) { getActiveMTLCommandBuffer(); }
// If the device supports it, signal all semaphores on the device.
- if (_device->_pMetalFeatures->events && _isSignalingSemaphores) {
+ if (mvkDev->_pMetalFeatures->events && _isSignalingSemaphores) {
_isSignalingSemaphores = false;
for (auto* ss : _signalSemaphores) {
ss->encodeSignal(getActiveMTLCommandBuffer());
@@ -315,13 +311,11 @@
this->destroy();
}
-MVKQueueCommandBufferSubmission::MVKQueueCommandBufferSubmission(MVKDevice* device,
- MVKQueue* queue,
+MVKQueueCommandBufferSubmission::MVKQueueCommandBufferSubmission(MVKQueue* queue,
const VkSubmitInfo* pSubmit,
VkFence fence,
MVKCommandUse cmdBuffUse)
- : MVKQueueSubmission(device,
- queue,
+ : MVKQueueSubmission(queue,
(pSubmit ? pSubmit->waitSemaphoreCount : 0),
(pSubmit ? pSubmit->pWaitSemaphores : nullptr)) {
@@ -332,7 +326,7 @@
for (uint32_t i = 0; i < cbCnt; i++) {
MVKCommandBuffer* cb = MVKCommandBuffer::getMVKCommandBuffer(pSubmit->pCommandBuffers[i]);
_cmdBuffers.push_back(cb);
- recordResult(cb->getRecordingResult());
+ setConfigurationResult(cb->getConfigurationResult());
}
uint32_t ssCnt = pSubmit->signalSemaphoreCount;
@@ -360,7 +354,8 @@
// If there are semaphores and this device supports MTLEvent, we must present
// with a command buffer in order to synchronize with the semaphores.
- if (_device->_pMetalFeatures->events && !_waitSemaphores.empty()) {
+ MVKDevice* mvkDev = _queue->getDevice();
+ if (mvkDev->_pMetalFeatures->events && !_waitSemaphores.empty()) {
// Create a command buffer, have it wait for the semaphores, then present
// surfaces via the command buffer.
id<MTLCommandBuffer> mtlCmdBuff = [mtlQ commandBufferWithUnretainedReferences];
@@ -371,7 +366,7 @@
for (auto& si : _surfaceImages) { si->presentCAMetalDrawable(mtlCmdBuff); }
[mtlCmdBuff commit];
- } else if (_device->_pMVKConfig->presentWithCommandBuffer || _device->_pMVKConfig->displayWatermark) {
+ } else if (mvkDev->_pMVKConfig->presentWithCommandBuffer || mvkDev->_pMVKConfig->displayWatermark) {
// Create a command buffer, present surfaces via the command buffer,
// then wait on the semaphores before committing.
id<MTLCommandBuffer> mtlCmdBuff = [mtlQ commandBufferWithUnretainedReferences];
@@ -396,13 +391,9 @@
this->destroy();
}
-MVKQueuePresentSurfaceSubmission::MVKQueuePresentSurfaceSubmission(MVKDevice* device,
- MVKQueue* queue,
+MVKQueuePresentSurfaceSubmission::MVKQueuePresentSurfaceSubmission(MVKQueue* queue,
const VkPresentInfoKHR* pPresentInfo)
- : MVKQueueSubmission(device,
- queue,
- pPresentInfo->waitSemaphoreCount,
- pPresentInfo->pWaitSemaphores) {
+ : MVKQueueSubmission(queue, pPresentInfo->waitSemaphoreCount, pPresentInfo->pWaitSemaphores) {
// Populate the array of swapchain images, testing each one for a change in surface size
_surfaceImages.reserve(pPresentInfo->swapchainCount);
@@ -411,9 +402,9 @@
_surfaceImages.push_back(mvkSC->getImage(pPresentInfo->pImageIndices[i]));
// Surface loss takes precedence over out-of-date errors.
if (mvkSC->getIsSurfaceLost()) {
- _submissionResult = VK_ERROR_SURFACE_LOST_KHR;
- } else if (mvkSC->getHasSurfaceSizeChanged() && _submissionResult != VK_ERROR_SURFACE_LOST_KHR) {
- _submissionResult = VK_ERROR_OUT_OF_DATE_KHR;
+ setConfigurationResult(VK_ERROR_SURFACE_LOST_KHR);
+ } else if (mvkSC->getHasSurfaceSizeChanged() && getConfigurationResult() != VK_ERROR_SURFACE_LOST_KHR) {
+ setConfigurationResult(VK_ERROR_OUT_OF_DATE_KHR);
}
}
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h
index 45c8788..d61285c 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.h
@@ -36,6 +36,10 @@
public:
+
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override;
+
/** Returns the number of color attachments, which may be zero for depth-only rendering. */
inline uint32_t getColorAttachmentCount() { return uint32_t(_colorAttachments.size()); }
@@ -97,7 +101,9 @@
class MVKRenderPassAttachment : public MVKBaseObject {
public:
- friend MVKRenderSubpass;
+
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override;
/** Returns the Vulkan format of this attachment. */
VkFormat getFormat();
@@ -137,10 +143,13 @@
#pragma mark MVKRenderPass
/** Represents a Vulkan render pass. */
-class MVKRenderPass : public MVKBaseDeviceObject {
+class MVKRenderPass : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT; }
+
/** Returns the granularity of the render area of this instance. */
VkExtent2D getRenderAreaGranularity();
@@ -150,7 +159,7 @@
/** Constructs an instance for the specified device. */
MVKRenderPass(MVKDevice* device, const VkRenderPassCreateInfo* pCreateInfo);
-private:
+protected:
friend class MVKRenderSubpass;
friend class MVKRenderPassAttachment;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm
index 11fa241..9a7cffe 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm
@@ -20,7 +20,7 @@
#include "MVKFramebuffer.h"
#include "MVKCommandBuffer.h"
#include "MVKFoundation.h"
-#include "mvk_datatypes.h"
+#include "mvk_datatypes.hpp"
using namespace std;
@@ -28,6 +28,8 @@
#pragma mark -
#pragma mark MVKRenderSubpass
+MVKVulkanAPIObject* MVKRenderSubpass::getVulkanAPIObject() { return _renderPass->getVulkanAPIObject(); };
+
VkFormat MVKRenderSubpass::getColorAttachmentFormat(uint32_t colorAttIdx) {
if (colorAttIdx < _colorAttachments.size()) {
uint32_t rpAttIdx = _colorAttachments[colorAttIdx].attachment;
@@ -213,7 +215,7 @@
}
MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass,
- const VkSubpassDescription* pCreateInfo) : MVKBaseObject() {
+ const VkSubpassDescription* pCreateInfo) {
_renderPass = renderPass;
_subpassIndex = (uint32_t)_renderPass->_subpasses.size();
@@ -251,6 +253,8 @@
#pragma mark -
#pragma mark MVKRenderPassAttachment
+MVKVulkanAPIObject* MVKRenderPassAttachment::getVulkanAPIObject() { return _renderPass->getVulkanAPIObject(); };
+
VkFormat MVKRenderPassAttachment::getFormat() { return _info.format; }
VkSampleCountFlagBits MVKRenderPassAttachment::getSampleCount() { return _info.samples; }
@@ -302,7 +306,7 @@
}
MVKRenderPassAttachment::MVKRenderPassAttachment(MVKRenderPass* renderPass,
- const VkAttachmentDescription* pCreateInfo) : MVKBaseObject() {
+ const VkAttachmentDescription* pCreateInfo) {
_renderPass = renderPass;
_attachmentIndex = uint32_t(_renderPass->_attachments.size());
@@ -329,7 +333,7 @@
MVKRenderSubpass* MVKRenderPass::getSubpass(uint32_t subpassIndex) { return &_subpasses[subpassIndex]; }
MVKRenderPass::MVKRenderPass(MVKDevice* device,
- const VkRenderPassCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
+ const VkRenderPassCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
// Add subpasses and dependencies first
_subpasses.reserve(pCreateInfo->subpassCount);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKResource.h b/MoltenVK/MoltenVK/GPUObjects/MVKResource.h
index a96867a..9022f86 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKResource.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKResource.h
@@ -28,7 +28,7 @@
#pragma mark MVKResource
/** Represents an abstract Vulkan resource. Specialized subclasses include MVKBuffer and MVKImage. */
-class MVKResource : public MVKRefCountedDeviceObject {
+class MVKResource : public MVKVulkanAPIDeviceObject {
public:
@@ -77,7 +77,7 @@
#pragma mark Construction
- MVKResource(MVKDevice* device) : MVKRefCountedDeviceObject(device) {}
+ MVKResource(MVKDevice* device) : MVKVulkanAPIDeviceObject(device) {}
protected:
virtual bool needsHostReadSync(VkPipelineStageFlags srcStageMask,
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm b/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm
index b3a3bc8..e8f7b88 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm
@@ -18,6 +18,7 @@
#include "MVKResource.h"
#include "MVKCommandBuffer.h"
+#include "MVKEnvironment.h"
struct MVKBindDeviceMemoryInfo {
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h
index 5fb7556..4a0ff70 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h
@@ -45,17 +45,23 @@
extern const MVKMTLFunction MVKMTLFunctionNull;
/** Wraps a single MTLLibrary. */
-class MVKShaderLibrary : public MVKBaseDeviceObject {
+class MVKShaderLibrary : public MVKBaseObject {
public:
+
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _owner->getVulkanAPIObject(); };
+
/** Returns the Metal shader function, possibly specialized. */
MVKMTLFunction getMTLFunction(const VkSpecializationInfo* pSpecializationInfo);
/** Constructs an instance from the specified MSL source code. */
- MVKShaderLibrary(MVKDevice* device, const std::string& mslSourceCode, const SPIRVEntryPoint& entryPoint);
+ MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner,
+ const std::string& mslSourceCode,
+ const SPIRVEntryPoint& entryPoint);
/** Constructs an instance from the specified compiled MSL code data. */
- MVKShaderLibrary(MVKDevice* device,
+ MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner,
const void* mslCompiledCodeData,
size_t mslCompiledCodeLength);
@@ -70,6 +76,7 @@
void handleCompilationError(NSError* err, const char* opDesc);
MTLFunctionConstant* getFunctionConstant(NSArray<MTLFunctionConstant*>* mtlFCs, NSUInteger mtlFCID);
+ MVKVulkanAPIDeviceObject* _owner;
id<MTLLibrary> _mtlLibrary;
SPIRVEntryPoint _entryPoint;
std::string _msl;
@@ -80,10 +87,13 @@
#pragma mark MVKShaderLibraryCache
/** Represents a cache of shader libraries for one shader module. */
-class MVKShaderLibraryCache : public MVKBaseDeviceObject {
+class MVKShaderLibraryCache : public MVKBaseObject {
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _owner->getVulkanAPIObject(); };
+
/**
* Returns a shader library from the specified shader context sourced from the specified shader module,
* lazily creating the shader library from source code in the shader module, if needed.
@@ -95,7 +105,7 @@
MVKShaderModule* shaderModule,
bool* pWasAdded = nullptr);
- MVKShaderLibraryCache(MVKDevice* device) : MVKBaseDeviceObject(device) {};
+ MVKShaderLibraryCache(MVKVulkanAPIDeviceObject* owner) : _owner(owner) {};
~MVKShaderLibraryCache() override;
@@ -109,6 +119,7 @@
const SPIRVEntryPoint& entryPoint);
void merge(MVKShaderLibraryCache* other);
+ MVKVulkanAPIDeviceObject* _owner;
std::mutex _accessLock;
std::vector<std::pair<SPIRVToMSLConverterContext, MVKShaderLibrary*>> _shaderLibraries;
};
@@ -140,9 +151,13 @@
}
/** Represents a Vulkan shader module. */
-class MVKShaderModule : public MVKBaseDeviceObject {
+class MVKShaderModule : public MVKVulkanAPIDeviceObject {
public:
+
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT; }
+
/** Returns the Metal shader function, possibly specialized. */
MVKMTLFunction getMTLFunction(SPIRVToMSLConverterContext* pContext,
const VkSpecializationInfo* pSpecializationInfo,
@@ -207,9 +222,9 @@
#pragma mark Construction
- MVKShaderLibraryCompiler(MVKDevice* device) : MVKMetalCompiler(device) {
+ MVKShaderLibraryCompiler(MVKVulkanAPIDeviceObject* owner) : MVKMetalCompiler(owner) {
_compilerType = "Shader library";
- _pPerformanceTracker = &_device->_performanceStatistics.shaderCompilation.mslCompile;
+ _pPerformanceTracker = &_owner->getDevice()->_performanceStatistics.shaderCompilation.mslCompile;
}
~MVKShaderLibraryCompiler() override;
@@ -245,9 +260,9 @@
#pragma mark Construction
- MVKFunctionSpecializer(MVKDevice* device) : MVKMetalCompiler(device) {
+ MVKFunctionSpecializer(MVKVulkanAPIDeviceObject* owner) : MVKMetalCompiler(owner) {
_compilerType = "Function specialization";
- _pPerformanceTracker = &_device->_performanceStatistics.shaderCompilation.functionSpecialization;
+ _pPerformanceTracker = &_owner->getDevice()->_performanceStatistics.shaderCompilation.functionSpecialization;
}
~MVKFunctionSpecializer() override;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm
index 46b5cec..199c0ba 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm
@@ -19,6 +19,7 @@
#include "MVKShaderModule.h"
#include "MVKPipeline.h"
#include "MVKFoundation.h"
+#include "MVKLogging.h"
#include "vk_mvk_moltenvk.h"
#include <string>
@@ -53,15 +54,17 @@
// as a function name), and retrieve the unspecialized Metal function with that name.
NSString* mtlFuncName = @(_entryPoint.mtlFunctionName.c_str());
- uint64_t startTime = _device->getPerformanceTimestamp();
+
+ MVKDevice* mvkDev = _owner->getDevice();
+ uint64_t startTime = mvkDev->getPerformanceTimestamp();
id<MTLFunction> mtlFunc = [[_mtlLibrary newFunctionWithName: mtlFuncName] autorelease];
- _device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
+ mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
if (mtlFunc) {
// If the Metal device supports shader specialization, and the Metal function expects to be
// specialized, populate Metal function constant values from the Vulkan specialization info,
// and compiled a specialized Metal function, otherwise simply use the unspecialized Metal function.
- if (_device->_pMetalFeatures->shaderSpecialization) {
+ if (mvkDev->_pMetalFeatures->shaderSpecialization) {
NSArray<MTLFunctionConstant*>* mtlFCs = mtlFunc.functionConstantsDictionary.allValues;
if (mtlFCs.count) {
// The Metal shader contains function constants and expects to be specialized
@@ -83,14 +86,13 @@
}
// Compile the specialized Metal function, and use it instead of the unspecialized Metal function.
- MVKFunctionSpecializer* fs = new MVKFunctionSpecializer(_device);
+ MVKFunctionSpecializer* fs = new MVKFunctionSpecializer(_owner);
mtlFunc = [fs->newMTLFunction(_mtlLibrary, mtlFuncName, mtlFCVals) autorelease];
- setConfigurationResult(fs->getConfigurationResult());
fs->destroy();
}
}
} else {
- mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Shader module does not contain an entry point named '%s'.", mtlFuncName.UTF8String);
+ reportError(VK_ERROR_INITIALIZATION_FAILED, "Shader module does not contain an entry point named '%s'.", mtlFuncName.UTF8String);
}
return { mtlFunc, MTLSizeMake(getWorkgroupDimensionSize(_entryPoint.workgroupSize.width, pSpecializationInfo),
@@ -106,34 +108,34 @@
return nil;
}
-MVKShaderLibrary::MVKShaderLibrary(MVKDevice* device, const string& mslSourceCode, const SPIRVEntryPoint& entryPoint) : MVKBaseDeviceObject(device) {
- MVKShaderLibraryCompiler* slc = new MVKShaderLibraryCompiler(_device);
+MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner, const string& mslSourceCode, const SPIRVEntryPoint& entryPoint) : _owner(owner) {
+ MVKShaderLibraryCompiler* slc = new MVKShaderLibraryCompiler(_owner);
_mtlLibrary = slc->newMTLLibrary(@(mslSourceCode.c_str())); // retained
- setConfigurationResult(slc->getConfigurationResult());
slc->destroy();
_entryPoint = entryPoint;
_msl = mslSourceCode;
}
-MVKShaderLibrary::MVKShaderLibrary(MVKDevice* device,
+MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner,
const void* mslCompiledCodeData,
- size_t mslCompiledCodeLength) : MVKBaseDeviceObject(device) {
- uint64_t startTime = _device->getPerformanceTimestamp();
+ size_t mslCompiledCodeLength) : _owner(owner) {
+ MVKDevice* mvkDev = _owner->getDevice();
+ uint64_t startTime = mvkDev->getPerformanceTimestamp();
@autoreleasepool {
dispatch_data_t shdrData = dispatch_data_create(mslCompiledCodeData,
mslCompiledCodeLength,
NULL,
DISPATCH_DATA_DESTRUCTOR_DEFAULT);
NSError* err = nil;
- _mtlLibrary = [getMTLDevice() newLibraryWithData: shdrData error: &err]; // retained
+ _mtlLibrary = [mvkDev->getMTLDevice() newLibraryWithData: shdrData error: &err]; // retained
handleCompilationError(err, "Compiled shader module creation");
[shdrData release];
}
- _device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.mslLoad, startTime);
+ mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.mslLoad, startTime);
}
-MVKShaderLibrary::MVKShaderLibrary(MVKShaderLibrary& other) : MVKBaseDeviceObject(other._device) {
+MVKShaderLibrary::MVKShaderLibrary(MVKShaderLibrary& other) : _owner(other._owner) {
_mtlLibrary = [other._mtlLibrary retain];
_entryPoint = other._entryPoint;
_msl = other._msl;
@@ -148,10 +150,10 @@
if (_mtlLibrary) {
MVKLogInfo("%s succeeded with warnings (Error code %li):\n%s", opDesc, (long)err.code, err.localizedDescription.UTF8String);
} else {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED,
- "%s failed (Error code %li):\n%s",
- opDesc, (long)err.code,
- err.localizedDescription.UTF8String));
+ _owner->setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED,
+ "%s failed (Error code %li):\n%s",
+ opDesc, (long)err.code,
+ err.localizedDescription.UTF8String));
}
}
@@ -196,7 +198,7 @@
MVKShaderLibrary* MVKShaderLibraryCache::addShaderLibrary(SPIRVToMSLConverterContext* pContext,
const string& mslSourceCode,
const SPIRVEntryPoint& entryPoint) {
- MVKShaderLibrary* shLib = new MVKShaderLibrary(_device, mslSourceCode, entryPoint);
+ MVKShaderLibrary* shLib = new MVKShaderLibrary(_owner, mslSourceCode, entryPoint);
_shaderLibraries.emplace_back(*pContext, shLib);
return shLib;
}
@@ -250,7 +252,7 @@
if (wasConverted) {
if (shouldLogCode) { MVKLogInfo("%s", _converter.getResultLog().data()); }
} else {
- mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "Unable to convert SPIR-V to MSL:\n%s", _converter.getResultLog().data());
+ reportError(VK_ERROR_FORMAT_NOT_SUPPORTED, "Unable to convert SPIR-V to MSL:\n%s", _converter.getResultLog().data());
}
return wasConverted;
}
@@ -259,7 +261,7 @@
#pragma mark Construction
MVKShaderModule::MVKShaderModule(MVKDevice* device,
- const VkShaderModuleCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device), _shaderLibraryCache(device) {
+ const VkShaderModuleCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device), _shaderLibraryCache(this) {
_defaultLibrary = nullptr;
@@ -268,7 +270,7 @@
// Ensure something is there.
if ( (pCreateInfo->pCode == VK_NULL_HANDLE) || (codeSize < 4) ) {
- setConfigurationResult(mvkNotifyErrorWithText(VK_INCOMPLETE, "Shader module contains no SPIR-V code."));
+ setConfigurationResult(reportError(VK_INCOMPLETE, "Shader module contains no SPIR-V code."));
return;
}
@@ -299,7 +301,7 @@
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
_converter.setMSL(pMSLCode, nullptr);
- _defaultLibrary = new MVKShaderLibrary(_device, _converter.getMSL().c_str(), _converter.getEntryPoint());
+ _defaultLibrary = new MVKShaderLibrary(this, _converter.getMSL().c_str(), _converter.getEntryPoint());
break;
}
@@ -313,12 +315,12 @@
codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
- _defaultLibrary = new MVKShaderLibrary(_device, (void*)(pMSLCode), mslCodeLen);
+ _defaultLibrary = new MVKShaderLibrary(this, (void*)(pMSLCode), mslCodeLen);
break;
}
default:
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "SPIR-V contains invalid magic number %x.", magicNum));
+ setConfigurationResult(reportError(VK_ERROR_FORMAT_NOT_SUPPORTED, "SPIR-V contains invalid magic number %x.", magicNum));
break;
}
@@ -337,12 +339,12 @@
unique_lock<mutex> lock(_completionLock);
compile(lock, ^{
- [getMTLDevice() newLibraryWithSource: mslSourceCode
- options: getDevice()->getMTLCompileOptions()
- completionHandler: ^(id<MTLLibrary> mtlLib, NSError* error) {
- bool isLate = compileComplete(mtlLib, error);
- if (isLate) { destroy(); }
- }];
+ [_owner->getMTLDevice() newLibraryWithSource: mslSourceCode
+ options: _owner->getDevice()->getMTLCompileOptions()
+ completionHandler: ^(id<MTLLibrary> mtlLib, NSError* error) {
+ bool isLate = compileComplete(mtlLib, error);
+ if (isLate) { destroy(); }
+ }];
});
return [_mtlLibrary retain];
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSurface.h b/MoltenVK/MoltenVK/GPUObjects/MVKSurface.h
index 7b718a6..5c21169 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSurface.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSurface.h
@@ -18,29 +18,23 @@
#pragma once
-#include "mvk_vulkan.h"
#include "MVKBaseObject.h"
+#include "MVKEnvironment.h"
#include <mutex>
+#import <Metal/Metal.h>
+#import <QuartzCore/CAMetalLayer.h>
-// Expose MoltenVK Apple surface extension functionality
#ifdef VK_USE_PLATFORM_IOS_MVK
-# define vkCreate_PLATFORM_SurfaceMVK vkCreateIOSSurfaceMVK
-# define Vk_PLATFORM_SurfaceCreateInfoMVK VkIOSSurfaceCreateInfoMVK
-# define PLATFORM_VIEW_CLASS UIView
+# define PLATFORM_VIEW_CLASS UIView
# import <UIKit/UIView.h>
#endif
#ifdef VK_USE_PLATFORM_MACOS_MVK
-# define vkCreate_PLATFORM_SurfaceMVK vkCreateMacOSSurfaceMVK
-# define Vk_PLATFORM_SurfaceCreateInfoMVK VkMacOSSurfaceCreateInfoMVK
-# define PLATFORM_VIEW_CLASS NSView
+# define PLATFORM_VIEW_CLASS NSView
# import <AppKit/NSView.h>
#endif
-#import <Metal/Metal.h>
-#import <QuartzCore/CAMetalLayer.h>
-
class MVKInstance;
@class MVKBlockObserver;
@@ -49,10 +43,16 @@
#pragma mark MVKSurface
/** Represents a Vulkan WSI surface. */
-class MVKSurface : public MVKConfigurableObject {
+class MVKSurface : public MVKVulkanAPIObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT; }
+
+ /** Returns a pointer to the Vulkan instance. */
+ MVKInstance* getInstance() override { return _mvkInstance; }
+
/** Returns the CAMetalLayer underlying this surface. */
inline CAMetalLayer* getCAMetalLayer() {
std::lock_guard<std::mutex> lock(_lock);
@@ -69,6 +69,7 @@
~MVKSurface() override;
protected:
+ MVKInstance* _mvkInstance;
CAMetalLayer* _mtlCAMetalLayer;
std::mutex _lock;
MVKBlockObserver* _layerObserver;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSurface.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSurface.mm
index fb9baaf..ab19020 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSurface.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSurface.mm
@@ -19,30 +19,19 @@
#include "MVKSurface.h"
#include "MVKInstance.h"
#include "MVKFoundation.h"
+#include "MVKLogging.h"
#include "MVKOSExtensions.h"
#import "MVKBlockObserver.h"
+#define STR(NAME) #NAME
+
#pragma mark MVKSurface
-#pragma mark Construction
-
-#ifdef VK_USE_PLATFORM_IOS_MVK
-static const char* mvkSurfaceCreateFuncName = "vkCreateIOSSurfaceMVK";
-static const char* mvkSurfaceCreateStructName = "VkIOSSurfaceCreateInfoMVK";
-static const char* mvkViewClassName = "UIView";
-#endif
-
-#ifdef VK_USE_PLATFORM_MACOS_MVK
-static const char* mvkSurfaceCreateFuncName = "vkCreateMacOSSurfaceMVK";
-static const char* mvkSurfaceCreateStructName = "VkMacOSSurfaceCreateInfoMVK";
-static const char* mvkViewClassName = "NSView";
-#endif
-
// pCreateInfo->pView can be either a CAMetalLayer or a view (NSView/UIView).
MVKSurface::MVKSurface(MVKInstance* mvkInstance,
const Vk_PLATFORM_SurfaceCreateInfoMVK* pCreateInfo,
- const VkAllocationCallbacks* pAllocator) {
+ const VkAllocationCallbacks* pAllocator) : _mvkInstance(mvkInstance) {
// Get the platform object contained in pView
id<NSObject> obj = (id<NSObject>)pCreateInfo->pView;
@@ -50,7 +39,8 @@
// If it's a view (NSView/UIView), extract the layer, otherwise assume it's already a CAMetalLayer.
if ([obj isKindOfClass: [PLATFORM_VIEW_CLASS class]]) {
if ( !NSThread.isMainThread ) {
- MVKLogInfo("%s(): You are not calling this function from the main thread. %s should only be accessed from the main thread. When using this function outside the main thread, consider passing the CAMetalLayer itself in %s::pView, instead of the %s.", mvkSurfaceCreateFuncName, mvkViewClassName, mvkSurfaceCreateStructName, mvkViewClassName);
+ MVKLogInfo("%s(): You are not calling this function from the main thread. %s should only be accessed from the main thread. When using this function outside the main thread, consider passing the CAMetalLayer itself in %s::pView, instead of the %s.",
+ STR(vkCreate_PLATFORM_SurfaceMVK), STR(PLATFORM_VIEW_CLASS), STR(Vk_PLATFORM_SurfaceCreateInfoMVK), STR(PLATFORM_VIEW_CLASS));
}
obj = ((PLATFORM_VIEW_CLASS*)obj).layer;
}
@@ -72,7 +62,9 @@
} forObject: _mtlCAMetalLayer.delegate atKeyPath: @"layer"];
}
} else {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "%s(): On-screen rendering requires a layer of type CAMetalLayer.", mvkSurfaceCreateFuncName));
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED,
+ "%s(): On-screen rendering requires a layer of type CAMetalLayer.",
+ STR(vkCreate_PLATFORM_SurfaceMVK)));
_mtlCAMetalLayer = nil;
}
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h
index 2c13f54..3ce0981 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h
@@ -30,10 +30,13 @@
#pragma mark MVKSwapchain
/** Represents a Vulkan swapchain. */
-class MVKSwapchain : public MVKBaseDeviceObject {
+class MVKSwapchain : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT; }
+
/** Returns the number of images in this swapchain. */
uint32_t getImageCount();
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
index 90ee5d2..4d720ed 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
@@ -24,7 +24,7 @@
#include "MVKWatermark.h"
#include "MVKWatermarkTextureContent.h"
#include "MVKWatermarkShaderSource.h"
-#include "mvk_datatypes.h"
+#include "mvk_datatypes.hpp"
#include "MVKLogging.h"
#import "CAMetalLayer+MoltenVK.h"
#import "MVKBlockObserver.h"
@@ -177,7 +177,7 @@
#pragma mark Construction
MVKSwapchain::MVKSwapchain(MVKDevice* device,
- const VkSwapchainCreateInfoKHR* pCreateInfo) : MVKBaseDeviceObject(device), _surfaceLost(false) {
+ const VkSwapchainCreateInfoKHR* pCreateInfo) : MVKVulkanAPIDeviceObject(device), _surfaceLost(false) {
_currentAcquisitionID = 0;
// If applicable, release any surfaces (not currently being displayed) from the old swapchain.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSync.h b/MoltenVK/MoltenVK/GPUObjects/MVKSync.h
index 034d473..1504c92 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSync.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSync.h
@@ -44,6 +44,9 @@
public:
+ /** Returns nil as this object has no need to track the Vulkan object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return nullptr; };
+
/**
* Adds a reservation to this semaphore, incrementing the reservation count.
* Subsequent calls to a wait() function will block until a corresponding call
@@ -105,10 +108,13 @@
#pragma mark MVKSemaphore
/** Represents a Vulkan semaphore. */
-class MVKSemaphore : public MVKRefCountedDeviceObject {
+class MVKSemaphore : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT; }
+
/**
* Blocks processing on the current thread until this semaphore is
* signaled, or until the specified timeout in nanoseconds expires.
@@ -146,10 +152,13 @@
#pragma mark MVKFence
/** Represents a Vulkan fence. */
-class MVKFence : public MVKRefCountedDeviceObject {
+class MVKFence : public MVKVulkanAPIDeviceObject {
public:
+ /** Returns the debug report object type of this object. */
+ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT; }
+
/**
* If this fence has not been signaled yet, adds the specified fence sitter to the
* internal list of fence sitters that will be notified when this fence is signaled,
@@ -180,7 +189,7 @@
#pragma mark Construction
MVKFence(MVKDevice* device, const VkFenceCreateInfo* pCreateInfo) :
- MVKRefCountedDeviceObject(device), _isSignaled(mvkAreFlagsEnabled(pCreateInfo->flags, VK_FENCE_CREATE_SIGNALED_BIT)) {}
+ MVKVulkanAPIDeviceObject(device), _isSignaled(mvkAreFlagsEnabled(pCreateInfo->flags, VK_FENCE_CREATE_SIGNALED_BIT)) {}
protected:
void notifySitters();
@@ -199,6 +208,9 @@
public:
+ /** This is a temporarily instantiated helper class. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return nullptr; }
+
/**
* If this instance has been configured to wait for fences, blocks processing on the
* current thread until any or all of the fences that this instance is waiting for are
@@ -236,7 +248,8 @@
* Blocks the current thread until any or all of the specified
* fences have been signaled, or the specified timeout occurs.
*/
-VkResult mvkWaitForFences(uint32_t fenceCount,
+VkResult mvkWaitForFences(MVKDevice* device,
+ uint32_t fenceCount,
const VkFence* pFences,
VkBool32 waitAll,
uint64_t timeout = UINT64_MAX);
@@ -251,17 +264,20 @@
*
* Instances of this class are one-shot, and can only be used for a single compilation.
*/
-class MVKMetalCompiler : public MVKBaseDeviceObject {
+class MVKMetalCompiler : public MVKBaseObject {
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _owner->getVulkanAPIObject(); };
+
/** If this object is waiting for compilation to complete, deletion will be deferred until then. */
void destroy() override;
#pragma mark Construction
- MVKMetalCompiler(MVKDevice* device) : MVKBaseDeviceObject(device) {}
+ MVKMetalCompiler(MVKVulkanAPIDeviceObject* owner) : _owner(owner) {}
~MVKMetalCompiler() override;
@@ -271,6 +287,7 @@
bool endCompile(NSError* compileError);
bool markDestroyed();
+ MVKVulkanAPIDeviceObject* _owner;
NSError* _compileError = nil;
uint64_t _startTime = 0;
bool _isCompileDone = false;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm
index 94679d7..171df2a 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm
@@ -18,6 +18,7 @@
#include "MVKSync.h"
#include "MVKFoundation.h"
+#include "MVKLogging.h"
using namespace std;
@@ -76,7 +77,7 @@
bool MVKSemaphore::wait(uint64_t timeout) {
bool isDone = _blocker.wait(timeout, true);
- if ( !isDone && timeout > 0 ) { mvkNotifyErrorWithText(VK_TIMEOUT, "Vulkan semaphore timeout after %llu nanoseconds.", timeout); }
+ if ( !isDone && timeout > 0 ) { reportError(VK_TIMEOUT, "Vulkan semaphore timeout after %llu nanoseconds.", timeout); }
return isDone;
}
@@ -94,7 +95,7 @@
}
MVKSemaphore::MVKSemaphore(MVKDevice* device, const VkSemaphoreCreateInfo* pCreateInfo)
- : MVKRefCountedDeviceObject(device), _blocker(false, 1), _mtlEvent(nil), _mtlEventValue(1) {
+ : MVKVulkanAPIDeviceObject(device), _blocker(false, 1), _mtlEvent(nil), _mtlEventValue(1) {
if (device->_pMetalFeatures->events) {
_mtlEvent = [device->getMTLDevice() newEvent];
@@ -165,7 +166,8 @@
}
// Create a blocking fence sitter, add it to each fence, wait, then remove it.
-VkResult mvkWaitForFences(uint32_t fenceCount,
+VkResult mvkWaitForFences(MVKDevice* device,
+ uint32_t fenceCount,
const VkFence* pFences,
VkBool32 waitAll,
uint64_t timeout) {
@@ -180,7 +182,7 @@
if ( !fenceSitter.wait(timeout) ) {
rslt = VK_TIMEOUT;
if (timeout > 0) {
- mvkNotifyErrorWithText(rslt, "Vulkan fence timeout after %llu nanoseconds.", timeout);
+ device->reportError(rslt, "Vulkan fence timeout after %llu nanoseconds.", timeout);
}
}
@@ -202,12 +204,14 @@
// over a second to return when a compiler failure occurs!
void MVKMetalCompiler::compile(unique_lock<mutex>& lock, dispatch_block_t block) {
MVKAssert( _startTime == 0, "%s compile occurred already in this instance. Instances of %s should only be used for a single compile activity.", _compilerType.c_str(), getClassName().c_str());
- _startTime = _device->getPerformanceTimestamp();
+
+ MVKDevice* mvkDev = _owner->getDevice();
+ _startTime = mvkDev->getPerformanceTimestamp();
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
// Limit timeout to avoid overflow since wait_for() uses wait_until()
- chrono::nanoseconds nanoTimeout(min(_device->_pMVKConfig->metalCompileTimeout, kMVKUndefinedLargeUInt64));
+ chrono::nanoseconds nanoTimeout(min(mvkDev->_pMVKConfig->metalCompileTimeout, kMVKUndefinedLargeUInt64));
_blocker.wait_for(lock, nanoTimeout, [this]{ return _isCompileDone; });
if ( !_isCompileDone ) {
@@ -217,14 +221,14 @@
if (_compileError) { handleError(); }
- _device->addActivityPerformance(*_pPerformanceTracker, _startTime);
+ mvkDev->addActivityPerformance(*_pPerformanceTracker, _startTime);
}
void MVKMetalCompiler::handleError() {
- setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED,
- "%s compile failed (Error code %li):\n%s.",
- _compilerType.c_str(), (long)_compileError.code,
- _compileError.localizedDescription.UTF8String));
+ _owner->setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED,
+ "%s compile failed (Error code %li):\n%s.",
+ _compilerType.c_str(), (long)_compileError.code,
+ _compileError.localizedDescription.UTF8String));
}
// Returns whether the compilation came in late, after the compiler was destroyed.
@@ -236,7 +240,7 @@
}
void MVKMetalCompiler::destroy() {
- if (markDestroyed()) { MVKBaseDeviceObject::destroy(); }
+ if (markDestroyed()) { MVKBaseObject::destroy(); }
}
// Marks this object as destroyed, and returns whether the compilation is complete.
diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp b/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp
index 761d6ab..d39ccb2 100644
--- a/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp
+++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp
@@ -19,6 +19,7 @@
#include "MVKExtensions.h"
#include "MVKFoundation.h"
#include "MVKOSExtensions.h"
+#include "MVKEnvironment.h"
#include "vk_mvk_moltenvk.h"
#include <vulkan/vulkan_ios.h>
#include <vulkan/vulkan_macos.h>
@@ -26,6 +27,9 @@
using namespace std;
+#pragma mark -
+#pragma mark MVKExtension
+
// Returns a VkExtensionProperties struct populated with a name and version
static VkExtensionProperties mvkMakeExtProps(const char* extensionName, uint32_t specVersion) {
VkExtensionProperties extProps;
@@ -40,11 +44,62 @@
static VkExtensionProperties kVkExtProps_ ##EXT = mvkMakeExtProps(VK_ ##EXT ##_EXTENSION_NAME, VK_ ##EXT ##_SPEC_VERSION);
#include "MVKExtensions.def"
-MVKExtensionList::MVKExtensionList(bool enableForPlatform) :
+// Returns whether the specified properties are valid for this platform
+static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) {
+#if !(MVK_IOS)
+ if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
+ return mvkOSVersion() >= 10.13;
+ }
+ if (pProperties == &kVkExtProps_MVK_IOS_SURFACE) { return false; }
+ if (pProperties == &kVkExtProps_IMG_FORMAT_PVRTC) { return false; }
+#endif
+#if !(MVK_MACOS)
+ if (pProperties == &kVkExtProps_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE) { return false; }
+ if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
+ return mvkOSVersion() >= 11.0;
+ }
+ if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; }
+#endif
+
+ return true;
+}
+
+// Disable by default unless asked to enable for platform and the extension is valid for this platform
+MVKExtension::MVKExtension(VkExtensionProperties* pProperties, bool enableForPlatform) {
+ this->pProperties = pProperties;
+ this->enabled = enableForPlatform && mvkIsSupportedOnPlatform(pProperties);
+}
+
+
+#pragma mark -
+#pragma mark MVKExtensionList
+
+MVKExtensionList::MVKExtensionList(MVKVulkanAPIObject* apiObject, bool enableForPlatform) : _apiObject(apiObject),
#define MVK_EXTENSION_LAST(var, EXT) vk_ ##var(&kVkExtProps_ ##EXT, enableForPlatform)
#define MVK_EXTENSION(var, EXT) MVK_EXTENSION_LAST(var, EXT),
#include "MVKExtensions.def"
-{}
+{
+ initCount();
+}
+
+// We can't determine size of annonymous struct, and can't rely on size of this class, since
+// it can contain additional member variables. So we need to explicitly count the extensions.
+void MVKExtensionList::initCount() {
+ _count = 0;
+
+#define MVK_EXTENSION(var, EXT) _count++;
+#include "MVKExtensions.def"
+}
+
+uint32_t MVKExtensionList::getEnabledCount() const {
+ uint32_t enabledCnt = 0;
+ uint32_t extnCnt = getCount();
+ const MVKExtension* extnAry = &extensionArray;
+ for (uint32_t extnIdx = 0; extnIdx < extnCnt; extnIdx++) {
+ if (extnAry[extnIdx].enabled) { enabledCnt++; }
+ }
+ return enabledCnt;
+}
bool MVKExtensionList::isEnabled(const char* extnName) const {
if ( !extnName ) { return false; }
@@ -77,7 +132,7 @@
for (uint32_t i = 0; i < count; i++) {
auto extnName = names[i];
if (parent && !parent->isEnabled(extnName)) {
- result = mvkNotifyErrorWithText(VK_ERROR_EXTENSION_NOT_PRESENT, "Vulkan extension %s is not supported.", extnName);
+ result = reportError(VK_ERROR_EXTENSION_NOT_PRESENT, "Vulkan extension %s is not supported.", extnName);
} else {
enable(extnName);
}
@@ -102,29 +157,3 @@
}
return logMsg;
}
-
-// Returns whether the specified properties are valid for this platform
-static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) {
-#if !(MVK_IOS)
- if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
- return mvkOSVersion() >= 10.13;
- }
- if (pProperties == &kVkExtProps_MVK_IOS_SURFACE) { return false; }
- if (pProperties == &kVkExtProps_IMG_FORMAT_PVRTC) { return false; }
-#endif
-#if !(MVK_MACOS)
- if (pProperties == &kVkExtProps_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE) { return false; }
- if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
- return mvkOSVersion() >= 11.0;
- }
- if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; }
-#endif
-
- return true;
-}
-
-// Disable by default unless asked to enable for platform and the extension is valid for this platform
-MVKExtension::MVKExtension(VkExtensionProperties* pProperties, bool enableForPlatform) {
- this->pProperties = pProperties;
- this->enabled = enableForPlatform && mvkIsSupportedOnPlatform(pProperties);
-}
diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
index 885b84d..764db98 100644
--- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def
+++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
@@ -52,6 +52,7 @@
MVK_EXTENSION(KHR_swapchain, KHR_SWAPCHAIN)
MVK_EXTENSION(KHR_swapchain_mutable_format, KHR_SWAPCHAIN_MUTABLE_FORMAT)
MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS)
+MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT)
MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET)
MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET)
MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER)
diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.h b/MoltenVK/MoltenVK/Layers/MVKExtensions.h
index 77d4dde..ae4379e 100644
--- a/MoltenVK/MoltenVK/Layers/MVKExtensions.h
+++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.h
@@ -18,9 +18,13 @@
#pragma once
-#include "mvk_vulkan.h"
+#include "MVKBaseObject.h"
#include <string>
+
+#pragma mark -
+#pragma mark MVKExtension
+
/** Describes a Vulkan extension and whether or not it is enabled or supported. */
struct MVKExtension {
bool enabled = false;
@@ -29,13 +33,23 @@
MVKExtension(VkExtensionProperties* pProperties, bool enableForPlatform = false);
};
+
+#pragma mark -
+#pragma mark MVKExtensionList
+
/**
* A fixed list of the Vulkan extensions known to MoltenVK, with
* an indication of whether each extension is supported/enabled.
*
* To add support for a Vulkan extension, add a variable to this list.
*/
-struct MVKExtensionList {
+class MVKExtensionList : public MVKBaseObject {
+
+public:
+
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _apiObject->getVulkanAPIObject(); };
+
union {
struct {
#define MVK_EXTENSION(var, EXT) MVKExtension vk_ ##var;
@@ -45,7 +59,10 @@
};
/** Returns the total number of extensions that are tracked by this object. */
- static uint32_t getCount() { return sizeof(MVKExtensionList) / sizeof(MVKExtension); }
+ uint32_t getCount() const { return _count; }
+
+ /** Returns the number of extensions that are enabled. */
+ uint32_t getEnabledCount() const;
/** Returns whether the named extension is enabled. */
bool isEnabled(const char* extnName) const;
@@ -68,6 +85,13 @@
*/
std::string enabledNamesString(const char* separator = " ", bool prefixFirstWithSeparator = false) const;
- MVKExtensionList(bool enableForPlatform = false);
+ MVKExtensionList(MVKVulkanAPIObject* apiObject, bool enableForPlatform = false);
+
+protected:
+ void initCount();
+
+ MVKVulkanAPIObject* _apiObject;
+ uint32_t _count;
+
};
diff --git a/MoltenVK/MoltenVK/Layers/MVKLayers.h b/MoltenVK/MoltenVK/Layers/MVKLayers.h
index 62a2b48..b93742a 100644
--- a/MoltenVK/MoltenVK/Layers/MVKLayers.h
+++ b/MoltenVK/MoltenVK/Layers/MVKLayers.h
@@ -26,10 +26,13 @@
#pragma mark MVKLayer
/** Represents a single Vulkan layer. */
-class MVKLayer : public MVKConfigurableObject {
+class MVKLayer : public MVKBaseObject {
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return nullptr; };
+
/** Returns the name of this layer. */
const char* getName();
@@ -66,10 +69,13 @@
#pragma mark MVKLayerManager
/** Manages a set of Vulkan layers. */
-class MVKLayerManager : public MVKConfigurableObject {
+class MVKLayerManager : public MVKBaseObject {
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return nullptr; };
+
/** Returns the driver layer. */
MVKLayer* getDriverLayer();
diff --git a/MoltenVK/MoltenVK/Layers/MVKLayers.mm b/MoltenVK/MoltenVK/Layers/MVKLayers.mm
index b6db84e..bbc5a79 100644
--- a/MoltenVK/MoltenVK/Layers/MVKLayers.mm
+++ b/MoltenVK/MoltenVK/Layers/MVKLayers.mm
@@ -60,7 +60,7 @@
#pragma mark Object Creation
-MVKLayer::MVKLayer() : _supportedExtensions(true) {
+MVKLayer::MVKLayer() : _supportedExtensions(nullptr, true) {
// The core driver layer
memset(_layerProperties.layerName, 0, sizeof(_layerProperties.layerName));
@@ -116,7 +116,7 @@
// Populate the layers
MVKLayerManager::MVKLayerManager() {
- _layers.push_back(MVKLayer());
+ _layers.emplace_back();
}
static mutex _lock;
diff --git a/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m b/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m
index 06b91f8..6316b91 100644
--- a/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m
+++ b/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m
@@ -17,8 +17,8 @@
*/
-#include "MVKCommonEnvironment.h"
#include "CAMetalLayer+MoltenVK.h"
+#include "MVKEnvironment.h"
@implementation CAMetalLayer (MoltenVK)
diff --git a/MoltenVK/MoltenVK/OS/MTLRenderPassDescriptor+MoltenVK.m b/MoltenVK/MoltenVK/OS/MTLRenderPassDescriptor+MoltenVK.m
index a4fd313..7017999 100644
--- a/MoltenVK/MoltenVK/OS/MTLRenderPassDescriptor+MoltenVK.m
+++ b/MoltenVK/MoltenVK/OS/MTLRenderPassDescriptor+MoltenVK.m
@@ -18,7 +18,7 @@
#include "MTLRenderPassDescriptor+MoltenVK.h"
-#include "MVKCommonEnvironment.h"
+#include "MVKEnvironment.h"
@implementation MTLRenderPassDescriptor (MoltenVK)
diff --git a/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m b/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m
index 745d0ba..b5dae5b 100644
--- a/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m
+++ b/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m
@@ -18,6 +18,7 @@
#include "MTLSamplerDescriptor+MoltenVK.h"
+#include "MVKEnvironment.h"
@implementation MTLSamplerDescriptor (MoltenVK)
diff --git a/MoltenVK/MoltenVK/OS/MVKGPUCapture.h b/MoltenVK/MoltenVK/OS/MVKGPUCapture.h
index 3bda589..1eb83be 100644
--- a/MoltenVK/MoltenVK/OS/MVKGPUCapture.h
+++ b/MoltenVK/MoltenVK/OS/MVKGPUCapture.h
@@ -18,12 +18,10 @@
#pragma once
-#include "MVKDevice.h"
+#include "MVKQueue.h"
#import <Metal/Metal.h>
-class MVKQueue;
-
#pragma mark -
#pragma mark MVKGPUCaptureScope
@@ -34,10 +32,13 @@
* If the OS supports the MTLCaptureScope protocol, this class creates and wraps an MTLCaptureScope
* instance for a MTLQueue, otherwise it interacts directly with the MTLQueue to define capture boundaries.
*/
-class MVKGPUCaptureScope : public MVKBaseDeviceObject {
+class MVKGPUCaptureScope : public MVKBaseObject {
public:
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return _queue->getVulkanAPIObject(); };
+
/** Marks the beginning boundary of a capture scope. */
void beginScope();
@@ -58,6 +59,7 @@
~MVKGPUCaptureScope() override;
protected:
+ MVKQueue* _queue;
id<MTLCaptureScope> _mtlCaptureScope = nil;
id<MTLCommandQueue> _mtlQueue = nil;
bool _isFirstBoundary = true;
diff --git a/MoltenVK/MoltenVK/OS/MVKGPUCapture.mm b/MoltenVK/MoltenVK/OS/MVKGPUCapture.mm
index bd1d9f3..156a16e 100644
--- a/MoltenVK/MoltenVK/OS/MVKGPUCapture.mm
+++ b/MoltenVK/MoltenVK/OS/MVKGPUCapture.mm
@@ -19,6 +19,7 @@
#include "MVKGPUCapture.h"
#include "MVKQueue.h"
#include "MVKOSExtensions.h"
+#include "MVKEnvironment.h"
#pragma mark -
@@ -55,11 +56,11 @@
}
}
-MVKGPUCaptureScope::MVKGPUCaptureScope(MVKQueue* mvkQueue, const char* purpose) : MVKBaseDeviceObject(mvkQueue->getDevice()) {
- _mtlQueue = [mvkQueue->getMTLCommandQueue() retain]; // retained
+MVKGPUCaptureScope::MVKGPUCaptureScope(MVKQueue* mvkQueue, const char* purpose) : _queue(mvkQueue) {
+ _mtlQueue = [_queue->getMTLCommandQueue() retain]; // retained
if (mvkOSVersion() >= kMinOSVersionMTLCaptureScope) {
_mtlCaptureScope = [[MTLCaptureManager sharedCaptureManager] newCaptureScopeWithCommandQueue: _mtlQueue]; // retained
- _mtlCaptureScope.label = @((mvkQueue->getName() + "-" + purpose).c_str());
+ _mtlCaptureScope.label = @((_queue->getName() + "-" + purpose).c_str());
}
}
diff --git a/MoltenVK/MoltenVK/Utility/MVKBaseObject.cpp b/MoltenVK/MoltenVK/Utility/MVKBaseObject.cpp
index 0d67b9f..e8abb0c 100644
--- a/MoltenVK/MoltenVK/Utility/MVKBaseObject.cpp
+++ b/MoltenVK/MoltenVK/Utility/MVKBaseObject.cpp
@@ -17,12 +17,57 @@
*/
#include "MVKBaseObject.h"
+#include "MVKInstance.h"
+#include "MVKFoundation.h"
+#include "MVKOSExtensions.h"
+#include "MVKLogging.h"
#include <stdlib.h>
#include <cxxabi.h>
using namespace std;
+// The logging level
+// 0 = None
+// 1 = Errors only
+// 2 = All
+#ifndef MVK_CONFIG_LOG_LEVEL
+# define MVK_CONFIG_LOG_LEVEL 2
+#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);
+}
+
+static const char* getReportingLevelString(int aslLvl) {
+ switch (aslLvl) {
+ case ASL_LEVEL_DEBUG:
+ return "mvk-debug";
+
+ case ASL_LEVEL_INFO:
+ case ASL_LEVEL_NOTICE:
+ return "mvk-info";
+
+ case ASL_LEVEL_WARNING:
+ return "mvk-warn";
+
+ case ASL_LEVEL_ERR:
+ case ASL_LEVEL_CRIT:
+ case ASL_LEVEL_ALERT:
+ case ASL_LEVEL_EMERG:
+ default:
+ return "mvk-error";
+ }
+}
+
+
#pragma mark -
#pragma mark MVKBaseObject
@@ -33,3 +78,125 @@
free(demangled);
return clzName;
}
+
+void MVKBaseObject::reportMessage(int aslLvl, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ reportMessage(this, aslLvl, format, args);
+ va_end(args);
+}
+
+void MVKBaseObject::reportMessage(MVKBaseObject* mvkObj, int aslLvl, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ reportMessage(mvkObj, aslLvl, format, args);
+ va_end(args);
+}
+
+// This is the core reporting implementation. Other similar functions delegate here.
+void MVKBaseObject::reportMessage(MVKBaseObject* mvkObj, int aslLvl, const char* format, va_list args) {
+
+ MVKVulkanAPIObject* mvkAPIObj = mvkObj ? mvkObj->getVulkanAPIObject() : nullptr;
+ MVKInstance* mvkInst = mvkAPIObj ? mvkAPIObj->getInstance() : nullptr;
+ bool hasDebugReportCallbacks = mvkInst && mvkInst->hasDebugReportCallbacks();
+ bool shouldLog = (aslLvl < (_mvkLogLevel << 2));
+
+ // Fail fast to avoid further unnecessary processing.
+ if ( !(shouldLog || hasDebugReportCallbacks) ) { return; }
+
+ va_list origArgs, redoArgs;
+ va_copy(origArgs, args);
+ va_copy(redoArgs, args);
+
+ // Choose a buffer size suitable for most messages and attempt to write it out.
+ const int kOrigBuffSize = 2 * KIBI;
+ char origBuff[kOrigBuffSize];
+ char* pMessage = origBuff;
+ int msgLen = vsnprintf(origBuff, kOrigBuffSize, format, origArgs);
+
+ // If message is too big for original buffer, allocate a buffer big enough to hold it and
+ // write the message out again. We only want to do this double writing if we have to.
+ // Create the redoBuff outside scope of if block to allow it to be referencable by pMessage later below.
+ int redoBuffSize = (msgLen >= kOrigBuffSize) ? msgLen + 1 : 0;
+ char redoBuff[redoBuffSize];
+ if (redoBuffSize > 0) {
+ pMessage = redoBuff;
+ vsnprintf(redoBuff, redoBuffSize, format, redoArgs);
+ }
+
+ va_end(redoArgs);
+ va_end(origArgs);
+
+ // Log the message to the standard error stream
+ if (shouldLog) { fprintf(stderr, "[%s] %s\n", getReportingLevelString(aslLvl), pMessage); }
+
+ // Broadcast the message to any Vulkan debug report callbacks
+ if (hasDebugReportCallbacks) { mvkInst->debugReportMessage(mvkAPIObj, aslLvl, pMessage); }
+}
+
+VkResult MVKBaseObject::reportError(VkResult vkErr, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ VkResult rslt = reportError(this, vkErr, format, args);
+ va_end(args);
+ return rslt;
+}
+
+VkResult MVKBaseObject::reportError(MVKBaseObject* mvkObj, VkResult vkErr, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ VkResult rslt = reportError(mvkObj, vkErr, format, args);
+ va_end(args);
+ return rslt;
+}
+
+// This is the core reporting implementation. Other similar functions delegate here.
+VkResult MVKBaseObject::reportError(MVKBaseObject* mvkObj, VkResult vkErr, const char* format, va_list args) {
+
+ // Prepend the error code to the format string
+ const char* vkRsltName = mvkVkResultName(vkErr);
+ char fmtStr[strlen(vkRsltName) + strlen(format) + 4];
+ sprintf(fmtStr, "%s: %s", vkRsltName, format);
+
+ // Report the error
+ va_list lclArgs;
+ va_copy(lclArgs, args);
+ reportMessage(mvkObj, ASL_LEVEL_ERR, fmtStr, lclArgs);
+ va_end(lclArgs);
+
+ return vkErr;
+}
+
+
+#pragma mark -
+#pragma mark MVKVulkanAPIObject
+
+void MVKVulkanAPIObject::retain() {
+ lock_guard<mutex> lock(_refLock);
+
+ _refCount++;
+}
+
+void MVKVulkanAPIObject::release() {
+ if (decrementRetainCount()) { destroy(); }
+}
+
+void MVKVulkanAPIObject::destroy() {
+ if (markDestroyed()) { MVKConfigurableObject::destroy(); }
+}
+
+// Decrements the reference count, and returns whether it's time to destroy this object.
+bool MVKVulkanAPIObject::decrementRetainCount() {
+ lock_guard<mutex> lock(_refLock);
+
+ if (_refCount > 0) { _refCount--; }
+ return (_isDestroyed && _refCount == 0);
+}
+
+// Marks this object as destroyed, and returns whether no references are left outstanding.
+bool MVKVulkanAPIObject::markDestroyed() {
+ lock_guard<mutex> lock(_refLock);
+
+ _isDestroyed = true;
+ return _refCount == 0;
+}
diff --git a/MoltenVK/MoltenVK/Utility/MVKBaseObject.h b/MoltenVK/MoltenVK/Utility/MVKBaseObject.h
index e9abadf..ccdf4bc 100644
--- a/MoltenVK/MoltenVK/Utility/MVKBaseObject.h
+++ b/MoltenVK/MoltenVK/Utility/MVKBaseObject.h
@@ -21,6 +21,10 @@
#include "mvk_vulkan.h"
#include <vulkan/vk_icd.h>
#include <string>
+#include <mutex>
+
+class MVKInstance;
+class MVKVulkanAPIObject;
#pragma mark -
@@ -37,6 +41,59 @@
/** Returns the name of the class of which this object is an instance. */
std::string getClassName();
+ /** Returns the Vulkan API opaque object controlling this object. */
+ virtual MVKVulkanAPIObject* getVulkanAPIObject() = 0;
+
+ /**
+ * Report a message. This includes logging to a standard system logging stream,
+ * and some subclasses will also forward the message to their VkInstance for
+ * output to the Vulkan debug report messaging API.
+ */
+ void reportMessage(int aslLvl, const char* format, ...) __printflike(3, 4);
+
+ /**
+ * Report a Vulkan error message, on behalf of the object, which may be nil.
+ * Reporting includes logging to a standard system logging stream, and if the object
+ * is not nil and has access to the VkInstance, the message will also be forwarded
+ * to the VkInstance for output to the Vulkan debug report messaging API.
+ */
+ static void reportMessage(MVKBaseObject* mvkObj, int aslLvl, const char* format, ...) __printflike(3, 4);
+
+ /**
+ * Report a Vulkan error message, on behalf of the object, which may be nil.
+ * Reporting includes logging to a standard system logging stream, and if the object
+ * is not nil and has access to the VkInstance, the message will also be forwarded
+ * to the VkInstance for output to the Vulkan debug report messaging API.
+ *
+ * This is the core reporting implementation. Other similar functions delegate here.
+ */
+ static void reportMessage(MVKBaseObject* mvkObj, int aslLvl, const char* format, va_list args) __printflike(3, 0);
+
+ /**
+ * Report a Vulkan error message. This includes logging to a standard system logging stream,
+ * and some subclasses will also forward the message to their VkInstance for output to the
+ * Vulkan debug report messaging API.
+ */
+ VkResult reportError(VkResult vkErr, const char* format, ...) __printflike(3, 4);
+
+ /**
+ * Report a Vulkan error message, on behalf of the object. which may be nil.
+ * Reporting includes logging to a standard system logging stream, and if the object
+ * is not nil and has access to the VkInstance, the message will also be forwarded
+ * to the VkInstance for output to the Vulkan debug report messaging API.
+ */
+ static VkResult reportError(MVKBaseObject* mvkObj, VkResult vkErr, const char* format, ...) __printflike(3, 4);
+
+ /**
+ * Report a Vulkan error message, on behalf of the object. which may be nil.
+ * Reporting includes logging to a standard system logging stream, and if the object
+ * is not nil and has access to the VkInstance, the message will also be forwarded
+ * to the VkInstance for output to the Vulkan debug report messaging API.
+ *
+ * This is the core reporting implementation. Other similar functions delegate here.
+ */
+ static VkResult reportError(MVKBaseObject* mvkObj, VkResult vkErr, const char* format, va_list args) __printflike(3, 0);
+
/** Destroys this object. Default behaviour simply deletes it. Subclasses may override to delay deletion. */
virtual void destroy() { delete this; }
@@ -72,14 +129,83 @@
#pragma mark -
-#pragma mark MVKDispatchableObject
+#pragma mark MVKVulkanAPIObject
-/** Abstract class that represents an object that can be used as a Vulkan API dispatchable object. */
-class MVKDispatchableObject : public MVKConfigurableObject {
+/**
+ * Abstract class that represents an opaque Vulkan API handle object.
+ *
+ * API objects can sometimes be destroyed by the client before the GPU is done with them.
+ * To support this, an object of this type will automatically be deleted iff it has been
+ * destroyed by the client, and all references have been released. An object of this type
+ * is therefore allowed to live past its destruction by the client, until it is no longer
+ * referenced by other objects.
+ */
+class MVKVulkanAPIObject : public MVKConfigurableObject {
+
+public:
+
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return this; };
+
+ /** Returns a reference to this object suitable for use as a Vulkan API handle. */
+ virtual void* getVkHandle() { return this; }
+
+ /** Returns the debug report object type of this object. */
+ virtual VkDebugReportObjectTypeEXT getVkDebugReportObjectType() = 0;
+
+ /** Returns the Vulkan instance. */
+ virtual MVKInstance* getInstance() = 0;
+
+ /**
+ * Called when this instance has been retained as a reference by another object,
+ * indicating that this instance will not be deleted until that reference is released.
+ */
+ void retain();
+
+ /**
+ * Called when this instance has been released as a reference from another object.
+ * Once all references have been released, this object is free to be deleted.
+ * If the destroy() function has already been called on this instance by the time
+ * this function is called, this instance will be deleted.
+ */
+ void release();
+
+ /**
+ * Marks this instance as destroyed. If all previous references to this instance
+ * have been released, this instance will be deleted, otherwise deletion of this
+ * instance will automatically be deferred until all references have been released.
+ */
+ void destroy() override;
+
+ /** Construct an empty instance. Declared here to support copy constructor. */
+ MVKVulkanAPIObject() {}
+
+ /**
+ * Construct an instance from a copy. Default copy constructor disallowed due to mutex.
+ * Copies start with fresh reference counts.
+ */
+ MVKVulkanAPIObject(const MVKVulkanAPIObject& other) {}
+
+protected:
+
+ bool decrementRetainCount();
+ bool markDestroyed();
+
+ std::mutex _refLock;
+ unsigned _refCount = 0;
+ bool _isDestroyed = false;
+};
+
+
+#pragma mark -
+#pragma mark MVKDispatchableVulkanAPIObject
+
+/** Abstract class that represents a dispatchable opaque Vulkan API handle object. */
+class MVKDispatchableVulkanAPIObject : public MVKVulkanAPIObject {
typedef struct {
VK_LOADER_DATA loaderData;
- MVKDispatchableObject* mvkObject;
+ MVKDispatchableVulkanAPIObject* mvkObject;
} MVKDispatchableObjectICDRef;
public:
@@ -88,13 +214,13 @@
* Returns a reference to this object suitable for use as a Vulkan API handle.
* This is the compliment of the getDispatchableObject() method.
*/
- inline void* getVkHandle() { return &_icdRef; }
+ void* getVkHandle() override { return &_icdRef; }
/**
- * Retrieves the MVKDispatchableObject instance referenced by the dispatchable Vulkan handle.
+ * Retrieves the MVKDispatchableVulkanAPIObject instance referenced by the dispatchable Vulkan handle.
* This is the compliment of the getVkHandle() method.
*/
- static inline MVKDispatchableObject* getDispatchableObject(void* vkHandle) {
+ static inline MVKDispatchableVulkanAPIObject* getDispatchableObject(void* vkHandle) {
return vkHandle ? ((MVKDispatchableObjectICDRef*)vkHandle)->mvkObject : nullptr;
}
diff --git a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h
index 19a6819..f593530 100644
--- a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h
+++ b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h
@@ -20,8 +20,20 @@
#pragma once
#include "MVKCommonEnvironment.h"
+#include "mvk_vulkan.h"
+// Expose MoltenVK Apple surface extension functionality
+#ifdef VK_USE_PLATFORM_IOS_MVK
+# define vkCreate_PLATFORM_SurfaceMVK vkCreateIOSSurfaceMVK
+# define Vk_PLATFORM_SurfaceCreateInfoMVK VkIOSSurfaceCreateInfoMVK
+#endif
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+# define vkCreate_PLATFORM_SurfaceMVK vkCreateMacOSSurfaceMVK
+# define Vk_PLATFORM_SurfaceCreateInfoMVK VkMacOSSurfaceCreateInfoMVK
+#endif
+
/** Macro to determine the Vulkan version supported by MoltenVK. */
#define MVK_VULKAN_API_VERSION VK_MAKE_VERSION(VK_VERSION_MAJOR(VK_API_VERSION_1_0), \
VK_VERSION_MINOR(VK_API_VERSION_1_0), \
diff --git a/MoltenVK/MoltenVK/Utility/MVKFoundation.cpp b/MoltenVK/MoltenVK/Utility/MVKFoundation.cpp
index 276df6f..a6f699c 100644
--- a/MoltenVK/MoltenVK/Utility/MVKFoundation.cpp
+++ b/MoltenVK/MoltenVK/Utility/MVKFoundation.cpp
@@ -17,7 +17,6 @@
*/
#include "MVKFoundation.h"
-#include "MVKLogging.h"
#define CASE_STRINGIFY(V) case V: return #V
@@ -75,23 +74,6 @@
}
}
-VkResult mvkNotifyErrorWithText(VkResult vkErr, const char* errFmt, ...) {
- va_list args;
- va_start(args, errFmt);
-
- // Prepend the error code to the format string
- const char* vkRsltName = mvkVkResultName(vkErr);
- char fmtStr[strlen(vkRsltName) + strlen(errFmt) + 4];
- sprintf(fmtStr, "%s: %s", vkRsltName, errFmt);
-
- // Log the error
- MVKLogImplV(true, !(MVK_DEBUG), ASL_LEVEL_ERR, "***MoltenVK ERROR***", fmtStr, args);
-
- va_end(args);
-
- return vkErr;
-}
-
#pragma mark -
#pragma mark Alignment functions
diff --git a/MoltenVK/MoltenVK/Utility/MVKFoundation.h b/MoltenVK/MoltenVK/Utility/MVKFoundation.h
index 472e9a3..00b0b85 100644
--- a/MoltenVK/MoltenVK/Utility/MVKFoundation.h
+++ b/MoltenVK/MoltenVK/Utility/MVKFoundation.h
@@ -21,7 +21,6 @@
#include "mvk_vulkan.h"
-#include "MVKLogging.h"
#include <algorithm>
#include <string>
#include <simd/simd.h>
@@ -138,13 +137,6 @@
return verStr;
}
-/**
- * Notifies the app of an error code and error message, via the following methods:
- *
- * - Logs the error code and message to the console
- */
-VkResult mvkNotifyErrorWithText(VkResult vkErr, const char* errFmt, ...) __printflike(2, 3);
-
#pragma mark -
#pragma mark Alignment functions
@@ -204,7 +196,7 @@
static inline uintptr_t mvkAlignByteRef(uintptr_t byteRef, uintptr_t byteAlignment, bool alignDown = false) {
if (byteAlignment == 0) { return byteRef; }
- MVKAssert(mvkIsPowerOfTwo(byteAlignment), "Byte alignment %lu is not a power-of-two value.", byteAlignment);
+ assert(mvkIsPowerOfTwo(byteAlignment));
uintptr_t mask = byteAlignment - 1;
uintptr_t alignedRef = (byteRef + mask) & ~mask;
diff --git a/MoltenVK/MoltenVK/Utility/MVKWatermark.h b/MoltenVK/MoltenVK/Utility/MVKWatermark.h
index 6836c03..b1b3028 100644
--- a/MoltenVK/MoltenVK/Utility/MVKWatermark.h
+++ b/MoltenVK/MoltenVK/Utility/MVKWatermark.h
@@ -58,6 +58,10 @@
public:
+
+ /** Returns the Vulkan API opaque object controlling this object. */
+ MVKVulkanAPIObject* getVulkanAPIObject() override { return nullptr; };
+
/** Sets the clip-space position (0.0 - 1.0) of this watermark. */
void setPosition(MVKWatermarkPosition position);
diff --git a/MoltenVK/MoltenVK/Utility/MVKWatermark.mm b/MoltenVK/MoltenVK/Utility/MVKWatermark.mm
index a87897a..db7740c 100644
--- a/MoltenVK/MoltenVK/Utility/MVKWatermark.mm
+++ b/MoltenVK/MoltenVK/Utility/MVKWatermark.mm
@@ -21,6 +21,7 @@
#include "MVKOSExtensions.h"
#include "MVKLogging.h"
#include "MTLTextureDescriptor+MoltenVK.h"
+#include "MVKEnvironment.h"
/** The structure to hold shader uniforms. */
diff --git a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp
new file mode 100644
index 0000000..6cc918f
--- /dev/null
+++ b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp
@@ -0,0 +1,78 @@
+/*
+ * mvk_datatypes.hpp
+ *
+ * Copyright (c) 2014-2019 The Brenwill Workshop Ltd. (http://www.brenwill.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __mvkDataTypes_hpp_
+#define __mvkDataTypes_hpp_ 1
+
+
+#include "mvk_datatypes.h"
+
+class MVKBaseObject;
+
+/*
+ * This header file should be used internally within MoltenVK in place of mvk_datatypes.h,
+ * which is part of the public external MoltenVK C API.
+ */
+
+
+#pragma mark -
+#pragma mark Support for VK_EXT_debug_report extension
+
+/*
+ * The following function declarations are variations of functions declared in mvk_datatypes.h.
+ *
+ * Each function variation declared here accepts an MVKBaseObject instance, which, if not nil,
+ * allows calls to MVKBaseObject::reportError() to be made from within these functions to perform
+ * debug report callbacks in support of the VK_EXT_debug_report extension.
+ *
+ * The original functions in mvk_datatypes.h are redefined here to redirect to the equivalent
+ * functions declared here, passing the calling instance, which is assumed to be an instance
+ * of an MVKBaseObject subclass, which is true for all but static calling functions.
+ */
+
+MTLPixelFormat mvkMTLPixelFormatFromVkFormatInObj(VkFormat vkFormat, MVKBaseObject* mvkObj);
+#define mvkMTLPixelFormatFromVkFormat(vkFormat) mvkMTLPixelFormatFromVkFormatInObj(vkFormat, this)
+
+MTLVertexFormat mvkMTLVertexFormatFromVkFormatInObj(VkFormat vkFormat, MVKBaseObject* mvkObj);
+#define mvkMTLVertexFormatFromVkFormat(vkFormat) mvkMTLVertexFormatFromVkFormatInObj(vkFormat, this)
+
+MTLPrimitiveType mvkMTLPrimitiveTypeFromVkPrimitiveTopologyInObj(VkPrimitiveTopology vkTopology, MVKBaseObject* mvkObj);
+#define mvkMTLPrimitiveTypeFromVkPrimitiveTopology(vkTopology) mvkMTLPrimitiveTypeFromVkPrimitiveTopologyInObj(vkTopology, this)
+
+MTLPrimitiveTopologyClass mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopologyInObj(VkPrimitiveTopology vkTopology, MVKBaseObject* mvkObj);
+#define mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(vkTopology) mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopologyInObj(vkTopology, this)
+
+MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonModeInObj(VkPolygonMode vkFillMode, MVKBaseObject* mvkObj);
+#define mvkMTLTriangleFillModeFromVkPolygonMode(vkFillMode) mvkMTLTriangleFillModeFromVkPolygonModeInObj(vkFillMode, this)
+
+MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOpInObj(VkAttachmentLoadOp vkLoadOp, MVKBaseObject* mvkObj);
+#define mvkMTLLoadActionFromVkAttachmentLoadOp(vkLoadOp) mvkMTLLoadActionFromVkAttachmentLoadOpInObj(vkLoadOp, this)
+
+MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOpInObj(VkAttachmentStoreOp vkStoreOp, bool hasResolveAttachment, MVKBaseObject* mvkObj);
+#define mvkMTLStoreActionFromVkAttachmentStoreOp(vkStoreOp, hasResolveAttachment) mvkMTLStoreActionFromVkAttachmentStoreOpInObj(vkStoreOp, hasResolveAttachment, this)
+
+MVKShaderStage mvkShaderStageFromVkShaderStageFlagBitsInObj(VkShaderStageFlagBits vkStage, MVKBaseObject* mvkObj);
+#define mvkShaderStageFromVkShaderStageFlagBits(vkStage) mvkShaderStageFromVkShaderStageFlagBitsInObj(vkStage, this)
+
+MTLWinding mvkMTLWindingFromSpvExecutionModeInObj(uint32_t spvMode, MVKBaseObject* mvkObj);
+#define mvkMTLWindingFromSpvExecutionMode(spvMode) mvkMTLWindingFromSpvExecutionModeInObj(spvMode, this)
+
+MTLTessellationPartitionMode mvkMTLTessellationPartitionModeFromSpvExecutionModeInObj(uint32_t spvMode, MVKBaseObject* mvkObj);
+#define mvkMTLTessellationPartitionModeFromSpvExecutionMode(spvMode) mvkMTLTessellationPartitionModeFromSpvExecutionModeInObj(spvMode, this)
+
+#endif
diff --git a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm
index b6a764c..329fb6d 100644
--- a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm
+++ b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm
@@ -17,10 +17,10 @@
*/
#include "MVKEnvironment.h"
-#include "mvk_datatypes.h"
+#include "mvk_datatypes.hpp"
#include "MVKFoundation.h"
#include "MVKOSExtensions.h"
-#include "MVKLogging.h"
+#include "MVKBaseObject.h"
#include <MoltenVKSPIRVToMSLConverter/SPIRVReflection.h>
#include <unordered_map>
#include <string>
@@ -489,8 +489,8 @@
* Populates the lookup maps that map Vulkan and Metal pixel formats to one-another.
*
* Because both Metal and core Vulkan format value are enumerations that start at zero and are
- * more or less consecutively enumerated, we can use a simple lookup array in each direction
- * to map the value in one architecture (as an array index) to the corresponding value in the
+ * more or less consecutively enumerated, we can use a simple lookup array in each direction
+ * to map the value in one architecture (as an array index) to the corresponding value in the
* other architecture. Values that exist in one API but not the other are given a default value.
*
* Vulkan extension formats have very large values, and are tracked in a separate map.
@@ -563,7 +563,12 @@
return formatDescForMTLPixelFormat(mtlFormat).formatType;
}
+#undef mvkMTLPixelFormatFromVkFormat
MVK_PUBLIC_SYMBOL MTLPixelFormat mvkMTLPixelFormatFromVkFormat(VkFormat vkFormat) {
+ return mvkMTLPixelFormatFromVkFormatInObj(vkFormat, nullptr);
+}
+
+MTLPixelFormat mvkMTLPixelFormatFromVkFormatInObj(VkFormat vkFormat, MVKBaseObject* mvkObj) {
MTLPixelFormat mtlPixFmt = MTLPixelFormatInvalid;
const MVKFormatDesc& fmtDesc = formatDescForVkFormat(vkFormat);
@@ -585,7 +590,7 @@
errMsg += (fmtDescSubs.vkName) ? fmtDescSubs.vkName : to_string(fmtDescSubs.vk);
errMsg += " instead.";
}
- mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "%s", errMsg.c_str());
+ MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "%s", errMsg.c_str());
}
return mtlPixFmt;
@@ -660,7 +665,12 @@
return formatDescForMTLPixelFormat(mtlFormat).mtlName;
}
+#undef mvkMTLVertexFormatFromVkFormat
MVK_PUBLIC_SYMBOL MTLVertexFormat mvkMTLVertexFormatFromVkFormat(VkFormat vkFormat) {
+ return mvkMTLVertexFormatFromVkFormatInObj(vkFormat, nullptr);
+}
+
+MTLVertexFormat mvkMTLVertexFormatFromVkFormatInObj(VkFormat vkFormat, MVKBaseObject* mvkObj) {
MTLVertexFormat mtlVtxFmt = MTLVertexFormatInvalid;
const MVKFormatDesc& fmtDesc = formatDescForVkFormat(vkFormat);
@@ -682,7 +692,7 @@
errMsg += (fmtDescSubs.vkName) ? fmtDescSubs.vkName : to_string(fmtDescSubs.vk);
errMsg += " instead.";
}
- mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "%s", errMsg.c_str());
+ MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "%s", errMsg.c_str());
}
return mtlVtxFmt;
@@ -1046,7 +1056,12 @@
}
}
+#undef mvkMTLPrimitiveTypeFromVkPrimitiveTopology
MVK_PUBLIC_SYMBOL MTLPrimitiveType mvkMTLPrimitiveTypeFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology) {
+ return mvkMTLPrimitiveTypeFromVkPrimitiveTopologyInObj(vkTopology, nullptr);
+}
+
+MTLPrimitiveType mvkMTLPrimitiveTypeFromVkPrimitiveTopologyInObj(VkPrimitiveTopology vkTopology, MVKBaseObject* mvkObj) {
switch (vkTopology) {
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
return MTLPrimitiveTypePoint;
@@ -1070,12 +1085,17 @@
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
default:
- mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "VkPrimitiveTopology value %d is not supported for rendering.", vkTopology);
+ MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "VkPrimitiveTopology value %d is not supported for rendering.", vkTopology);
return MTLPrimitiveTypePoint;
}
}
+#undef mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology
MVK_PUBLIC_SYMBOL MTLPrimitiveTopologyClass mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology) {
+ return mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopologyInObj(vkTopology, nullptr);
+}
+
+MTLPrimitiveTopologyClass mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopologyInObj(VkPrimitiveTopology vkTopology, MVKBaseObject* mvkObj) {
switch (vkTopology) {
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
return MTLPrimitiveTopologyClassPoint;
@@ -1095,12 +1115,17 @@
return MTLPrimitiveTopologyClassTriangle;
default:
- mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "VkPrimitiveTopology value %d is not supported for render pipelines.", vkTopology);
+ MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "VkPrimitiveTopology value %d is not supported for render pipelines.", vkTopology);
return MTLPrimitiveTopologyClassUnspecified;
}
}
+#undef mvkMTLTriangleFillModeFromVkPolygonMode
MVK_PUBLIC_SYMBOL MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonMode(VkPolygonMode vkFillMode) {
+ return mvkMTLTriangleFillModeFromVkPolygonModeInObj(vkFillMode, nullptr);
+}
+
+MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonModeInObj(VkPolygonMode vkFillMode, MVKBaseObject* mvkObj) {
switch (vkFillMode) {
case VK_POLYGON_MODE_FILL:
case VK_POLYGON_MODE_POINT:
@@ -1110,30 +1135,40 @@
return MTLTriangleFillModeLines;
default:
- mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "VkPolygonMode value %d is not supported for render pipelines.", vkFillMode);
+ MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "VkPolygonMode value %d is not supported for render pipelines.", vkFillMode);
return MTLTriangleFillModeFill;
}
}
+#undef mvkMTLLoadActionFromVkAttachmentLoadOp
MVK_PUBLIC_SYMBOL MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOp(VkAttachmentLoadOp vkLoadOp) {
+ return mvkMTLLoadActionFromVkAttachmentLoadOpInObj(vkLoadOp, nullptr);
+}
+
+MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOpInObj(VkAttachmentLoadOp vkLoadOp, MVKBaseObject* mvkObj) {
switch (vkLoadOp) {
case VK_ATTACHMENT_LOAD_OP_LOAD: return MTLLoadActionLoad;
case VK_ATTACHMENT_LOAD_OP_CLEAR: return MTLLoadActionClear;
case VK_ATTACHMENT_LOAD_OP_DONT_CARE: return MTLLoadActionDontCare;
default:
- mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "VkAttachmentLoadOp value %d is not supported.", vkLoadOp);
+ MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "VkAttachmentLoadOp value %d is not supported.", vkLoadOp);
return MTLLoadActionLoad;
}
}
+#undef mvkMTLStoreActionFromVkAttachmentStoreOp
MVK_PUBLIC_SYMBOL MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOp(VkAttachmentStoreOp vkStoreOp, bool hasResolveAttachment) {
+ return mvkMTLStoreActionFromVkAttachmentStoreOpInObj(vkStoreOp, hasResolveAttachment, nullptr);
+}
+
+MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOpInObj(VkAttachmentStoreOp vkStoreOp, bool hasResolveAttachment, MVKBaseObject* mvkObj) {
switch (vkStoreOp) {
case VK_ATTACHMENT_STORE_OP_STORE: return hasResolveAttachment ? MTLStoreActionStoreAndMultisampleResolve : MTLStoreActionStore;
case VK_ATTACHMENT_STORE_OP_DONT_CARE: return hasResolveAttachment ? MTLStoreActionMultisampleResolve : MTLStoreActionDontCare;
default:
- mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "VkAttachmentStoreOp value %d is not supported.", vkStoreOp);
+ MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "VkAttachmentStoreOp value %d is not supported.", vkStoreOp);
return MTLStoreActionStore;
}
}
@@ -1218,7 +1253,12 @@
}
}
+#undef mvkShaderStageFromVkShaderStageFlagBits
MVK_PUBLIC_SYMBOL MVKShaderStage mvkShaderStageFromVkShaderStageFlagBits(VkShaderStageFlagBits vkStage) {
+ return mvkShaderStageFromVkShaderStageFlagBitsInObj(vkStage, nullptr);
+}
+
+MVKShaderStage mvkShaderStageFromVkShaderStageFlagBitsInObj(VkShaderStageFlagBits vkStage, MVKBaseObject* mvkObj) {
switch (vkStage) {
case VK_SHADER_STAGE_VERTEX_BIT: return kMVKShaderStageVertex;
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return kMVKShaderStageTessCtl;
@@ -1227,7 +1267,7 @@
case VK_SHADER_STAGE_FRAGMENT_BIT: return kMVKShaderStageFragment;
case VK_SHADER_STAGE_COMPUTE_BIT: return kMVKShaderStageCompute;
default:
- mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "VkShaderStage %x is not supported.", vkStage);
+ MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "VkShaderStage %x is not supported.", vkStage);
return kMVKShaderStageMax;
}
}
@@ -1246,24 +1286,34 @@
}
}
+#undef mvkMTLWindingFromSpvExecutionMode
MVK_PUBLIC_SYMBOL MTLWinding mvkMTLWindingFromSpvExecutionMode(uint32_t spvMode) {
+ return mvkMTLWindingFromSpvExecutionModeInObj(spvMode, nullptr);
+}
+
+MTLWinding mvkMTLWindingFromSpvExecutionModeInObj(uint32_t spvMode, MVKBaseObject* mvkObj) {
switch (spvMode) {
// These are reversed due to the vertex flip.
case spv::ExecutionModeVertexOrderCw: return MTLWindingCounterClockwise;
case spv::ExecutionModeVertexOrderCcw: return MTLWindingClockwise;
default:
- mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "spv::ExecutionMode %u is not a winding order mode.\n", spvMode);
+ MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "spv::ExecutionMode %u is not a winding order mode.\n", spvMode);
return MTLWindingCounterClockwise;
}
}
+#undef mvkMTLTessellationPartitionModeFromSpvExecutionMode
MVK_PUBLIC_SYMBOL MTLTessellationPartitionMode mvkMTLTessellationPartitionModeFromSpvExecutionMode(uint32_t spvMode) {
+ return mvkMTLTessellationPartitionModeFromSpvExecutionModeInObj(spvMode, nullptr);
+}
+
+MTLTessellationPartitionMode mvkMTLTessellationPartitionModeFromSpvExecutionModeInObj(uint32_t spvMode, MVKBaseObject* mvkObj) {
switch (spvMode) {
case spv::ExecutionModeSpacingEqual: return MTLTessellationPartitionModeInteger;
case spv::ExecutionModeSpacingFractionalEven: return MTLTessellationPartitionModeFractionalEven;
case spv::ExecutionModeSpacingFractionalOdd: return MTLTessellationPartitionModeFractionalOdd;
default:
- mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "spv::ExecutionMode %u is not a tessellation partition mode.\n", spvMode);
+ MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "spv::ExecutionMode %u is not a tessellation partition mode.\n", spvMode);
return MTLTessellationPartitionModePow2;
}
}
diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
index dbf86e4..3c5e144 100644
--- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm
+++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
@@ -38,16 +38,12 @@
#include "MVKQueue.h"
#include "MVKQueryPool.h"
#include "MVKSwapchain.h"
+#include "MVKSurface.h"
#include "MVKFoundation.h"
#include "MVKLogging.h"
-static VkResult MVKLogUnimplemented(const char* funcName) {
- return mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "%s() is not implemented!", funcName);
-}
-
static bool _mvkTraceVulkanCalls = false;
-#define MVKTraceVulkanCall() MVKLogInfoIf(_mvkTraceVulkanCalls, "%s()", __FUNCTION__)
-
+#define MVKTraceVulkanCall() if (_mvkTraceVulkanCalls) { fprintf(stderr, "[mvk-trace] %s()\n", __FUNCTION__); }
MVK_PUBLIC_SYMBOL VkResult vkCreateInstance(
const VkInstanceCreateInfo* pCreateInfo,
@@ -204,7 +200,7 @@
MVKTraceVulkanCall();
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
- return mvkPD->getLayerManager()->getLayerNamed(pLayerName)->getExtensionProperties(pCount, pProperties);
+ return mvkPD->getInstance()->getLayerManager()->getLayerNamed(pLayerName)->getExtensionProperties(pCount, pProperties);
}
MVK_PUBLIC_SYMBOL VkResult vkEnumerateInstanceLayerProperties(
@@ -222,7 +218,7 @@
MVKTraceVulkanCall();
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
- return mvkPD->getLayerManager()->getLayerProperties(pCount, pProperties);
+ return mvkPD->getInstance()->getLayerManager()->getLayerProperties(pCount, pProperties);
}
MVK_PUBLIC_SYMBOL void vkGetDeviceQueue(
@@ -441,7 +437,8 @@
VkFence fence) {
MVKTraceVulkanCall();
- return mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkQueueBindSparse(): Sparse binding is not supported.");
+ MVKQueue* mvkQ = MVKQueue::getMVKQueue(queue);
+ return mvkQ->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkQueueBindSparse(): Sparse binding is not supported.");
}
MVK_PUBLIC_SYMBOL VkResult vkCreateFence(
@@ -494,7 +491,8 @@
uint64_t timeout) {
MVKTraceVulkanCall();
- return mvkWaitForFences(fenceCount, pFences, waitAll, timeout);
+ MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
+ return mvkWaitForFences(mvkDev, fenceCount, pFences, waitAll, timeout);
}
MVK_PUBLIC_SYMBOL VkResult vkCreateSemaphore(
@@ -528,7 +526,9 @@
VkEvent* pEvent) {
MVKTraceVulkanCall();
- return MVKLogUnimplemented("vkCreateEvent");
+ //VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT
+ MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
+ return mvkDev->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateEvent(): Vukan events are not supported.");
}
MVK_PUBLIC_SYMBOL void vkDestroyEvent(
@@ -538,7 +538,8 @@
MVKTraceVulkanCall();
if ( !event ) { return; }
- MVKLogUnimplemented("vkDestroyEvent");
+ MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
+ mvkDev->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkDestroyEvent(): Vukan events are not supported.");
}
MVK_PUBLIC_SYMBOL VkResult vkGetEventStatus(
@@ -546,7 +547,8 @@
VkEvent event) {
MVKTraceVulkanCall();
- return MVKLogUnimplemented("vkGetEventStatus");
+ MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
+ return mvkDev->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkGetEventStatus(): Vukan events are not supported.");
}
MVK_PUBLIC_SYMBOL VkResult vkSetEvent(
@@ -554,7 +556,8 @@
VkEvent event) {
MVKTraceVulkanCall();
- return MVKLogUnimplemented("vkSetEvent");
+ MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
+ return mvkDev->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkSetEvent(): Vukan events are not supported.");
}
MVK_PUBLIC_SYMBOL VkResult vkResetEvent(
@@ -562,7 +565,8 @@
VkEvent event) {
MVKTraceVulkanCall();
- return MVKLogUnimplemented("vkResetEvent");
+ MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
+ return mvkDev->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkResetEvent(): Vukan events are not supported.");
}
MVK_PUBLIC_SYMBOL VkResult vkCreateQueryPool(
@@ -1468,7 +1472,8 @@
VkPipelineStageFlags stageMask) {
MVKTraceVulkanCall();
- MVKLogUnimplemented("vkCmdSetEvent");
+ MVKCommandBuffer* cmdBuff = MVKCommandBuffer::getMVKCommandBuffer(commandBuffer);
+ cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdSetEvent(): Vukan events are not supported.");
}
MVK_PUBLIC_SYMBOL void vkCmdResetEvent(
@@ -1477,7 +1482,8 @@
VkPipelineStageFlags stageMask) {
MVKTraceVulkanCall();
- MVKLogUnimplemented("vkCmdResetEvent");
+ MVKCommandBuffer* cmdBuff = MVKCommandBuffer::getMVKCommandBuffer(commandBuffer);
+ cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdResetEvent(): Vukan events are not supported.");
}
MVK_PUBLIC_SYMBOL void vkCmdWaitEvents(
@@ -1494,7 +1500,8 @@
const VkImageMemoryBarrier* pImageMemoryBarriers) {
MVKTraceVulkanCall();
- MVKLogUnimplemented("vkCmdWaitEvents");
+ MVKCommandBuffer* cmdBuff = MVKCommandBuffer::getMVKCommandBuffer(commandBuffer);
+ cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdWaitEvents(): Vukan events are not supported.");
}
MVK_PUBLIC_SYMBOL void vkCmdPipelineBarrier(
@@ -2084,6 +2091,49 @@
#pragma mark -
+#pragma mark VK_EXT_debug_report extension
+
+MVK_PUBLIC_SYMBOL VkResult vkCreateDebugReportCallbackEXT(
+ VkInstance instance,
+ const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDebugReportCallbackEXT* pCallback) {
+
+ MVKTraceVulkanCall();
+ MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance);
+ MVKDebugReportCallback* mvkDRCB = mvkInst->createDebugReportCallback(pCreateInfo, pAllocator);
+ *pCallback = (VkDebugReportCallbackEXT)mvkDRCB;
+ return mvkDRCB->getConfigurationResult();
+}
+
+MVK_PUBLIC_SYMBOL void vkDestroyDebugReportCallbackEXT(
+ VkInstance instance,
+ VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks* pAllocator) {
+
+ MVKTraceVulkanCall();
+ if ( !callback ) { return; }
+ MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance);
+ mvkInst->destroyDebugReportCallback((MVKDebugReportCallback*)callback, pAllocator);
+}
+
+MVK_PUBLIC_SYMBOL void vkDebugReportMessageEXT(
+ VkInstance instance,
+ VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objectType,
+ uint64_t object,
+ size_t location,
+ int32_t messageCode,
+ const char* pLayerPrefix,
+ const char* pMessage) {
+
+ MVKTraceVulkanCall();
+ MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance);
+ mvkInst->debugReportMessage(flags, objectType, object, location, messageCode, pLayerPrefix, pMessage);
+}
+
+
+#pragma mark -
#pragma mark iOS & macOS surface extensions
MVK_PUBLIC_SYMBOL VkResult vkCreate_PLATFORM_SurfaceMVK(
diff --git a/MoltenVKShaderConverter/MoltenVKShaderConverter.xcodeproj/project.pbxproj b/MoltenVKShaderConverter/MoltenVKShaderConverter.xcodeproj/project.pbxproj
index 8d0a209..634d744 100644
--- a/MoltenVKShaderConverter/MoltenVKShaderConverter.xcodeproj/project.pbxproj
+++ b/MoltenVKShaderConverter/MoltenVKShaderConverter.xcodeproj/project.pbxproj
@@ -57,15 +57,10 @@
A9C70F65221B321700FBA31A /* SPIRVSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9C70F5E221B321700FBA31A /* SPIRVSupport.cpp */; };
A9C70F66221B321700FBA31A /* SPIRVSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9C70F5E221B321700FBA31A /* SPIRVSupport.cpp */; };
A9C70F67221B321700FBA31A /* SPIRVSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9C70F5E221B321700FBA31A /* SPIRVSupport.cpp */; };
- A9E337B8220129ED00363D2A /* MVKLogging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9E337B7220129ED00363D2A /* MVKLogging.cpp */; };
A9F042B01FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */; };
A9F042B11FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */; };
A9F042B21FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */; };
A9F042B31FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */; };
- A9F042B41FB4D060009FCCB8 /* MVKLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AB1FB4D060009FCCB8 /* MVKLogging.h */; };
- A9F042B51FB4D060009FCCB8 /* MVKLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AB1FB4D060009FCCB8 /* MVKLogging.h */; };
- A9F042B61FB4D060009FCCB8 /* MVKLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AB1FB4D060009FCCB8 /* MVKLogging.h */; };
- A9F042B71FB4D060009FCCB8 /* MVKLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AB1FB4D060009FCCB8 /* MVKLogging.h */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -120,9 +115,7 @@
A9B51BDC225E98BB00AC74D2 /* MVKOSExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKOSExtensions.h; sourceTree = "<group>"; };
A9C70F5D221B321600FBA31A /* SPIRVSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SPIRVSupport.h; path = Common/SPIRVSupport.h; sourceTree = SOURCE_ROOT; };
A9C70F5E221B321700FBA31A /* SPIRVSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SPIRVSupport.cpp; path = Common/SPIRVSupport.cpp; sourceTree = SOURCE_ROOT; };
- A9E337B7220129ED00363D2A /* MVKLogging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MVKLogging.cpp; sourceTree = "<group>"; };
A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCommonEnvironment.h; sourceTree = "<group>"; };
- A9F042AB1FB4D060009FCCB8 /* MVKLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKLogging.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -244,8 +237,6 @@
isa = PBXGroup;
children = (
A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */,
- A9E337B7220129ED00363D2A /* MVKLogging.cpp */,
- A9F042AB1FB4D060009FCCB8 /* MVKLogging.h */,
A9B51BDC225E98BB00AC74D2 /* MVKOSExtensions.h */,
A9B51BDB225E98BB00AC74D2 /* MVKOSExtensions.mm */,
A98149651FB6A98A005F00B4 /* MVKStrings.h */,
@@ -275,7 +266,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
- A9F042B41FB4D060009FCCB8 /* MVKLogging.h in Headers */,
A9C70F5F221B321700FBA31A /* SPIRVSupport.h in Headers */,
A90941A51C581F840094110D /* GLSLConversion.h in Headers */,
A90940A91C5808BB0094110D /* GLSLToSPIRVConverter.h in Headers */,
@@ -288,7 +278,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
- A9F042B51FB4D060009FCCB8 /* MVKLogging.h in Headers */,
A9C70F60221B321700FBA31A /* SPIRVSupport.h in Headers */,
A90941A61C581F840094110D /* GLSLConversion.h in Headers */,
A90940AA1C5808BB0094110D /* GLSLToSPIRVConverter.h in Headers */,
@@ -305,7 +294,6 @@
A98149681FB6A98A005F00B4 /* MVKStrings.h in Headers */,
A9C70F61221B321700FBA31A /* SPIRVSupport.h in Headers */,
A928C9191D0488DC00071B88 /* SPIRVConversion.h in Headers */,
- A9F042B61FB4D060009FCCB8 /* MVKLogging.h in Headers */,
A909408C1C58013E0094110D /* SPIRVToMSLConverter.h in Headers */,
A9F042B21FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */,
);
@@ -320,7 +308,6 @@
A9C70F62221B321700FBA31A /* SPIRVSupport.h in Headers */,
A928C91A1D0488DC00071B88 /* SPIRVConversion.h in Headers */,
A909408D1C58013E0094110D /* SPIRVToMSLConverter.h in Headers */,
- A9F042B71FB4D060009FCCB8 /* MVKLogging.h in Headers */,
A9F042B31FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -625,7 +612,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- A9E337B8220129ED00363D2A /* MVKLogging.cpp in Sources */,
A97CC7411C7527F3004A5C7E /* MoltenVKShaderConverterTool.cpp in Sources */,
A9C70F63221B321700FBA31A /* SPIRVSupport.cpp in Sources */,
A95096BF2003D32400F10950 /* OSSupport.mm in Sources */,