Add support for the VK_EXT_debug_report extension.
Add MVKDebugReportCallback class. Add MVKVulkanAPIObject class as base class of classes exposed in Vulkan API. Remove MVKRefCountedDeviceObject class and move ref-counting to MVKVulkanAPIObject. Rename MVKDispatchableObject class to MVKDispatchableVulkanAPIObject. Introduce multiple inheritance mixin classes into class hierarchy. Add MVKBaseObject::getVulkanAPIObject() function to find Vulkan API object controlling any subobject that needs to report something. MVKCommandResourceFactory functions pass in calling object for reporting. Add MVKBaseObject::reportMessage() & reportError() functions. Replace mvkNotifyErrorWithText() static function with reportError() instance function to allow access to debug reporting. Redefine MVKLog*() functions to call reportError() instance method. Delete MVKLogging.cpp. Remove MVKLogging.h from MoltenVKShaderConverter project. Add mvk_datatypes.hpp to redirect errors in mvk_datatypes.h functions to debug reporting. Use mvk_datatypes.hpp internally for all references to these functions. Convert several static methods to instance methods. Refactor platform defines in MVKSurface.h. Explicitly count MVKExtensionList extension count to avoid relying on struct size. Remove MVKCommandBuffer::recordResult() and use setConfigurationResult(). Change log indication of error in logs from [***MoltenVK ERROR***] to [mvk-error], for consistency with other log level indications. Update MoltenVK version to 1.0.35.
This commit is contained in:
parent
fc1ce42a37
commit
173d8cc5f3
@ -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
|
|
@ -23,7 +23,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
#include "MVKCommonEnvironment.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -93,12 +92,6 @@ extern "C" {
|
|||||||
* from the compiled code, thus eliminating both the memory and CPU overhead that the assertion
|
* from the compiled code, thus eliminating both the memory and CPU overhead that the assertion
|
||||||
* calls would add
|
* 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
|
* 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
|
* technique is to set these switches via the compiler build setting GCC_PREPROCESSOR_DEFINITIONS
|
||||||
* in your build configuration.
|
* in your build configuration.
|
||||||
@ -172,22 +165,10 @@ extern "C" {
|
|||||||
# define MVKLogDebugIf(cond, fmt, ...)
|
# define MVKLogDebugIf(cond, fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
#define MVKLogErrorImpl(fmt, ...) reportMessage(ASL_LEVEL_ERR, fmt, ##__VA_ARGS__)
|
||||||
* Combine the specified log level and format string, then log
|
#define MVKLogInfoImpl(fmt, ...) reportMessage(ASL_LEVEL_NOTICE, fmt, ##__VA_ARGS__)
|
||||||
* the specified args to one or both of ASL and printf.
|
#define MVKLogTraceImpl(fmt, ...) reportMessage(ASL_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
|
||||||
*/
|
#define MVKLogDebugImpl(fmt, ...) reportMessage(ASL_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
|
||||||
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__)
|
|
||||||
|
|
||||||
// Assertions
|
// Assertions
|
||||||
#ifdef NS_BLOCK_ASSERTIONS
|
#ifdef NS_BLOCK_ASSERTIONS
|
||||||
@ -203,8 +184,6 @@ do { \
|
|||||||
assert(!isErr || MVK_BLOCK_ASSERTIONS); \
|
assert(!isErr || MVK_BLOCK_ASSERTIONS); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define MVKAssertUnimplemented(name) MVKAssert(false, "%s is not implemented!", name)
|
|
||||||
|
|
||||||
// Use this macro to open a break-point programmatically.
|
// Use this macro to open a break-point programmatically.
|
||||||
#ifndef MVK_DEBUGGER
|
#ifndef MVK_DEBUGGER
|
||||||
# define MVK_DEBUGGER() { kill( getpid(), SIGINT ) ; }
|
# define MVK_DEBUGGER() { kill( getpid(), SIGINT ) ; }
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "MVKOSExtensions.h"
|
#include "MVKOSExtensions.h"
|
||||||
#include "MVKLogging.h"
|
|
||||||
#include <mach/mach_time.h>
|
#include <mach/mach_time.h>
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
@ -51,10 +50,8 @@ double mvkGetElapsedMilliseconds(uint64_t startTimestamp, uint64_t endTimestamp)
|
|||||||
return (double)(endTimestamp - startTimestamp) * _mvkTimestampPeriod / 1e6;
|
return (double)(endTimestamp - startTimestamp) * _mvkTimestampPeriod / 1e6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Initialize timestamping capabilities on app startup.
|
||||||
* Initialize timestamping capabilities on app startup.
|
//Called automatically when the framework is loaded and initialized.
|
||||||
* Called automatically when the framework is loaded and initialized.
|
|
||||||
*/
|
|
||||||
static bool _mvkTimestampsInitialized = false;
|
static bool _mvkTimestampsInitialized = false;
|
||||||
__attribute__((constructor)) static void MVKInitTimestamps() {
|
__attribute__((constructor)) static void MVKInitTimestamps() {
|
||||||
if (_mvkTimestampsInitialized ) { return; }
|
if (_mvkTimestampsInitialized ) { return; }
|
||||||
@ -64,8 +61,6 @@ __attribute__((constructor)) static void MVKInitTimestamps() {
|
|||||||
mach_timebase_info_data_t timebase;
|
mach_timebase_info_data_t timebase;
|
||||||
mach_timebase_info(&timebase);
|
mach_timebase_info(&timebase);
|
||||||
_mvkTimestampPeriod = (double)timebase.numer / (double)timebase.denom;
|
_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) {
|
void mvkDispatchToMainAndWait(dispatch_block_t block) {
|
||||||
|
@ -248,6 +248,7 @@ In addition to the core *Vulkan* API, **MoltenVK** also supports the following
|
|||||||
- `VK_KHR_swapchain`
|
- `VK_KHR_swapchain`
|
||||||
- `VK_KHR_swapchain_mutable_format`
|
- `VK_KHR_swapchain_mutable_format`
|
||||||
- `VK_KHR_variable_pointers`
|
- `VK_KHR_variable_pointers`
|
||||||
|
- `VK_EXT_debug_report`
|
||||||
- `VK_EXT_host_query_reset`
|
- `VK_EXT_host_query_reset`
|
||||||
- `VK_EXT_memory_budget`
|
- `VK_EXT_memory_budget`
|
||||||
- `VK_EXT_shader_viewport_index_layer`
|
- `VK_EXT_shader_viewport_index_layer`
|
||||||
|
@ -18,6 +18,9 @@ MoltenVK 1.0.35
|
|||||||
|
|
||||||
Released TBD
|
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:
|
- Tessellation fixes:
|
||||||
- Don't use setVertexBytes() for passing tessellation vertex counts.
|
- Don't use setVertexBytes() for passing tessellation vertex counts.
|
||||||
- Fix intermediate Metal renderpasses load and store actions maintaining
|
- Fix intermediate Metal renderpasses load and store actions maintaining
|
||||||
|
@ -187,8 +187,8 @@
|
|||||||
A9C96DD11DDC20C20053187F /* MVKMTLBufferAllocation.h in Headers */ = {isa = PBXBuildFile; fileRef = A9C96DCE1DDC20C20053187F /* MVKMTLBufferAllocation.h */; };
|
A9C96DD11DDC20C20053187F /* MVKMTLBufferAllocation.h in Headers */ = {isa = PBXBuildFile; fileRef = A9C96DCE1DDC20C20053187F /* MVKMTLBufferAllocation.h */; };
|
||||||
A9C96DD21DDC20C20053187F /* MVKMTLBufferAllocation.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9C96DCF1DDC20C20053187F /* MVKMTLBufferAllocation.mm */; };
|
A9C96DD21DDC20C20053187F /* MVKMTLBufferAllocation.mm in Sources */ = {isa = PBXBuildFile; fileRef = A9C96DCF1DDC20C20053187F /* MVKMTLBufferAllocation.mm */; };
|
||||||
A9C96DD31DDC20C20053187F /* 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 */; };
|
A9CEAAD5227378D400FAF779 /* mvk_datatypes.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A9CEAAD1227378D400FAF779 /* mvk_datatypes.hpp */; };
|
||||||
A9E337B6220129DD00363D2A /* MVKLogging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9E337B1220129DD00363D2A /* MVKLogging.cpp */; };
|
A9CEAAD6227378D400FAF779 /* mvk_datatypes.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A9CEAAD1227378D400FAF779 /* mvk_datatypes.hpp */; };
|
||||||
A9E4B7891E1D8AF10046A4CE /* MVKMTLResourceBindings.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E4B7881E1D8AF10046A4CE /* MVKMTLResourceBindings.h */; };
|
A9E4B7891E1D8AF10046A4CE /* MVKMTLResourceBindings.h in Headers */ = {isa = PBXBuildFile; fileRef = A9E4B7881E1D8AF10046A4CE /* MVKMTLResourceBindings.h */; };
|
||||||
A9E4B78A1E1D8AF10046A4CE /* 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 */; };
|
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>"; };
|
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>"; };
|
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; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
A9E53DD02100B197002781DD /* MTLTextureDescriptor+MoltenVK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MTLTextureDescriptor+MoltenVK.h"; sourceTree = "<group>"; };
|
||||||
@ -504,6 +504,7 @@
|
|||||||
A94FB7A81C7DFB4800632CA3 /* Vulkan */ = {
|
A94FB7A81C7DFB4800632CA3 /* Vulkan */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
A9CEAAD1227378D400FAF779 /* mvk_datatypes.hpp */,
|
||||||
A94FB7A91C7DFB4800632CA3 /* mvk_datatypes.mm */,
|
A94FB7A91C7DFB4800632CA3 /* mvk_datatypes.mm */,
|
||||||
A94FB7AC1C7DFB4800632CA3 /* vk_mvk_moltenvk.mm */,
|
A94FB7AC1C7DFB4800632CA3 /* vk_mvk_moltenvk.mm */,
|
||||||
A94FB7AD1C7DFB4800632CA3 /* vulkan.mm */,
|
A94FB7AD1C7DFB4800632CA3 /* vulkan.mm */,
|
||||||
@ -581,7 +582,6 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
A9F0429D1FB4CF82009FCCB8 /* MVKCommonEnvironment.h */,
|
A9F0429D1FB4CF82009FCCB8 /* MVKCommonEnvironment.h */,
|
||||||
A9E337B1220129DD00363D2A /* MVKLogging.cpp */,
|
|
||||||
A9F0429E1FB4CF82009FCCB8 /* MVKLogging.h */,
|
A9F0429E1FB4CF82009FCCB8 /* MVKLogging.h */,
|
||||||
A9B51BD6225E986A00AC74D2 /* MVKOSExtensions.h */,
|
A9B51BD6225E986A00AC74D2 /* MVKOSExtensions.h */,
|
||||||
A9B51BD2225E986A00AC74D2 /* MVKOSExtensions.mm */,
|
A9B51BD2225E986A00AC74D2 /* MVKOSExtensions.mm */,
|
||||||
@ -672,6 +672,7 @@
|
|||||||
A94FB7E81C7DFB4800632CA3 /* MVKDeviceMemory.h in Headers */,
|
A94FB7E81C7DFB4800632CA3 /* MVKDeviceMemory.h in Headers */,
|
||||||
A9E4B7891E1D8AF10046A4CE /* MVKMTLResourceBindings.h in Headers */,
|
A9E4B7891E1D8AF10046A4CE /* MVKMTLResourceBindings.h in Headers */,
|
||||||
45003E73214AD4E500E989CB /* MVKExtensions.def in Headers */,
|
45003E73214AD4E500E989CB /* MVKExtensions.def in Headers */,
|
||||||
|
A9CEAAD5227378D400FAF779 /* mvk_datatypes.hpp in Headers */,
|
||||||
A90C8DEA1F45354D009CB32C /* MVKCommandEncodingPool.h in Headers */,
|
A90C8DEA1F45354D009CB32C /* MVKCommandEncodingPool.h in Headers */,
|
||||||
A94FB8081C7DFB4800632CA3 /* MVKResource.h in Headers */,
|
A94FB8081C7DFB4800632CA3 /* MVKResource.h in Headers */,
|
||||||
A9E53DDD2100B197002781DD /* MTLTextureDescriptor+MoltenVK.h in Headers */,
|
A9E53DDD2100B197002781DD /* MTLTextureDescriptor+MoltenVK.h in Headers */,
|
||||||
@ -737,6 +738,7 @@
|
|||||||
A94FB7E91C7DFB4800632CA3 /* MVKDeviceMemory.h in Headers */,
|
A94FB7E91C7DFB4800632CA3 /* MVKDeviceMemory.h in Headers */,
|
||||||
A9E4B78A1E1D8AF10046A4CE /* MVKMTLResourceBindings.h in Headers */,
|
A9E4B78A1E1D8AF10046A4CE /* MVKMTLResourceBindings.h in Headers */,
|
||||||
45003E74214AD4E600E989CB /* MVKExtensions.def in Headers */,
|
45003E74214AD4E600E989CB /* MVKExtensions.def in Headers */,
|
||||||
|
A9CEAAD6227378D400FAF779 /* mvk_datatypes.hpp in Headers */,
|
||||||
A90C8DEB1F45354D009CB32C /* MVKCommandEncodingPool.h in Headers */,
|
A90C8DEB1F45354D009CB32C /* MVKCommandEncodingPool.h in Headers */,
|
||||||
A94FB8091C7DFB4800632CA3 /* MVKResource.h in Headers */,
|
A94FB8091C7DFB4800632CA3 /* MVKResource.h in Headers */,
|
||||||
A9E53DDE2100B197002781DD /* MTLTextureDescriptor+MoltenVK.h in Headers */,
|
A9E53DDE2100B197002781DD /* MTLTextureDescriptor+MoltenVK.h in Headers */,
|
||||||
@ -974,7 +976,6 @@
|
|||||||
A94FB8301C7DFB4800632CA3 /* vk_mvk_moltenvk.mm in Sources */,
|
A94FB8301C7DFB4800632CA3 /* vk_mvk_moltenvk.mm in Sources */,
|
||||||
A94FB8161C7DFB4800632CA3 /* MVKSwapchain.mm in Sources */,
|
A94FB8161C7DFB4800632CA3 /* MVKSwapchain.mm in Sources */,
|
||||||
A95B7D6B1D3EE486003183D3 /* MVKCommandEncoderState.mm in Sources */,
|
A95B7D6B1D3EE486003183D3 /* MVKCommandEncoderState.mm in Sources */,
|
||||||
A9E337B5220129DD00363D2A /* MVKLogging.cpp in Sources */,
|
|
||||||
A93E83352121F0C8001FEBD4 /* MVKGPUCapture.mm in Sources */,
|
A93E83352121F0C8001FEBD4 /* MVKGPUCapture.mm in Sources */,
|
||||||
A9B51BD7225E986A00AC74D2 /* MVKOSExtensions.mm in Sources */,
|
A9B51BD7225E986A00AC74D2 /* MVKOSExtensions.mm in Sources */,
|
||||||
A94FB7CE1C7DFB4800632CA3 /* MVKCommand.mm in Sources */,
|
A94FB7CE1C7DFB4800632CA3 /* MVKCommand.mm in Sources */,
|
||||||
@ -1029,7 +1030,6 @@
|
|||||||
A94FB8311C7DFB4800632CA3 /* vk_mvk_moltenvk.mm in Sources */,
|
A94FB8311C7DFB4800632CA3 /* vk_mvk_moltenvk.mm in Sources */,
|
||||||
A94FB8171C7DFB4800632CA3 /* MVKSwapchain.mm in Sources */,
|
A94FB8171C7DFB4800632CA3 /* MVKSwapchain.mm in Sources */,
|
||||||
A95B7D6C1D3EE486003183D3 /* MVKCommandEncoderState.mm in Sources */,
|
A95B7D6C1D3EE486003183D3 /* MVKCommandEncoderState.mm in Sources */,
|
||||||
A9E337B6220129DD00363D2A /* MVKLogging.cpp in Sources */,
|
|
||||||
A93E83362121F0C8001FEBD4 /* MVKGPUCapture.mm in Sources */,
|
A93E83362121F0C8001FEBD4 /* MVKGPUCapture.mm in Sources */,
|
||||||
A9B51BD8225E986A00AC74D2 /* MVKOSExtensions.mm in Sources */,
|
A9B51BD8225E986A00AC74D2 /* MVKOSExtensions.mm in Sources */,
|
||||||
A94FB7CF1C7DFB4800632CA3 /* MVKCommand.mm in Sources */,
|
A94FB7CF1C7DFB4800632CA3 /* MVKCommand.mm in Sources */,
|
||||||
@ -1134,7 +1134,6 @@
|
|||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
"DEBUG=1",
|
"DEBUG=1",
|
||||||
MVK_ENV_LOG_LEVEL,
|
|
||||||
"SPIRV_CROSS_NAMESPACE_OVERRIDE=MVK_spirv_cross",
|
"SPIRV_CROSS_NAMESPACE_OVERRIDE=MVK_spirv_cross",
|
||||||
);
|
);
|
||||||
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
||||||
@ -1194,10 +1193,7 @@
|
|||||||
GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
|
GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
GCC_OPTIMIZATION_LEVEL = fast;
|
GCC_OPTIMIZATION_LEVEL = fast;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = "SPIRV_CROSS_NAMESPACE_OVERRIDE=MVK_spirv_cross";
|
||||||
MVK_ENV_LOG_LEVEL,
|
|
||||||
"SPIRV_CROSS_NAMESPACE_OVERRIDE=MVK_spirv_cross",
|
|
||||||
);
|
|
||||||
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
||||||
|
@ -299,7 +299,7 @@ VkExtent3D mvkMipmapBaseSizeFromLevelSize3D(VkExtent3D levelSize, uint32_t level
|
|||||||
*/
|
*/
|
||||||
MTLSamplerAddressMode mvkMTLSamplerAddressModeFromVkSamplerAddressMode(VkSamplerAddressMode vkMode);
|
MTLSamplerAddressMode mvkMTLSamplerAddressModeFromVkSamplerAddressMode(VkSamplerAddressMode vkMode);
|
||||||
|
|
||||||
#if MVK_MACOS
|
#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
|
||||||
/**
|
/**
|
||||||
* Returns the Metal MTLSamplerBorderColor corresponding to the specified Vulkan VkBorderColor,
|
* Returns the Metal MTLSamplerBorderColor corresponding to the specified Vulkan VkBorderColor,
|
||||||
* or returns MTLSamplerBorderColorTransparentBlack if no corresponding MTLSamplerBorderColor exists.
|
* or returns MTLSamplerBorderColorTransparentBlack if no corresponding MTLSamplerBorderColor exists.
|
||||||
|
@ -50,7 +50,7 @@ typedef unsigned long MTLLanguageVersion;
|
|||||||
*/
|
*/
|
||||||
#define MVK_VERSION_MAJOR 1
|
#define MVK_VERSION_MAJOR 1
|
||||||
#define MVK_VERSION_MINOR 0
|
#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_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch))
|
||||||
#define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH)
|
#define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH)
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include "MVKCommandPool.h"
|
#include "MVKCommandPool.h"
|
||||||
#include "MVKBuffer.h"
|
#include "MVKBuffer.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "mvk_datatypes.hpp"
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
@ -70,7 +70,7 @@ protected:
|
|||||||
#pragma mark MVKCmdDraw
|
#pragma mark MVKCmdDraw
|
||||||
|
|
||||||
/** Vulkan command to draw vertices. */
|
/** Vulkan command to draw vertices. */
|
||||||
class MVKCmdDraw : public MVKCommand, public MVKLoadStoreOverride {
|
class MVKCmdDraw : public MVKCommand, public MVKLoadStoreOverrideMixin {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setContent(uint32_t vertexCount,
|
void setContent(uint32_t vertexCount,
|
||||||
@ -94,7 +94,7 @@ protected:
|
|||||||
#pragma mark MVKCmdDrawIndexed
|
#pragma mark MVKCmdDrawIndexed
|
||||||
|
|
||||||
/** Vulkan command to draw indexed vertices. */
|
/** Vulkan command to draw indexed vertices. */
|
||||||
class MVKCmdDrawIndexed : public MVKCommand, public MVKLoadStoreOverride {
|
class MVKCmdDrawIndexed : public MVKCommand, public MVKLoadStoreOverrideMixin {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setContent(uint32_t indexCount,
|
void setContent(uint32_t indexCount,
|
||||||
@ -120,7 +120,7 @@ protected:
|
|||||||
#pragma mark MVKCmdDrawIndirect
|
#pragma mark MVKCmdDrawIndirect
|
||||||
|
|
||||||
/** Vulkan command to draw vertices indirectly. */
|
/** Vulkan command to draw vertices indirectly. */
|
||||||
class MVKCmdDrawIndirect : public MVKCommand, public MVKLoadStoreOverride {
|
class MVKCmdDrawIndirect : public MVKCommand, public MVKLoadStoreOverrideMixin {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setContent(VkBuffer buffer,
|
void setContent(VkBuffer buffer,
|
||||||
@ -144,7 +144,7 @@ protected:
|
|||||||
#pragma mark MVKCmdDrawIndexedIndirect
|
#pragma mark MVKCmdDrawIndexedIndirect
|
||||||
|
|
||||||
/** Vulkan command to draw indexed vertices indirectly. */
|
/** Vulkan command to draw indexed vertices indirectly. */
|
||||||
class MVKCmdDrawIndexedIndirect : public MVKCommand, public MVKLoadStoreOverride {
|
class MVKCmdDrawIndexedIndirect : public MVKCommand, public MVKLoadStoreOverrideMixin {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setContent(VkBuffer buffer,
|
void setContent(VkBuffer buffer,
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "MVKBuffer.h"
|
#include "MVKBuffer.h"
|
||||||
#include "MVKPipeline.h"
|
#include "MVKPipeline.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "mvk_datatypes.hpp"
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
@ -88,9 +88,8 @@ void MVKCmdDraw::setContent(uint32_t vertexCount,
|
|||||||
_storeOverride = false;
|
_storeOverride = false;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
clearConfigurationResult();
|
|
||||||
if ((_firstInstance != 0) && !(getDevice()->_pMetalFeatures->baseVertexInstanceDrawing)) {
|
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 @@ void MVKCmdDrawIndexed::setContent(uint32_t indexCount,
|
|||||||
_storeOverride = false;
|
_storeOverride = false;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
clearConfigurationResult();
|
|
||||||
if ((_firstInstance != 0) && !(getDevice()->_pMetalFeatures->baseVertexInstanceDrawing)) {
|
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)) {
|
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 @@ void MVKCmdDrawIndirect::setContent(VkBuffer buffer,
|
|||||||
_storeOverride = false;
|
_storeOverride = false;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
clearConfigurationResult();
|
|
||||||
if ( !(getDevice()->_pMetalFeatures->indirectDrawing) ) {
|
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 @@ void MVKCmdDrawIndexedIndirect::setContent(VkBuffer buffer,
|
|||||||
_storeOverride = false;
|
_storeOverride = false;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
clearConfigurationResult();
|
|
||||||
if ( !(getDevice()->_pMetalFeatures->indirectDrawing) ) {
|
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."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
#include "MVKBuffer.h"
|
#include "MVKBuffer.h"
|
||||||
#include "MVKPipeline.h"
|
#include "MVKPipeline.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "MVKEnvironment.h"
|
||||||
|
#include "mvk_datatypes.hpp"
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
@ -37,6 +37,7 @@ MVKCmdQuery::MVKCmdQuery(MVKCommandTypePool<MVKCommand>* pool) : MVKCommand::MVK
|
|||||||
#pragma mark MVKCmdBeginQuery
|
#pragma mark MVKCmdBeginQuery
|
||||||
|
|
||||||
void MVKCmdBeginQuery::added(MVKCommandBuffer* cmdBuffer) {
|
void MVKCmdBeginQuery::added(MVKCommandBuffer* cmdBuffer) {
|
||||||
|
MVKCommand::added(cmdBuffer);
|
||||||
_queryPool->beginQueryAddedTo(_query, cmdBuffer);
|
_queryPool->beginQueryAddedTo(_query, cmdBuffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class MVKFramebuffer;
|
|||||||
#pragma mark MVKCmdBeginRenderPass
|
#pragma mark MVKCmdBeginRenderPass
|
||||||
|
|
||||||
/** Vulkan command to begin a render pass. */
|
/** Vulkan command to begin a render pass. */
|
||||||
class MVKCmdBeginRenderPass : public MVKCommand, public MVKLoadStoreOverride {
|
class MVKCmdBeginRenderPass : public MVKCommand, public MVKLoadStoreOverrideMixin {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setContent(const VkRenderPassBeginInfo* pRenderPassBegin,
|
void setContent(const VkRenderPassBeginInfo* pRenderPassBegin,
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "MVKRenderPass.h"
|
#include "MVKRenderPass.h"
|
||||||
#include "MVKPipeline.h"
|
#include "MVKPipeline.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "mvk_datatypes.hpp"
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
@ -149,9 +149,8 @@ void MVKCmdSetLineWidth::setContent(float lineWidth) {
|
|||||||
_lineWidth = lineWidth;
|
_lineWidth = lineWidth;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
clearConfigurationResult();
|
|
||||||
if (_lineWidth != 1.0 || getDevice()->_enabledFeatures.wideLines) {
|
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 @@ void MVKCmdSetDepthBounds::setContent(float minDepthBounds, float maxDepthBounds
|
|||||||
_maxDepthBounds = maxDepthBounds;
|
_maxDepthBounds = maxDepthBounds;
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
clearConfigurationResult();
|
|
||||||
if (getDevice()->_enabledFeatures.depthBounds) {
|
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."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,9 @@
|
|||||||
#include "MVKFramebuffer.h"
|
#include "MVKFramebuffer.h"
|
||||||
#include "MVKRenderPass.h"
|
#include "MVKRenderPass.h"
|
||||||
#include "MTLRenderPassDescriptor+MoltenVK.h"
|
#include "MTLRenderPassDescriptor+MoltenVK.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "MVKEnvironment.h"
|
||||||
|
#include "MVKLogging.h"
|
||||||
|
#include "mvk_datatypes.hpp"
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
@ -58,9 +60,8 @@ void MVKCmdCopyImage::setContent(VkImage srcImage,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
clearConfigurationResult();
|
|
||||||
if ((_srcImage->getMTLTextureType() == MTLTextureType3D) != (_dstImage->getMTLTextureType() == MTLTextureType3D)) {
|
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 @@ void MVKCmdBlitImage::setContent(VkImage srcImage,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
clearConfigurationResult();
|
|
||||||
if (_blitKey.isDepthFormat() && renderRegionCount > 0) {
|
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)) {
|
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 @@ void MVKCmdBufferImageCopy::setContent(VkBuffer buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
clearConfigurationResult();
|
|
||||||
if ( !_image->hasExpectedTexelSize() ) {
|
if ( !_image->hasExpectedTexelSize() ) {
|
||||||
const char* cmdName = _toImage ? "vkCmdCopyBufferToImage" : "vkCmdCopyImageToBuffer";
|
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())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,8 +37,11 @@ class MVKCommand : public MVKConfigurableObject {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** Returns the Vulkan API opaque object controlling this object. */
|
||||||
|
MVKVulkanAPIObject* getVulkanAPIObject() override;
|
||||||
|
|
||||||
/** Called when this command is added to a command buffer. */
|
/** 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. */
|
/** Indicates that this command has a valid configuration and can be encoded. */
|
||||||
inline bool canEncode() { return _configurationResult == VK_SUCCESS; }
|
inline bool canEncode() { return _configurationResult == VK_SUCCESS; }
|
||||||
@ -84,18 +87,31 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
MVKCommandTypePool<MVKCommand>* _pool;
|
MVKCommandTypePool<MVKCommand>* _pool;
|
||||||
|
MVKCommandBuffer* _commandBuffer = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKCommandTypePool
|
#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. */
|
/** A pool of MVKCommand instances of a particular type. */
|
||||||
template <class T>
|
template <class T>
|
||||||
class MVKCommandTypePool : public MVKObjectPool<T> {
|
class MVKCommandTypePool : public MVKObjectPool<T> {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Some commands require access to the command pool to access resources. */
|
||||||
MVKCommandPool* getCommandPool() { return _commandPool; }
|
MVKCommandPool* getCommandPool() { return _commandPool; }
|
||||||
|
|
||||||
@ -114,10 +130,16 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#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:
|
public:
|
||||||
void setLoadOverride(bool loadOverride);
|
void setLoadOverride(bool loadOverride);
|
||||||
void setStoreOverride(bool storeOverride);
|
void setStoreOverride(bool storeOverride);
|
||||||
|
@ -27,7 +27,13 @@
|
|||||||
// Opt 1: Leave arrays & rezs allocated in command, per current practice
|
// 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
|
// 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(); }
|
MVKCommandPool* MVKCommand::getCommandPool() { return _pool->getCommandPool(); }
|
||||||
|
|
||||||
@ -39,13 +45,19 @@ id<MTLDevice> MVKCommand::getMTLDevice() { return getCommandPool()->getMTLDevice
|
|||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#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;
|
_loadOverride = loadOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKLoadStoreOverride::setStoreOverride(bool storeOverride) {
|
void MVKLoadStoreOverrideMixin::setStoreOverride(bool storeOverride) {
|
||||||
_storeOverride = storeOverride;
|
_storeOverride = storeOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class MVKGraphicsPipeline;
|
|||||||
class MVKComputePipeline;
|
class MVKComputePipeline;
|
||||||
class MVKCmdBeginRenderPass;
|
class MVKCmdBeginRenderPass;
|
||||||
class MVKCmdEndRenderPass;
|
class MVKCmdEndRenderPass;
|
||||||
class MVKLoadStoreOverride;
|
class MVKLoadStoreOverrideMixin;
|
||||||
|
|
||||||
typedef uint64_t MVKMTLCommandBufferID;
|
typedef uint64_t MVKMTLCommandBufferID;
|
||||||
|
|
||||||
@ -50,10 +50,16 @@ typedef uint64_t MVKMTLCommandBufferID;
|
|||||||
#pragma mark MVKCommandBuffer
|
#pragma mark MVKCommandBuffer
|
||||||
|
|
||||||
/** Represents a Vulkan command pool. */
|
/** Represents a Vulkan command pool. */
|
||||||
class MVKCommandBuffer : public MVKDispatchableDeviceObject {
|
class MVKCommandBuffer : public MVKDispatchableVulkanAPIObject, public MVKDeviceTrackingMixin {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Prepares this instance to receive commands. */
|
||||||
VkResult begin(const VkCommandBufferBeginInfo* pBeginInfo);
|
VkResult begin(const VkCommandBufferBeginInfo* pBeginInfo);
|
||||||
|
|
||||||
@ -72,12 +78,6 @@ public:
|
|||||||
/** Submit the commands in this buffer as part of the queue submission. */
|
/** Submit the commands in this buffer as part of the queue submission. */
|
||||||
void submit(MVKQueueCommandBufferSubmission* cmdBuffSubmit);
|
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. */
|
/** Returns whether this command buffer can be submitted to a queue more than once. */
|
||||||
inline bool getIsReusable() { return _isReusable; }
|
inline bool getIsReusable() { return _isReusable; }
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ public:
|
|||||||
void recordBindPipeline(MVKCmdBindPipeline* mvkBindPipeline);
|
void recordBindPipeline(MVKCmdBindPipeline* mvkBindPipeline);
|
||||||
|
|
||||||
/** Update the last recorded drawcall to determine load/store actions */
|
/** Update the last recorded drawcall to determine load/store actions */
|
||||||
void recordDraw(MVKLoadStoreOverride* mvkDraw);
|
void recordDraw(MVKLoadStoreOverrideMixin* mvkDraw);
|
||||||
|
|
||||||
/** The most recent recorded begin renderpass */
|
/** The most recent recorded begin renderpass */
|
||||||
MVKCmdBeginRenderPass* _lastBeginRenderPass;
|
MVKCmdBeginRenderPass* _lastBeginRenderPass;
|
||||||
@ -121,12 +121,12 @@ public:
|
|||||||
MVKCmdBindPipeline* _lastTessellationPipeline;
|
MVKCmdBindPipeline* _lastTessellationPipeline;
|
||||||
|
|
||||||
/** The most recent recorded multi-pass (ie, tessellation) draw */
|
/** The most recent recorded multi-pass (ie, tessellation) draw */
|
||||||
MVKLoadStoreOverride* _lastTessellationDraw;
|
MVKLoadStoreOverrideMixin* _lastTessellationDraw;
|
||||||
|
|
||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKCommandBuffer(MVKDevice* device) : MVKDispatchableDeviceObject(device) {}
|
MVKCommandBuffer(MVKDevice* device) : MVKDeviceTrackingMixin(device) {}
|
||||||
|
|
||||||
~MVKCommandBuffer() override;
|
~MVKCommandBuffer() override;
|
||||||
|
|
||||||
@ -148,6 +148,7 @@ protected:
|
|||||||
friend class MVKCommandEncoder;
|
friend class MVKCommandEncoder;
|
||||||
friend class MVKCommandPool;
|
friend class MVKCommandPool;
|
||||||
|
|
||||||
|
MVKBaseObject* getBaseObject() override { return this; };
|
||||||
void init(const VkCommandBufferAllocateInfo* pAllocateInfo);
|
void init(const VkCommandBufferAllocateInfo* pAllocateInfo);
|
||||||
bool canExecute();
|
bool canExecute();
|
||||||
bool canPrefill();
|
bool canPrefill();
|
||||||
@ -158,7 +159,6 @@ protected:
|
|||||||
MVKCommand* _tail = nullptr;
|
MVKCommand* _tail = nullptr;
|
||||||
uint32_t _commandCount;
|
uint32_t _commandCount;
|
||||||
std::atomic_flag _isExecutingNonConcurrently;
|
std::atomic_flag _isExecutingNonConcurrently;
|
||||||
VkResult _recordingResult;
|
|
||||||
VkCommandBufferInheritanceInfo _secondaryInheritanceInfo;
|
VkCommandBufferInheritanceInfo _secondaryInheritanceInfo;
|
||||||
id<MTLCommandBuffer> _prefilledMTLCmdBuffer = nil;
|
id<MTLCommandBuffer> _prefilledMTLCmdBuffer = nil;
|
||||||
bool _isSecondary;
|
bool _isSecondary;
|
||||||
@ -255,6 +255,9 @@ class MVKCommandEncoder : public MVKBaseDeviceObject {
|
|||||||
|
|
||||||
public:
|
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. */
|
/** Encode commands from the command buffer onto the Metal command buffer. */
|
||||||
void encode(id<MTLCommandBuffer> mtlCmdBuff);
|
void encode(id<MTLCommandBuffer> mtlCmdBuff);
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "MVKFramebuffer.h"
|
#include "MVKFramebuffer.h"
|
||||||
#include "MVKQueryPool.h"
|
#include "MVKQueryPool.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
|
#include "MVKLogging.h"
|
||||||
#include "MTLRenderPassDescriptor+MoltenVK.h"
|
#include "MTLRenderPassDescriptor+MoltenVK.h"
|
||||||
#include "MVKCmdDraw.h"
|
#include "MVKCmdDraw.h"
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ VkResult MVKCommandBuffer::begin(const VkCommandBufferBeginInfo* pBeginInfo) {
|
|||||||
|
|
||||||
reset(0);
|
reset(0);
|
||||||
|
|
||||||
_recordingResult = VK_SUCCESS;
|
clearConfigurationResult();
|
||||||
_canAcceptCommands = true;
|
_canAcceptCommands = true;
|
||||||
|
|
||||||
VkCommandBufferUsageFlags usage = pBeginInfo->flags;
|
VkCommandBufferUsageFlags usage = pBeginInfo->flags;
|
||||||
@ -50,7 +51,7 @@ VkResult MVKCommandBuffer::begin(const VkCommandBufferBeginInfo* pBeginInfo) {
|
|||||||
bool hasInheritInfo = mvkSetOrClear(&_secondaryInheritanceInfo, pInheritInfo);
|
bool hasInheritInfo = mvkSetOrClear(&_secondaryInheritanceInfo, pInheritInfo);
|
||||||
_doesContinueRenderPass = mvkAreFlagsEnabled(usage, VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) && hasInheritInfo;
|
_doesContinueRenderPass = mvkAreFlagsEnabled(usage, VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) && hasInheritInfo;
|
||||||
|
|
||||||
return _recordingResult;
|
return getConfigurationResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult MVKCommandBuffer::reset(VkCommandBufferResetFlags flags) {
|
VkResult MVKCommandBuffer::reset(VkCommandBufferResetFlags flags) {
|
||||||
@ -71,9 +72,9 @@ VkResult MVKCommandBuffer::reset(VkCommandBufferResetFlags flags) {
|
|||||||
_supportsConcurrentExecution = false;
|
_supportsConcurrentExecution = false;
|
||||||
_wasExecuted = false;
|
_wasExecuted = false;
|
||||||
_isExecutingNonConcurrently.clear();
|
_isExecutingNonConcurrently.clear();
|
||||||
_recordingResult = VK_NOT_READY;
|
|
||||||
_commandCount = 0;
|
_commandCount = 0;
|
||||||
_initialVisibilityResultMTLBuffer = nil; // not retained
|
_initialVisibilityResultMTLBuffer = nil; // not retained
|
||||||
|
setConfigurationResult(VK_NOT_READY);
|
||||||
|
|
||||||
if (mvkAreFlagsEnabled(flags, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT)) {
|
if (mvkAreFlagsEnabled(flags, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT)) {
|
||||||
// TODO: what are we releasing or returning here?
|
// TODO: what are we releasing or returning here?
|
||||||
@ -85,12 +86,12 @@ VkResult MVKCommandBuffer::reset(VkCommandBufferResetFlags flags) {
|
|||||||
VkResult MVKCommandBuffer::end() {
|
VkResult MVKCommandBuffer::end() {
|
||||||
_canAcceptCommands = false;
|
_canAcceptCommands = false;
|
||||||
prefill();
|
prefill();
|
||||||
return _recordingResult;
|
return getConfigurationResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKCommandBuffer::addCommand(MVKCommand* command) {
|
void MVKCommandBuffer::addCommand(MVKCommand* command) {
|
||||||
if ( !_canAcceptCommands ) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +103,7 @@ void MVKCommandBuffer::addCommand(MVKCommand* command) {
|
|||||||
|
|
||||||
command->added(this);
|
command->added(this);
|
||||||
|
|
||||||
recordResult(command->getConfigurationResult());
|
setConfigurationResult(command->getConfigurationResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKCommandBuffer::submit(MVKQueueCommandBufferSubmission* cmdBuffSubmit) {
|
void MVKCommandBuffer::submit(MVKQueueCommandBufferSubmission* cmdBuffSubmit) {
|
||||||
@ -121,17 +122,17 @@ void MVKCommandBuffer::submit(MVKQueueCommandBufferSubmission* cmdBuffSubmit) {
|
|||||||
|
|
||||||
bool MVKCommandBuffer::canExecute() {
|
bool MVKCommandBuffer::canExecute() {
|
||||||
if (_isSecondary) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if ( !_isReusable && _wasExecuted ) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do this test last so that _isExecutingNonConcurrently is only set if everything else passes
|
// Do this test last so that _isExecutingNonConcurrently is only set if everything else passes
|
||||||
if ( !_supportsConcurrentExecution && _isExecutingNonConcurrently.test_and_set()) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +218,7 @@ void MVKCommandBuffer::recordBindPipeline(MVKCmdBindPipeline* mvkBindPipeline) {
|
|||||||
_lastTessellationPipeline = nullptr;
|
_lastTessellationPipeline = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKCommandBuffer::recordDraw(MVKLoadStoreOverride* mvkDraw) {
|
void MVKCommandBuffer::recordDraw(MVKLoadStoreOverrideMixin* mvkDraw) {
|
||||||
if (_lastTessellationPipeline != nullptr) {
|
if (_lastTessellationPipeline != nullptr) {
|
||||||
// If a multi-pass pipeline is bound and we've already drawn something, need to override load actions
|
// If a multi-pass pipeline is bound and we've already drawn something, need to override load actions
|
||||||
mvkDraw->setLoadOverride(true);
|
mvkDraw->setLoadOverride(true);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "MVKMTLResourceBindings.h"
|
#include "MVKMTLResourceBindings.h"
|
||||||
#include "MVKCommandResourceFactory.h"
|
#include "MVKCommandResourceFactory.h"
|
||||||
|
#include "MVKDevice.h"
|
||||||
#include "MVKVector.h"
|
#include "MVKVector.h"
|
||||||
|
|
||||||
class MVKCommandEncoder;
|
class MVKCommandEncoder;
|
||||||
@ -43,6 +44,9 @@ class MVKCommandEncoderState : public MVKBaseObject {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** Returns the Vulkan API opaque object controlling this object. */
|
||||||
|
MVKVulkanAPIObject* getVulkanAPIObject() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the content of this instance as dirty, relative to the
|
* Marks the content of this instance as dirty, relative to the
|
||||||
* current or next Metal render pass, and in need of submission to Metal.
|
* current or next Metal render pass, and in need of submission to Metal.
|
||||||
@ -399,6 +403,9 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateSwizzle(MVKVector<uint32_t> &constants, uint32_t index, uint32_t swizzle);
|
||||||
|
void assertMissingSwizzles(bool needsSwizzle, const char* stageName, MVKVector<MVKMTLTextureBinding>& texBindings);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,11 +23,16 @@
|
|||||||
#include "MVKPipeline.h"
|
#include "MVKPipeline.h"
|
||||||
#include "MVKQueryPool.h"
|
#include "MVKQueryPool.h"
|
||||||
#include "MVKLogging.h"
|
#include "MVKLogging.h"
|
||||||
#include "mvk_datatypes.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark MVKCommandEncoderState
|
||||||
|
|
||||||
|
MVKVulkanAPIObject* MVKCommandEncoderState::getVulkanAPIObject() { return _cmdEncoder->getVulkanAPIObject(); };
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKPipelineCommandEncoderState
|
#pragma mark MVKPipelineCommandEncoderState
|
||||||
|
|
||||||
@ -443,13 +448,13 @@ void MVKBlendColorCommandEncoderState::resetImpl() {
|
|||||||
#pragma mark MVKResourcesCommandEncoderState
|
#pragma mark MVKResourcesCommandEncoderState
|
||||||
|
|
||||||
// Updates the swizzle for an image in the given vector.
|
// 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); }
|
if (index >= constants.size()) { constants.resize(index + 1); }
|
||||||
constants[index] = swizzle;
|
constants[index] = swizzle;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a swizzle is needed for this stage, iterates all the bindings and logs errors for those that need texture swizzling.
|
// 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) {
|
if (needsSwizzle) {
|
||||||
for (MVKMTLTextureBinding& tb : texBindings) {
|
for (MVKMTLTextureBinding& tb : texBindings) {
|
||||||
VkComponentMapping vkcm = mvkUnpackSwizzle(tb.swizzle);
|
VkComponentMapping vkcm = mvkUnpackSwizzle(tb.swizzle);
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "MVKDevice.h"
|
|
||||||
#include "MVKCommandResourceFactory.h"
|
#include "MVKCommandResourceFactory.h"
|
||||||
#include "MVKMTLBufferAllocation.h"
|
#include "MVKMTLBufferAllocation.h"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -27,6 +26,9 @@
|
|||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
|
|
||||||
|
class MVKCommandPool;
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKCommandEncodingPool
|
#pragma mark MVKCommandEncodingPool
|
||||||
|
|
||||||
@ -37,12 +39,15 @@
|
|||||||
*
|
*
|
||||||
* Access to the content within this pool is thread-safe.
|
* Access to the content within this pool is thread-safe.
|
||||||
*/
|
*/
|
||||||
class MVKCommandEncodingPool : public MVKBaseDeviceObject {
|
class MVKCommandEncodingPool : public MVKBaseObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
#pragma mark Command resources
|
#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. */
|
/** Returns a MTLRenderPipelineState to support certain Vulkan BLIT commands. */
|
||||||
id<MTLRenderPipelineState> getCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey);
|
id<MTLRenderPipelineState> getCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey);
|
||||||
|
|
||||||
@ -124,13 +129,14 @@ public:
|
|||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKCommandEncodingPool(MVKDevice* device);
|
MVKCommandEncodingPool(MVKCommandPool* commandPool);
|
||||||
|
|
||||||
~MVKCommandEncodingPool() override;
|
~MVKCommandEncodingPool() override;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void destroyMetalResources();
|
void destroyMetalResources();
|
||||||
|
|
||||||
|
MVKCommandPool* _commandPool;
|
||||||
std::mutex _lock;
|
std::mutex _lock;
|
||||||
std::unordered_map<MVKRPSKeyBlitImg, id<MTLRenderPipelineState>> _cmdBlitImageMTLRenderPipelineStates;
|
std::unordered_map<MVKRPSKeyBlitImg, id<MTLRenderPipelineState>> _cmdBlitImageMTLRenderPipelineStates;
|
||||||
std::unordered_map<MVKRPSKeyClearAtt, id<MTLRenderPipelineState>> _cmdClearMTLRenderPipelineStates;
|
std::unordered_map<MVKRPSKeyClearAtt, id<MTLRenderPipelineState>> _cmdClearMTLRenderPipelineStates;
|
||||||
|
@ -17,13 +17,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MVKCommandEncodingPool.h"
|
#include "MVKCommandEncodingPool.h"
|
||||||
|
#include "MVKCommandPool.h"
|
||||||
#include "MVKImage.h"
|
#include "MVKImage.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKCommandEncodingPool
|
#pragma mark MVKCommandEncodingPool
|
||||||
|
|
||||||
|
MVKVulkanAPIObject* MVKCommandEncodingPool::getVulkanAPIObject() { return _commandPool->getVulkanAPIObject(); };
|
||||||
|
|
||||||
|
|
||||||
// In order to provide thread-safety with minimal performance impact, each of these access
|
// In order to provide thread-safety with minimal performance impact, each of these access
|
||||||
// functions follows a 3-step pattern:
|
// functions follows a 3-step pattern:
|
||||||
//
|
//
|
||||||
@ -42,17 +47,17 @@ using namespace std;
|
|||||||
rez = rezAccess; \
|
rez = rezAccess; \
|
||||||
if (rez) { return rez; } \
|
if (rez) { return rez; } \
|
||||||
\
|
\
|
||||||
rez = _device->getCommandResourceFactory()->rezFactoryFunc; \
|
rez = _commandPool->getDevice()->getCommandResourceFactory()->rezFactoryFunc; \
|
||||||
rezAccess = rez; \
|
rezAccess = rez; \
|
||||||
return rez
|
return rez
|
||||||
|
|
||||||
|
|
||||||
id<MTLRenderPipelineState> MVKCommandEncodingPool::getCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey) {
|
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) {
|
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) {
|
id<MTLSamplerState> MVKCommandEncodingPool::getCmdBlitImageMTLSamplerState(MTLSamplerMinMagFilter mtlFilter) {
|
||||||
@ -102,23 +107,23 @@ MVKBuffer* MVKCommandEncodingPool::getTransferMVKBuffer(MVKBufferDescriptorData&
|
|||||||
}
|
}
|
||||||
|
|
||||||
id<MTLComputePipelineState> MVKCommandEncodingPool::getCmdCopyBufferBytesMTLComputePipelineState() {
|
id<MTLComputePipelineState> MVKCommandEncodingPool::getCmdCopyBufferBytesMTLComputePipelineState() {
|
||||||
MVK_ENC_REZ_ACCESS(_mtlCopyBufferBytesComputePipelineState, newCmdCopyBufferBytesMTLComputePipelineState());
|
MVK_ENC_REZ_ACCESS(_mtlCopyBufferBytesComputePipelineState, newCmdCopyBufferBytesMTLComputePipelineState(_commandPool));
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLComputePipelineState> MVKCommandEncodingPool::getCmdFillBufferMTLComputePipelineState() {
|
id<MTLComputePipelineState> MVKCommandEncodingPool::getCmdFillBufferMTLComputePipelineState() {
|
||||||
MVK_ENC_REZ_ACCESS(_mtlFillBufferComputePipelineState, newCmdFillBufferMTLComputePipelineState());
|
MVK_ENC_REZ_ACCESS(_mtlFillBufferComputePipelineState, newCmdFillBufferMTLComputePipelineState(_commandPool));
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLComputePipelineState> MVKCommandEncodingPool::getCmdCopyBufferToImage3DDecompressMTLComputePipelineState(bool needsTempBuff) {
|
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) {
|
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) {
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKCommandEncodingPool::clear() {
|
void MVKCommandEncodingPool::clear() {
|
||||||
@ -129,8 +134,8 @@ void MVKCommandEncodingPool::clear() {
|
|||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKCommandEncodingPool::MVKCommandEncodingPool(MVKDevice* device) : MVKBaseDeviceObject(device),
|
MVKCommandEncodingPool::MVKCommandEncodingPool(MVKCommandPool* commandPool) : _commandPool(commandPool),
|
||||||
_mtlBufferAllocator(device, device->_pMetalFeatures->maxMTLBufferSize, true) {
|
_mtlBufferAllocator(commandPool->getDevice(), commandPool->getDevice()->_pMetalFeatures->maxMTLBufferSize, true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKCommandEncodingPool::~MVKCommandEncodingPool() {
|
MVKCommandEncodingPool::~MVKCommandEncodingPool() {
|
||||||
@ -139,6 +144,8 @@ MVKCommandEncodingPool::~MVKCommandEncodingPool() {
|
|||||||
|
|
||||||
/** Ensure all cached Metal components are released. */
|
/** Ensure all cached Metal components are released. */
|
||||||
void MVKCommandEncodingPool::destroyMetalResources() {
|
void MVKCommandEncodingPool::destroyMetalResources() {
|
||||||
|
MVKDevice* mvkDev = _commandPool->getDevice();
|
||||||
|
|
||||||
for (auto& pair : _cmdBlitImageMTLRenderPipelineStates) { [pair.second release]; }
|
for (auto& pair : _cmdBlitImageMTLRenderPipelineStates) { [pair.second release]; }
|
||||||
_cmdBlitImageMTLRenderPipelineStates.clear();
|
_cmdBlitImageMTLRenderPipelineStates.clear();
|
||||||
|
|
||||||
@ -148,13 +155,13 @@ void MVKCommandEncodingPool::destroyMetalResources() {
|
|||||||
for (auto& pair : _mtlDepthStencilStates) { [pair.second release]; }
|
for (auto& pair : _mtlDepthStencilStates) { [pair.second release]; }
|
||||||
_mtlDepthStencilStates.clear();
|
_mtlDepthStencilStates.clear();
|
||||||
|
|
||||||
for (auto& pair : _transferImages) { _device->destroyImage(pair.second, nullptr); }
|
for (auto& pair : _transferImages) { mvkDev->destroyImage(pair.second, nullptr); }
|
||||||
_transferImages.clear();
|
_transferImages.clear();
|
||||||
|
|
||||||
for (auto& pair : _transferBuffers) { _device->destroyBuffer(pair.second, nullptr); }
|
for (auto& pair : _transferBuffers) { mvkDev->destroyBuffer(pair.second, nullptr); }
|
||||||
_transferBuffers.clear();
|
_transferBuffers.clear();
|
||||||
|
|
||||||
for (auto& pair : _transferBufferMemory) { _device->freeMemory(pair.second, nullptr); }
|
for (auto& pair : _transferBufferMemory) { mvkDev->freeMemory(pair.second, nullptr); }
|
||||||
_transferBufferMemory.clear();
|
_transferBufferMemory.clear();
|
||||||
|
|
||||||
[_cmdBlitImageLinearMTLSamplerState release];
|
[_cmdBlitImageLinearMTLSamplerState release];
|
||||||
|
@ -49,10 +49,13 @@
|
|||||||
* of this pool should be done during the setContent() function of each MVKCommand, and NOT
|
* 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.
|
* during the execution of the command via the MVKCommand::encode() member function.
|
||||||
*/
|
*/
|
||||||
class MVKCommandPool : public MVKBaseDeviceObject {
|
class MVKCommandPool : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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
|
#pragma mark Command type pools
|
||||||
|
|
||||||
MVKCommandTypePool<MVKCmdPipelineBarrier> _cmdPipelineBarrierPool;
|
MVKCommandTypePool<MVKCmdPipelineBarrier> _cmdPipelineBarrierPool;
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "MVKQueue.h"
|
#include "MVKQueue.h"
|
||||||
#include "MVKDeviceMemory.h"
|
#include "MVKDeviceMemory.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "mvk_datatypes.hpp"
|
||||||
#include "MVKLogging.h"
|
#include "MVKLogging.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -56,7 +56,10 @@ VkResult MVKCommandPool::allocateCommandBuffers(const VkCommandBufferAllocateInf
|
|||||||
mvkCmdBuff->init(pAllocateInfo);
|
mvkCmdBuff->init(pAllocateInfo);
|
||||||
_allocatedCommandBuffers.insert(mvkCmdBuff);
|
_allocatedCommandBuffers.insert(mvkCmdBuff);
|
||||||
pCmdBuffer[cbIdx] = mvkCmdBuff->getVkCommandBuffer();
|
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;
|
return rslt;
|
||||||
}
|
}
|
||||||
@ -127,9 +130,9 @@ void MVKCommandPool::trim() {
|
|||||||
|
|
||||||
MVKCommandPool::MVKCommandPool(MVKDevice* device,
|
MVKCommandPool::MVKCommandPool(MVKDevice* device,
|
||||||
const VkCommandPoolCreateInfo* pCreateInfo) :
|
const VkCommandPoolCreateInfo* pCreateInfo) :
|
||||||
MVKBaseDeviceObject(device),
|
MVKVulkanAPIDeviceObject(device),
|
||||||
_commandBufferPool(device),
|
_commandBufferPool(device),
|
||||||
_commandEncodingPool(device),
|
_commandEncodingPool(this),
|
||||||
_queueFamilyIndex(pCreateInfo->queueFamilyIndex),
|
_queueFamilyIndex(pCreateInfo->queueFamilyIndex),
|
||||||
_cmdPipelineBarrierPool(this, true),
|
_cmdPipelineBarrierPool(this, true),
|
||||||
_cmdBindPipelinePool(this, true),
|
_cmdBindPipelinePool(this, true),
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include "MVKDevice.h"
|
#include "MVKDevice.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "mvk_datatypes.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
@ -306,10 +306,14 @@ class MVKCommandResourceFactory : public MVKBaseDeviceObject {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** Returns the Vulkan API opaque object controlling this object. */
|
||||||
|
MVKVulkanAPIObject* getVulkanAPIObject() override { return _device->getVulkanAPIObject(); };
|
||||||
|
|
||||||
#pragma mark Command resources
|
#pragma mark Command resources
|
||||||
|
|
||||||
/** Returns a new MTLRenderPipelineState to support certain Vulkan BLIT commands. */
|
/** 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
|
* Returns a new MTLSamplerState dedicated to rendering to a texture using the
|
||||||
@ -321,7 +325,8 @@ public:
|
|||||||
* Returns a new MTLRenderPipelineState dedicated to rendering to several
|
* Returns a new MTLRenderPipelineState dedicated to rendering to several
|
||||||
* attachments to support clearing regions of those attachments.
|
* 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
|
* Returns a new MTLDepthStencilState dedicated to rendering to several
|
||||||
@ -353,19 +358,22 @@ public:
|
|||||||
MVKBuffer* newMVKBuffer(MVKBufferDescriptorData& buffData, MVKDeviceMemory*& buffMem);
|
MVKBuffer* newMVKBuffer(MVKBufferDescriptorData& buffData, MVKDeviceMemory*& buffMem);
|
||||||
|
|
||||||
/** Returns a new MTLComputePipelineState for copying between two buffers with byte-aligned copy regions. */
|
/** 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. */
|
/** 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. */
|
/** 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. */
|
/** 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. */
|
/** 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);
|
||||||
|
|
||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
@ -383,8 +391,10 @@ protected:
|
|||||||
NSString* getMTLFormatTypeString(MTLPixelFormat mtlPixFmt);
|
NSString* getMTLFormatTypeString(MTLPixelFormat mtlPixFmt);
|
||||||
id<MTLFunction> getFunctionNamed(const char* funcName);
|
id<MTLFunction> getFunctionNamed(const char* funcName);
|
||||||
id<MTLFunction> newMTLFunction(NSString* mslSrcCode, NSString* funcName);
|
id<MTLFunction> newMTLFunction(NSString* mslSrcCode, NSString* funcName);
|
||||||
id<MTLRenderPipelineState> newMTLRenderPipelineState(MTLRenderPipelineDescriptor* plDesc);
|
id<MTLRenderPipelineState> newMTLRenderPipelineState(MTLRenderPipelineDescriptor* plDesc,
|
||||||
id<MTLComputePipelineState> newMTLComputePipelineState(id<MTLFunction> mtlFunction);
|
MVKVulkanAPIDeviceObject* owner);
|
||||||
|
id<MTLComputePipelineState> newMTLComputePipelineState(id<MTLFunction> mtlFunction,
|
||||||
|
MVKVulkanAPIDeviceObject* owner);
|
||||||
|
|
||||||
id<MTLLibrary> _mtlLibrary;
|
id<MTLLibrary> _mtlLibrary;
|
||||||
MVKDeviceMemory* _transferImageMemory;
|
MVKDeviceMemory* _transferImageMemory;
|
||||||
|
@ -31,7 +31,8 @@ using namespace std;
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKCommandResourceFactory
|
#pragma mark MVKCommandResourceFactory
|
||||||
|
|
||||||
id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey) {
|
id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey,
|
||||||
|
MVKVulkanAPIDeviceObject* owner) {
|
||||||
MTLRenderPipelineDescriptor* plDesc = [[[MTLRenderPipelineDescriptor alloc] init] autorelease];
|
MTLRenderPipelineDescriptor* plDesc = [[[MTLRenderPipelineDescriptor alloc] init] autorelease];
|
||||||
plDesc.label = @"CmdBlitImage";
|
plDesc.label = @"CmdBlitImage";
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdBlitImageMTLRenderPi
|
|||||||
vbDesc.stepRate = 1;
|
vbDesc.stepRate = 1;
|
||||||
vbDesc.stride = vtxStride;
|
vbDesc.stride = vtxStride;
|
||||||
|
|
||||||
return newMTLRenderPipelineState(plDesc);
|
return newMTLRenderPipelineState(plDesc, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLSamplerState> MVKCommandResourceFactory::newCmdBlitImageMTLSamplerState(MTLSamplerMinMagFilter mtlFilter) {
|
id<MTLSamplerState> MVKCommandResourceFactory::newCmdBlitImageMTLSamplerState(MTLSamplerMinMagFilter mtlFilter) {
|
||||||
@ -85,7 +86,8 @@ id<MTLSamplerState> MVKCommandResourceFactory::newCmdBlitImageMTLSamplerState(MT
|
|||||||
return [getMTLDevice() newSamplerStateWithDescriptor: sDesc];
|
return [getMTLDevice() newSamplerStateWithDescriptor: sDesc];
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey) {
|
id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey,
|
||||||
|
MVKVulkanAPIDeviceObject* owner) {
|
||||||
MTLRenderPipelineDescriptor* plDesc = [[[MTLRenderPipelineDescriptor alloc] init] autorelease];
|
MTLRenderPipelineDescriptor* plDesc = [[[MTLRenderPipelineDescriptor alloc] init] autorelease];
|
||||||
plDesc.label = @"CmdClearAttachments";
|
plDesc.label = @"CmdClearAttachments";
|
||||||
plDesc.vertexFunction = getClearVertFunction(attKey);
|
plDesc.vertexFunction = getClearVertFunction(attKey);
|
||||||
@ -124,7 +126,7 @@ id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdClearMTLRenderPipeli
|
|||||||
vbDesc.stepRate = 1;
|
vbDesc.stepRate = 1;
|
||||||
vbDesc.stride = vtxStride;
|
vbDesc.stride = vtxStride;
|
||||||
|
|
||||||
return newMTLRenderPipelineState(plDesc);
|
return newMTLRenderPipelineState(plDesc, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLFunction> MVKCommandResourceFactory::getBlitFragFunction(MVKRPSKeyBlitImg& blitKey) {
|
id<MTLFunction> MVKCommandResourceFactory::getBlitFragFunction(MVKRPSKeyBlitImg& blitKey) {
|
||||||
@ -372,27 +374,33 @@ MVKBuffer* MVKCommandResourceFactory::newMVKBuffer(MVKBufferDescriptorData& buff
|
|||||||
return mvkBuff;
|
return mvkBuff;
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdCopyBufferBytesMTLComputePipelineState() {
|
id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdCopyBufferBytesMTLComputePipelineState(MVKVulkanAPIDeviceObject* owner) {
|
||||||
return newMTLComputePipelineState(getFunctionNamed("cmdCopyBufferBytes"));
|
return newMTLComputePipelineState(getFunctionNamed("cmdCopyBufferBytes"), owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdFillBufferMTLComputePipelineState() {
|
id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdFillBufferMTLComputePipelineState(MVKVulkanAPIDeviceObject* owner) {
|
||||||
return newMTLComputePipelineState(getFunctionNamed("cmdFillBuffer"));
|
return newMTLComputePipelineState(getFunctionNamed("cmdFillBuffer"), owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdCopyBufferToImage3DDecompressMTLComputePipelineState(bool needTempBuf) {
|
id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdCopyBufferToImage3DDecompressMTLComputePipelineState(bool needTempBuf,
|
||||||
return newMTLComputePipelineState(getFunctionNamed(needTempBuf ? "cmdCopyBufferToImage3DDecompressTempBufferDXTn" :
|
MVKVulkanAPIDeviceObject* owner) {
|
||||||
"cmdCopyBufferToImage3DDecompressDXTn"));
|
return newMTLComputePipelineState(getFunctionNamed(needTempBuf
|
||||||
|
? "cmdCopyBufferToImage3DDecompressTempBufferDXTn"
|
||||||
|
: "cmdCopyBufferToImage3DDecompressDXTn"), owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed) {
|
id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed,
|
||||||
return newMTLComputePipelineState(getFunctionNamed(indexed ? "cmdDrawIndexedIndirectConvertBuffers" :
|
MVKVulkanAPIDeviceObject* owner) {
|
||||||
"cmdDrawIndirectConvertBuffers"));
|
return newMTLComputePipelineState(getFunctionNamed(indexed
|
||||||
|
? "cmdDrawIndexedIndirectConvertBuffers"
|
||||||
|
: "cmdDrawIndirectConvertBuffers"), owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdDrawIndexedCopyIndexBufferMTLComputePipelineState(MTLIndexType type) {
|
id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdDrawIndexedCopyIndexBufferMTLComputePipelineState(MTLIndexType type,
|
||||||
return newMTLComputePipelineState(getFunctionNamed(type == MTLIndexTypeUInt16 ? "cmdDrawIndexedCopyIndex16Buffer" :
|
MVKVulkanAPIDeviceObject* owner) {
|
||||||
"cmdDrawIndexedCopyIndex32Buffer"));
|
return newMTLComputePipelineState(getFunctionNamed(type == MTLIndexTypeUInt16
|
||||||
|
? "cmdDrawIndexedCopyIndex16Buffer"
|
||||||
|
: "cmdDrawIndexedCopyIndex32Buffer"), owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -414,7 +422,7 @@ id<MTLFunction> MVKCommandResourceFactory::newMTLFunction(NSString* mslSrcCode,
|
|||||||
error: &err] autorelease];
|
error: &err] autorelease];
|
||||||
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.mslCompile, startTime);
|
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.mslCompile, startTime);
|
||||||
if (err) {
|
if (err) {
|
||||||
mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED,
|
reportError(VK_ERROR_INITIALIZATION_FAILED,
|
||||||
"Could not compile support shader from MSL source (Error code %li):\n%s\n%s",
|
"Could not compile support shader from MSL source (Error code %li):\n%s\n%s",
|
||||||
(long)err.code, mslSrcCode.UTF8String, err.localizedDescription.UTF8String);
|
(long)err.code, mslSrcCode.UTF8String, err.localizedDescription.UTF8String);
|
||||||
return nil;
|
return nil;
|
||||||
@ -427,15 +435,17 @@ id<MTLFunction> MVKCommandResourceFactory::newMTLFunction(NSString* mslSrcCode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLRenderPipelineState> MVKCommandResourceFactory::newMTLRenderPipelineState(MTLRenderPipelineDescriptor* plDesc) {
|
id<MTLRenderPipelineState> MVKCommandResourceFactory::newMTLRenderPipelineState(MTLRenderPipelineDescriptor* plDesc,
|
||||||
MVKRenderPipelineCompiler* plc = new MVKRenderPipelineCompiler(_device);
|
MVKVulkanAPIDeviceObject* owner) {
|
||||||
|
MVKRenderPipelineCompiler* plc = new MVKRenderPipelineCompiler(owner);
|
||||||
id<MTLRenderPipelineState> rps = plc->newMTLRenderPipelineState(plDesc); // retained
|
id<MTLRenderPipelineState> rps = plc->newMTLRenderPipelineState(plDesc); // retained
|
||||||
plc->destroy();
|
plc->destroy();
|
||||||
return rps;
|
return rps;
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLComputePipelineState> MVKCommandResourceFactory::newMTLComputePipelineState(id<MTLFunction> mtlFunction) {
|
id<MTLComputePipelineState> MVKCommandResourceFactory::newMTLComputePipelineState(id<MTLFunction> mtlFunction,
|
||||||
MVKComputePipelineCompiler* plc = new MVKComputePipelineCompiler(_device);
|
MVKVulkanAPIDeviceObject* owner) {
|
||||||
|
MVKComputePipelineCompiler* plc = new MVKComputePipelineCompiler(owner);
|
||||||
id<MTLComputePipelineState> cps = plc->newMTLComputePipelineState(mtlFunction); // retained
|
id<MTLComputePipelineState> cps = plc->newMTLComputePipelineState(mtlFunction); // retained
|
||||||
plc->destroy();
|
plc->destroy();
|
||||||
return cps;
|
return cps;
|
||||||
|
@ -38,6 +38,9 @@ public:
|
|||||||
NSUInteger _offset;
|
NSUInteger _offset;
|
||||||
NSUInteger _length;
|
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
|
* Returns a pointer to the begining of this allocation memory, taking into
|
||||||
* consideration this allocation's offset into the underlying MTLBuffer.
|
* consideration this allocation's offset into the underlying MTLBuffer.
|
||||||
@ -83,6 +86,9 @@ class MVKMTLBufferAllocationPool : public MVKObjectPool<MVKMTLBufferAllocation>
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** Returns the Vulkan API opaque object controlling this object. */
|
||||||
|
MVKVulkanAPIObject* getVulkanAPIObject() override { return _device->getVulkanAPIObject(); };
|
||||||
|
|
||||||
/** Returns a new MVKMTLBufferAllocation instance. */
|
/** Returns a new MVKMTLBufferAllocation instance. */
|
||||||
MVKMTLBufferAllocation* newObject() override;
|
MVKMTLBufferAllocation* newObject() override;
|
||||||
|
|
||||||
@ -119,6 +125,9 @@ class MVKMTLBufferAllocator : public MVKBaseDeviceObject {
|
|||||||
|
|
||||||
public:
|
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
|
* 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.
|
* power-of-two value that is at least as big as the requested size.
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKMTLBufferAllocation
|
#pragma mark MVKMTLBufferAllocation
|
||||||
|
|
||||||
|
MVKVulkanAPIObject* MVKMTLBufferAllocation::getVulkanAPIObject() { return _pool->getVulkanAPIObject(); };
|
||||||
|
|
||||||
void MVKMTLBufferAllocation::returnToPool() { _pool->returnObjectSafely(this); }
|
void MVKMTLBufferAllocation::returnToPool() { _pool->returnObjectSafely(this); }
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +31,9 @@ class MVKBuffer : public MVKResource {
|
|||||||
|
|
||||||
public:
|
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
|
#pragma mark Resource memory
|
||||||
|
|
||||||
/** Returns the memory requirements of this resource by populating the specified structure. */
|
/** Returns the memory requirements of this resource by populating the specified structure. */
|
||||||
@ -89,10 +92,13 @@ protected:
|
|||||||
#pragma mark MVKBufferView
|
#pragma mark MVKBufferView
|
||||||
|
|
||||||
/** Represents a Vulkan buffer view. */
|
/** Represents a Vulkan buffer view. */
|
||||||
class MVKBufferView : public MVKRefCountedDeviceObject {
|
class MVKBufferView : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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
|
#pragma mark Metal
|
||||||
|
|
||||||
/** Returns a Metal texture that overlays this buffer view. */
|
/** Returns a Metal texture that overlays this buffer view. */
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
#include "MVKBuffer.h"
|
#include "MVKBuffer.h"
|
||||||
#include "MVKCommandBuffer.h"
|
#include "MVKCommandBuffer.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "MVKEnvironment.h"
|
||||||
|
#include "mvk_datatypes.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -158,7 +159,7 @@ id<MTLTexture> MVKBufferView::getMTLTexture() {
|
|||||||
|
|
||||||
#pragma mark Construction
|
#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;
|
_buffer = (MVKBuffer*)pCreateInfo->buffer;
|
||||||
_mtlBufferOffset = _buffer->getMTLBufferOffset() + pCreateInfo->offset;
|
_mtlBufferOffset = _buffer->getMTLBufferOffset() + pCreateInfo->offset;
|
||||||
_mtlPixelFormat = getMTLPixelFormatFromVkFormat(pCreateInfo->format);
|
_mtlPixelFormat = getMTLPixelFormatFromVkFormat(pCreateInfo->format);
|
||||||
@ -184,7 +185,7 @@ MVKBufferView::MVKBufferView(MVKDevice* device, const VkBufferViewCreateInfo* pC
|
|||||||
_textureSize.height = uint32_t(rowCount * fmtBlockSize.height);
|
_textureSize.height = uint32_t(rowCount * fmtBlockSize.height);
|
||||||
|
|
||||||
if ( !_device->_pMetalFeatures->texelBuffers ) {
|
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."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include "MVKDevice.h"
|
#include "MVKDevice.h"
|
||||||
#include "MVKImage.h"
|
#include "MVKImage.h"
|
||||||
#include "MVKVector.h"
|
#include "MVKVector.h"
|
||||||
#include "mvk_datatypes.h"
|
|
||||||
#include <MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.h>
|
#include <MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.h>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -76,6 +75,9 @@ class MVKDescriptorSetLayoutBinding : public MVKBaseDeviceObject {
|
|||||||
|
|
||||||
public:
|
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. */
|
/** Encodes this binding layout and the specified descriptor set binding on the specified command encoder. */
|
||||||
void bind(MVKCommandEncoder* cmdEncoder,
|
void bind(MVKCommandEncoder* cmdEncoder,
|
||||||
MVKDescriptorBinding& descBinding,
|
MVKDescriptorBinding& descBinding,
|
||||||
@ -116,6 +118,7 @@ protected:
|
|||||||
MVKShaderStageResourceBinding* pDescSetCounts,
|
MVKShaderStageResourceBinding* pDescSetCounts,
|
||||||
const VkDescriptorSetLayoutBinding* pBinding);
|
const VkDescriptorSetLayoutBinding* pBinding);
|
||||||
|
|
||||||
|
MVKDescriptorSetLayout* _layout;
|
||||||
VkDescriptorSetLayoutBinding _info;
|
VkDescriptorSetLayoutBinding _info;
|
||||||
std::vector<MVKSampler*> _immutableSamplers;
|
std::vector<MVKSampler*> _immutableSamplers;
|
||||||
MVKShaderResourceBinding _mtlResourceIndexOffsets;
|
MVKShaderResourceBinding _mtlResourceIndexOffsets;
|
||||||
@ -127,10 +130,13 @@ protected:
|
|||||||
#pragma mark MVKDescriptorSetLayout
|
#pragma mark MVKDescriptorSetLayout
|
||||||
|
|
||||||
/** Represents a Vulkan descriptor set layout. */
|
/** Represents a Vulkan descriptor set layout. */
|
||||||
class MVKDescriptorSetLayout : public MVKBaseDeviceObject {
|
class MVKDescriptorSetLayout : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Encodes this descriptor set layout and the specified descriptor set on the specified command encoder. */
|
||||||
void bindDescriptorSet(MVKCommandEncoder* cmdEncoder,
|
void bindDescriptorSet(MVKCommandEncoder* cmdEncoder,
|
||||||
MVKDescriptorSet* descSet,
|
MVKDescriptorSet* descSet,
|
||||||
@ -184,6 +190,9 @@ class MVKDescriptorBinding : public MVKBaseObject {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** Returns the Vulkan API opaque object controlling this object. */
|
||||||
|
MVKVulkanAPIObject* getVulkanAPIObject() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the internal element bindings from the specified content.
|
* Updates the internal element bindings from the specified content.
|
||||||
*
|
*
|
||||||
@ -242,7 +251,7 @@ public:
|
|||||||
bool hasBinding(uint32_t binding);
|
bool hasBinding(uint32_t binding);
|
||||||
|
|
||||||
/** Constructs an instance. */
|
/** Constructs an instance. */
|
||||||
MVKDescriptorBinding(MVKDescriptorSetLayoutBinding* pBindingLayout);
|
MVKDescriptorBinding(MVKDescriptorSet* pDescSet, MVKDescriptorSetLayoutBinding* pBindingLayout);
|
||||||
|
|
||||||
/** Destructor. */
|
/** Destructor. */
|
||||||
~MVKDescriptorBinding();
|
~MVKDescriptorBinding();
|
||||||
@ -252,6 +261,7 @@ protected:
|
|||||||
|
|
||||||
void initMTLSamplers(MVKDescriptorSetLayoutBinding* pBindingLayout);
|
void initMTLSamplers(MVKDescriptorSetLayoutBinding* pBindingLayout);
|
||||||
|
|
||||||
|
MVKDescriptorSet* _pDescSet;
|
||||||
MVKDescriptorSetLayoutBinding* _pBindingLayout;
|
MVKDescriptorSetLayoutBinding* _pBindingLayout;
|
||||||
std::vector<VkDescriptorImageInfo> _imageBindings;
|
std::vector<VkDescriptorImageInfo> _imageBindings;
|
||||||
std::vector<VkDescriptorBufferInfo> _bufferBindings;
|
std::vector<VkDescriptorBufferInfo> _bufferBindings;
|
||||||
@ -268,10 +278,13 @@ protected:
|
|||||||
#pragma mark MVKDescriptorSet
|
#pragma mark MVKDescriptorSet
|
||||||
|
|
||||||
/** Represents a Vulkan descriptor set. */
|
/** Represents a Vulkan descriptor set. */
|
||||||
class MVKDescriptorSet : public MVKBaseDeviceObject {
|
class MVKDescriptorSet : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Updates the resource bindings in this instance from the specified content. */
|
||||||
template<typename DescriptorAction>
|
template<typename DescriptorAction>
|
||||||
void writeDescriptorSets(const DescriptorAction* pDescriptorAction,
|
void writeDescriptorSets(const DescriptorAction* pDescriptorAction,
|
||||||
@ -295,7 +308,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
MVKDescriptorSet* _next;
|
MVKDescriptorSet* _next;
|
||||||
|
|
||||||
MVKDescriptorSet(MVKDevice* device) : MVKBaseDeviceObject(device) {}
|
MVKDescriptorSet(MVKDevice* device) : MVKVulkanAPIDeviceObject(device) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class MVKDescriptorSetLayout;
|
friend class MVKDescriptorSetLayout;
|
||||||
@ -315,10 +328,13 @@ protected:
|
|||||||
typedef MVKDeviceObjectPool<MVKDescriptorSet> MVKDescriptorSetPool;
|
typedef MVKDeviceObjectPool<MVKDescriptorSet> MVKDescriptorSetPool;
|
||||||
|
|
||||||
/** Represents a Vulkan descriptor pool. */
|
/** Represents a Vulkan descriptor pool. */
|
||||||
class MVKDescriptorPool : public MVKBaseDeviceObject {
|
class MVKDescriptorPool : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Allocates the specified number of descriptor sets. */
|
||||||
VkResult allocateDescriptorSets(uint32_t count,
|
VkResult allocateDescriptorSets(uint32_t count,
|
||||||
const VkDescriptorSetLayout* pSetLayouts,
|
const VkDescriptorSetLayout* pSetLayouts,
|
||||||
@ -349,10 +365,13 @@ protected:
|
|||||||
#pragma mark MVKDescriptorUpdateTemplate
|
#pragma mark MVKDescriptorUpdateTemplate
|
||||||
|
|
||||||
/** Represents a Vulkan descriptor update template. */
|
/** Represents a Vulkan descriptor update template. */
|
||||||
class MVKDescriptorUpdateTemplate : public MVKConfigurableObject {
|
class MVKDescriptorUpdateTemplate : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Get the nth update template entry. */
|
||||||
const VkDescriptorUpdateTemplateEntryKHR* getEntry(uint32_t n) const;
|
const VkDescriptorUpdateTemplateEntryKHR* getEntry(uint32_t n) const;
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "MVKBuffer.h"
|
#include "MVKBuffer.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "MVKLogging.h"
|
#include "MVKLogging.h"
|
||||||
|
#include "mvk_datatypes.hpp"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -28,7 +29,7 @@ using namespace std;
|
|||||||
|
|
||||||
#pragma mark MVKShaderStageResourceBinding
|
#pragma mark MVKShaderStageResourceBinding
|
||||||
|
|
||||||
MVK_PUBLIC_SYMBOL MVKShaderStageResourceBinding MVKShaderStageResourceBinding::operator+ (const MVKShaderStageResourceBinding& rhs) {
|
MVKShaderStageResourceBinding MVKShaderStageResourceBinding::operator+ (const MVKShaderStageResourceBinding& rhs) {
|
||||||
MVKShaderStageResourceBinding rslt;
|
MVKShaderStageResourceBinding rslt;
|
||||||
rslt.bufferIndex = this->bufferIndex + rhs.bufferIndex;
|
rslt.bufferIndex = this->bufferIndex + rhs.bufferIndex;
|
||||||
rslt.textureIndex = this->textureIndex + rhs.textureIndex;
|
rslt.textureIndex = this->textureIndex + rhs.textureIndex;
|
||||||
@ -36,7 +37,7 @@ MVK_PUBLIC_SYMBOL MVKShaderStageResourceBinding MVKShaderStageResourceBinding::o
|
|||||||
return rslt;
|
return rslt;
|
||||||
}
|
}
|
||||||
|
|
||||||
MVK_PUBLIC_SYMBOL MVKShaderStageResourceBinding& MVKShaderStageResourceBinding::operator+= (const MVKShaderStageResourceBinding& rhs) {
|
MVKShaderStageResourceBinding& MVKShaderStageResourceBinding::operator+= (const MVKShaderStageResourceBinding& rhs) {
|
||||||
this->bufferIndex += rhs.bufferIndex;
|
this->bufferIndex += rhs.bufferIndex;
|
||||||
this->textureIndex += rhs.textureIndex;
|
this->textureIndex += rhs.textureIndex;
|
||||||
this->samplerIndex += rhs.samplerIndex;
|
this->samplerIndex += rhs.samplerIndex;
|
||||||
@ -46,19 +47,19 @@ MVK_PUBLIC_SYMBOL MVKShaderStageResourceBinding& MVKShaderStageResourceBinding::
|
|||||||
|
|
||||||
#pragma mark MVKShaderResourceBinding
|
#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});
|
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});
|
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});
|
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;
|
MVKShaderResourceBinding rslt;
|
||||||
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
||||||
rslt.stages[i] = this->stages[i] + rhs.stages[i];
|
rslt.stages[i] = this->stages[i] + rhs.stages[i];
|
||||||
@ -66,7 +67,7 @@ MVK_PUBLIC_SYMBOL MVKShaderResourceBinding MVKShaderResourceBinding::operator+ (
|
|||||||
return rslt;
|
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++) {
|
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
||||||
this->stages[i] += rhs.stages[i];
|
this->stages[i] += rhs.stages[i];
|
||||||
}
|
}
|
||||||
@ -77,6 +78,8 @@ MVK_PUBLIC_SYMBOL MVKShaderResourceBinding& MVKShaderResourceBinding::operator+=
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKDescriptorSetLayoutBinding
|
#pragma mark MVKDescriptorSetLayoutBinding
|
||||||
|
|
||||||
|
MVKVulkanAPIObject* MVKDescriptorSetLayoutBinding::getVulkanAPIObject() { return _layout; };
|
||||||
|
|
||||||
void MVKDescriptorSetLayoutBinding::bind(MVKCommandEncoder* cmdEncoder,
|
void MVKDescriptorSetLayoutBinding::bind(MVKCommandEncoder* cmdEncoder,
|
||||||
MVKDescriptorBinding& descBinding,
|
MVKDescriptorBinding& descBinding,
|
||||||
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
|
MVKShaderResourceBinding& dslMTLRezIdxOffsets,
|
||||||
@ -376,7 +379,8 @@ void MVKDescriptorSetLayoutBinding::populateShaderConverterContext(SPIRVToMSLCon
|
|||||||
|
|
||||||
MVKDescriptorSetLayoutBinding::MVKDescriptorSetLayoutBinding(MVKDevice* device,
|
MVKDescriptorSetLayoutBinding::MVKDescriptorSetLayoutBinding(MVKDevice* device,
|
||||||
MVKDescriptorSetLayout* layout,
|
MVKDescriptorSetLayout* layout,
|
||||||
const VkDescriptorSetLayoutBinding* pBinding) : MVKBaseDeviceObject(device) {
|
const VkDescriptorSetLayoutBinding* pBinding) : MVKBaseDeviceObject(device), _layout(layout) {
|
||||||
|
|
||||||
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
||||||
// Determine if this binding is used by this shader stage
|
// Determine if this binding is used by this shader stage
|
||||||
_applyToStage[i] = mvkAreFlagsEnabled(pBinding->stageFlags, mvkVkShaderStageFlagBitsFromMVKShaderStage(MVKShaderStage(i)));
|
_applyToStage[i] = mvkAreFlagsEnabled(pBinding->stageFlags, mvkVkShaderStageFlagBitsFromMVKShaderStage(MVKShaderStage(i)));
|
||||||
@ -403,8 +407,10 @@ MVKDescriptorSetLayoutBinding::MVKDescriptorSetLayoutBinding(MVKDevice* device,
|
|||||||
}
|
}
|
||||||
|
|
||||||
MVKDescriptorSetLayoutBinding::MVKDescriptorSetLayoutBinding(const MVKDescriptorSetLayoutBinding& binding) :
|
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) {
|
_mtlResourceIndexOffsets(binding._mtlResourceIndexOffsets) {
|
||||||
|
|
||||||
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
|
||||||
_applyToStage[i] = binding._applyToStage[i];
|
_applyToStage[i] = binding._applyToStage[i];
|
||||||
}
|
}
|
||||||
@ -430,7 +436,7 @@ void MVKDescriptorSetLayoutBinding::initMetalResourceIndexOffsets(MVKShaderStage
|
|||||||
pDescSetCounts->samplerIndex += pBinding->descriptorCount;
|
pDescSetCounts->samplerIndex += pBinding->descriptorCount;
|
||||||
|
|
||||||
if (pBinding->descriptorCount > 1 && !_device->_pMetalFeatures->arrayOfSamplers) {
|
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;
|
break;
|
||||||
|
|
||||||
@ -442,10 +448,10 @@ void MVKDescriptorSetLayoutBinding::initMetalResourceIndexOffsets(MVKShaderStage
|
|||||||
|
|
||||||
if (pBinding->descriptorCount > 1) {
|
if (pBinding->descriptorCount > 1) {
|
||||||
if ( !_device->_pMetalFeatures->arrayOfTextures ) {
|
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 ) {
|
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;
|
break;
|
||||||
@ -459,7 +465,7 @@ void MVKDescriptorSetLayoutBinding::initMetalResourceIndexOffsets(MVKShaderStage
|
|||||||
pDescSetCounts->textureIndex += pBinding->descriptorCount;
|
pDescSetCounts->textureIndex += pBinding->descriptorCount;
|
||||||
|
|
||||||
if (pBinding->descriptorCount > 1 && !_device->_pMetalFeatures->arrayOfTextures) {
|
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;
|
break;
|
||||||
|
|
||||||
@ -601,14 +607,13 @@ void MVKDescriptorSetLayout::populateShaderConverterContext(SPIRVToMSLConverterC
|
|||||||
}
|
}
|
||||||
|
|
||||||
MVKDescriptorSetLayout::MVKDescriptorSetLayout(MVKDevice* device,
|
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;
|
_isPushDescriptorLayout = (pCreateInfo->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR) != 0;
|
||||||
// Create the descriptor bindings
|
// Create the descriptor bindings
|
||||||
_bindings.reserve(pCreateInfo->bindingCount);
|
_bindings.reserve(pCreateInfo->bindingCount);
|
||||||
for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
|
for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
|
||||||
_bindings.emplace_back(_device, this, &pCreateInfo->pBindings[i]);
|
_bindings.emplace_back(_device, this, &pCreateInfo->pBindings[i]);
|
||||||
_bindingToIndex[pCreateInfo->pBindings[i].binding] = i;
|
_bindingToIndex[pCreateInfo->pBindings[i].binding] = i;
|
||||||
setConfigurationResult(_bindings.back().getConfigurationResult());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -616,6 +621,8 @@ MVKDescriptorSetLayout::MVKDescriptorSetLayout(MVKDevice* device,
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKDescriptorBinding
|
#pragma mark MVKDescriptorBinding
|
||||||
|
|
||||||
|
MVKVulkanAPIObject* MVKDescriptorBinding::getVulkanAPIObject() { return _pDescSet->getVulkanAPIObject(); };
|
||||||
|
|
||||||
uint32_t MVKDescriptorBinding::writeBindings(uint32_t srcStartIndex,
|
uint32_t MVKDescriptorBinding::writeBindings(uint32_t srcStartIndex,
|
||||||
uint32_t dstStartIndex,
|
uint32_t dstStartIndex,
|
||||||
uint32_t count,
|
uint32_t count,
|
||||||
@ -785,7 +792,7 @@ bool MVKDescriptorBinding::hasBinding(uint32_t binding) {
|
|||||||
return _pBindingLayout->_info.binding == binding;
|
return _pBindingLayout->_info.binding == binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKDescriptorBinding::MVKDescriptorBinding(MVKDescriptorSetLayoutBinding* pBindingLayout) : MVKBaseObject() {
|
MVKDescriptorBinding::MVKDescriptorBinding(MVKDescriptorSet* pDescSet, MVKDescriptorSetLayoutBinding* pBindingLayout) : _pDescSet(pDescSet) {
|
||||||
|
|
||||||
uint32_t descCnt = pBindingLayout->_info.descriptorCount;
|
uint32_t descCnt = pBindingLayout->_info.descriptorCount;
|
||||||
|
|
||||||
@ -941,7 +948,7 @@ void MVKDescriptorSet::setLayout(MVKDescriptorSetLayout* layout) {
|
|||||||
_bindings.clear();
|
_bindings.clear();
|
||||||
_bindings.reserve(bindCnt);
|
_bindings.reserve(bindCnt);
|
||||||
for (uint32_t i = 0; i < bindCnt; i++) {
|
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 @@ VkResult MVKDescriptorPool::allocateDescriptorSets(uint32_t count,
|
|||||||
if (_device->_enabledExtensions.vk_KHR_maintenance1.enabled) {
|
if (_device->_enabledExtensions.vk_KHR_maintenance1.enabled) {
|
||||||
return VK_ERROR_OUT_OF_POOL_MEMORY; // Failure is an acceptable test...don't log as error.
|
return VK_ERROR_OUT_OF_POOL_MEMORY; // Failure is an acceptable test...don't log as error.
|
||||||
} else {
|
} 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 @@ MVKDescriptorSetPool* MVKDescriptorPool::getDescriptorSetPool(MVKDescriptorSetLa
|
|||||||
}
|
}
|
||||||
|
|
||||||
MVKDescriptorPool::MVKDescriptorPool(MVKDevice* device,
|
MVKDescriptorPool::MVKDescriptorPool(MVKDevice* device,
|
||||||
const VkDescriptorPoolCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
|
const VkDescriptorPoolCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
|
||||||
_maxSets = pCreateInfo->maxSets;
|
_maxSets = pCreateInfo->maxSets;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1030,8 +1037,9 @@ VkDescriptorUpdateTemplateTypeKHR MVKDescriptorUpdateTemplate::getType() const {
|
|||||||
return _type;
|
return _type;
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKDescriptorUpdateTemplate::MVKDescriptorUpdateTemplate(MVKDevice* device, const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo) :
|
MVKDescriptorUpdateTemplate::MVKDescriptorUpdateTemplate(MVKDevice* device,
|
||||||
MVKConfigurableObject(), _type(pCreateInfo->templateType) {
|
const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo) :
|
||||||
|
MVKVulkanAPIDeviceObject(device), _type(pCreateInfo->templateType) {
|
||||||
|
|
||||||
for (uint32_t i = 0; i < pCreateInfo->descriptorUpdateEntryCount; i++)
|
for (uint32_t i = 0; i < pCreateInfo->descriptorUpdateEntryCount; i++)
|
||||||
_entries.push_back(pCreateInfo->pDescriptorUpdateEntries[i]);
|
_entries.push_back(pCreateInfo->pDescriptorUpdateEntries[i]);
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "MVKBaseObject.h"
|
#include "MVKBaseObject.h"
|
||||||
#include "MVKLayers.h"
|
#include "MVKLayers.h"
|
||||||
#include "MVKObjectPool.h"
|
#include "MVKObjectPool.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "mvk_datatypes.hpp"
|
||||||
#include "vk_mvk_moltenvk.h"
|
#include "vk_mvk_moltenvk.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -75,10 +75,16 @@ const static uint32_t kMVKCachedScissorCount = 16;
|
|||||||
#pragma mark MVKPhysicalDevice
|
#pragma mark MVKPhysicalDevice
|
||||||
|
|
||||||
/** Represents a Vulkan physical GPU device. */
|
/** Represents a Vulkan physical GPU device. */
|
||||||
class MVKPhysicalDevice : public MVKDispatchableObject {
|
class MVKPhysicalDevice : public MVKDispatchableVulkanAPIObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Populates the specified structure with the features of this device. */
|
||||||
void getFeatures(VkPhysicalDeviceFeatures* features);
|
void getFeatures(VkPhysicalDeviceFeatures* features);
|
||||||
|
|
||||||
@ -224,12 +230,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
VkResult getQueueFamilyProperties(uint32_t* pCount, VkQueueFamilyProperties2KHR* pQueueFamilyProperties);
|
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
|
#pragma mark Memory models
|
||||||
|
|
||||||
@ -339,12 +339,15 @@ protected:
|
|||||||
#pragma mark MVKDevice
|
#pragma mark MVKDevice
|
||||||
|
|
||||||
/** Represents a Vulkan logical GPU device, associated with a physical device. */
|
/** Represents a Vulkan logical GPU device, associated with a physical device. */
|
||||||
class MVKDevice : public MVKDispatchableObject {
|
class MVKDevice : public MVKDispatchableVulkanAPIObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** 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. */
|
/** Returns the physical device underlying this logical device. */
|
||||||
inline MVKPhysicalDevice* getPhysicalDevice() { return _physicalDevice; }
|
inline MVKPhysicalDevice* getPhysicalDevice() { return _physicalDevice; }
|
||||||
@ -658,13 +661,17 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#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.
|
* 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:
|
public:
|
||||||
|
|
||||||
@ -683,90 +690,53 @@ public:
|
|||||||
* are managed for each platform device.
|
* are managed for each platform device.
|
||||||
*/
|
*/
|
||||||
inline MTLPixelFormat getMTLPixelFormatFromVkFormat(VkFormat vkFormat) {
|
inline MTLPixelFormat getMTLPixelFormatFromVkFormat(VkFormat vkFormat) {
|
||||||
return _device ? _device->getMTLPixelFormatFromVkFormat(vkFormat) : mvkMTLPixelFormatFromVkFormat(vkFormat);
|
return _device ? _device->getMTLPixelFormatFromVkFormat(vkFormat)
|
||||||
|
: mvkMTLPixelFormatFromVkFormatInObj(vkFormat, getBaseObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructs an instance for the specified device. */
|
/** Constructs an instance for the specified device. */
|
||||||
MVKBaseDeviceObject(MVKDevice* device) : _device(device) {}
|
MVKDeviceTrackingMixin(MVKDevice* device) : _device(device) {}
|
||||||
|
|
||||||
|
virtual ~MVKDeviceTrackingMixin() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual MVKBaseObject* getBaseObject() = 0;
|
||||||
MVKDevice* _device;
|
MVKDevice* _device;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKDispatchableDeviceObject
|
#pragma mark MVKBaseDeviceObject
|
||||||
|
|
||||||
/**
|
/** Represents an object that is spawned from a Vulkan device, and tracks that device. */
|
||||||
* Represents a dispatchable object that is spawned from a Vulkan device, and tracks that device.
|
class MVKBaseDeviceObject : public MVKBaseObject, public MVKDeviceTrackingMixin {
|
||||||
* Implementation supports an instance where the device is null.
|
|
||||||
*/
|
|
||||||
class MVKDispatchableDeviceObject : public MVKDispatchableObject {
|
|
||||||
|
|
||||||
public:
|
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. */
|
/** Constructs an instance for the specified device. */
|
||||||
MVKDispatchableDeviceObject(MVKDevice* device) : _device(device) {}
|
MVKBaseDeviceObject(MVKDevice* device) : MVKDeviceTrackingMixin(device) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MVKDevice* _device;
|
MVKBaseObject* getBaseObject() override { return this; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKRefCountedDeviceObject
|
#pragma mark MVKVulkanAPIDeviceObject
|
||||||
|
|
||||||
/**
|
/** Abstract class that represents an opaque Vulkan API handle object spawned from a Vulkan device. */
|
||||||
* Represents a device-spawned object that supports basic reference counting.
|
class MVKVulkanAPIDeviceObject : public MVKVulkanAPIObject, public MVKDeviceTrackingMixin {
|
||||||
*
|
|
||||||
* 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 {
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/** Returns a pointer to the Vulkan instance. */
|
||||||
* Called when this instance has been retained as a reference by another object,
|
MVKInstance* getInstance() override { return _device ? _device->getInstance() : nullptr; }
|
||||||
* indicating that this instance will not be deleted until that reference is released.
|
|
||||||
*/
|
|
||||||
void retain();
|
|
||||||
|
|
||||||
/**
|
/** Constructs an instance for the specified device. */
|
||||||
* Called when this instance has been released as a reference from another object.
|
MVKVulkanAPIDeviceObject(MVKDevice* device) : MVKDeviceTrackingMixin(device) {}
|
||||||
* 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();
|
|
||||||
|
|
||||||
/**
|
protected:
|
||||||
* Marks this instance as destroyed. If all previous references to this instance
|
MVKBaseObject* getBaseObject() override { return this; };
|
||||||
* 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -779,6 +749,10 @@ class MVKDeviceObjectPool : public MVKObjectPool<T> {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns the Vulkan API opaque object controlling this object. */
|
||||||
|
MVKVulkanAPIObject* getVulkanAPIObject() override { return _device; };
|
||||||
|
|
||||||
/** Returns a new instance. */
|
/** Returns a new instance. */
|
||||||
T* newObject() override { return new T(_device); }
|
T* newObject() override { return new T(_device); }
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "MVKCodec.h"
|
#include "MVKCodec.h"
|
||||||
#include "MVKEnvironment.h"
|
#include "MVKEnvironment.h"
|
||||||
|
#include "MVKLogging.h"
|
||||||
#include "MVKOSExtensions.h"
|
#include "MVKOSExtensions.h"
|
||||||
#include <MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.h>
|
#include <MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.h>
|
||||||
#include "vk_mvk_moltenvk.h"
|
#include "vk_mvk_moltenvk.h"
|
||||||
@ -2028,7 +2029,7 @@ uint32_t MVKDevice::expandVisibilityResultMTLBuffer(uint32_t queryCount) {
|
|||||||
_globalVisibilityQueryCount = uint32_t(newBuffLen / kMVKQuerySlotSizeInBytes);
|
_globalVisibilityQueryCount = uint32_t(newBuffLen / kMVKQuerySlotSizeInBytes);
|
||||||
|
|
||||||
if (reqBuffLen > maxBuffLen) {
|
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);
|
NSUInteger mtlBuffLen = mvkAlignByteOffset(newBuffLen, _pMetalFeatures->mtlBufferAlignment);
|
||||||
@ -2050,7 +2051,8 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo
|
|||||||
_enabledVarPtrFeatures(),
|
_enabledVarPtrFeatures(),
|
||||||
_enabledHostQryResetFeatures(),
|
_enabledHostQryResetFeatures(),
|
||||||
_enabledVtxAttrDivFeatures(),
|
_enabledVtxAttrDivFeatures(),
|
||||||
_enabledPortabilityFeatures()
|
_enabledPortabilityFeatures(),
|
||||||
|
_enabledExtensions(this)
|
||||||
{
|
{
|
||||||
|
|
||||||
initPerformanceTracking();
|
initPerformanceTracking();
|
||||||
@ -2065,9 +2067,10 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo
|
|||||||
|
|
||||||
initQueues(pCreateInfo);
|
initQueues(pCreateInfo);
|
||||||
|
|
||||||
string logMsg = "Created VkDevice to run on GPU %s with the following Vulkan extensions enabled:";
|
MVKLogInfo("Created VkDevice to run on GPU %s with the following %d Vulkan extensions enabled:%s",
|
||||||
logMsg += _enabledExtensions.enabledNamesString("\n\t\t", true);
|
_pProperties->deviceName,
|
||||||
MVKLogInfo(logMsg.c_str(), _pProperties->deviceName);
|
_enabledExtensions.getEnabledCount(),
|
||||||
|
_enabledExtensions.enabledNamesString("\n\t\t", true).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKDevice::initPerformanceTracking() {
|
void MVKDevice::initPerformanceTracking() {
|
||||||
@ -2238,7 +2241,7 @@ void MVKDevice::enableFeatures(const VkBool32* pEnable, const VkBool32* pRequest
|
|||||||
for (uint32_t i = 0; i < count; i++) {
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
((VkBool32*)pEnable)[i] = pRequested[i] && pAvailable[i];
|
((VkBool32*)pEnable)[i] = pRequested[i] && pAvailable[i];
|
||||||
if (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."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2279,40 +2282,6 @@ MVKDevice::~MVKDevice() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#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 -
|
||||||
#pragma mark Support functions
|
#pragma mark Support functions
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "MVKDevice.h"
|
#include "MVKDevice.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
@ -30,10 +31,13 @@ class MVKImage;
|
|||||||
#pragma mark MVKDeviceMemory
|
#pragma mark MVKDeviceMemory
|
||||||
|
|
||||||
/** Represents a Vulkan device-space memory allocation. */
|
/** Represents a Vulkan device-space memory allocation. */
|
||||||
class MVKDeviceMemory : public MVKBaseDeviceObject {
|
class MVKDeviceMemory : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Returns whether the memory is accessible from the host. */
|
||||||
inline bool isMemoryHostAccessible() {
|
inline bool isMemoryHostAccessible() {
|
||||||
#if MVK_IOS
|
#if MVK_IOS
|
||||||
|
@ -19,8 +19,10 @@
|
|||||||
#include "MVKDeviceMemory.h"
|
#include "MVKDeviceMemory.h"
|
||||||
#include "MVKBuffer.h"
|
#include "MVKBuffer.h"
|
||||||
#include "MVKImage.h"
|
#include "MVKImage.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "MVKEnvironment.h"
|
||||||
|
#include "mvk_datatypes.hpp"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
|
#include "MVKLogging.h"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@ -31,15 +33,15 @@ using namespace std;
|
|||||||
VkResult MVKDeviceMemory::map(VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) {
|
VkResult MVKDeviceMemory::map(VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) {
|
||||||
|
|
||||||
if ( !isMemoryHostAccessible() ) {
|
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) {
|
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() ) {
|
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;
|
_mapOffset = offset;
|
||||||
@ -57,7 +59,7 @@ VkResult MVKDeviceMemory::map(VkDeviceSize offset, VkDeviceSize size, VkMemoryMa
|
|||||||
void MVKDeviceMemory::unmap() {
|
void MVKDeviceMemory::unmap() {
|
||||||
|
|
||||||
if ( !_isMapped ) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,11 +110,11 @@ VkResult MVKDeviceMemory::addBuffer(MVKBuffer* mvkBuff) {
|
|||||||
// If a dedicated alloc, ensure this buffer is the one and only buffer
|
// If a dedicated alloc, ensure this buffer is the one and only buffer
|
||||||
// I am dedicated to.
|
// I am dedicated to.
|
||||||
if (_isDedicated && (_buffers.empty() || _buffers[0] != mvkBuff) ) {
|
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() ) {
|
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.
|
// In the dedicated case, we already saved the buffer we're going to use.
|
||||||
@ -133,7 +135,7 @@ VkResult MVKDeviceMemory::addImage(MVKImage* mvkImg) {
|
|||||||
// If a dedicated alloc, ensure this image is the one and only image
|
// If a dedicated alloc, ensure this image is the one and only image
|
||||||
// I am dedicated to.
|
// I am dedicated to.
|
||||||
if (_isDedicated && (_images.empty() || _images[0] != mvkImg) ) {
|
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)
|
if (!_isDedicated)
|
||||||
@ -201,7 +203,7 @@ MVKResource* MVKDeviceMemory::getDedicatedResource() {
|
|||||||
|
|
||||||
MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
||||||
const VkMemoryAllocateInfo* pAllocateInfo,
|
const VkMemoryAllocateInfo* pAllocateInfo,
|
||||||
const VkAllocationCallbacks* pAllocator) : MVKBaseDeviceObject(device) {
|
const VkAllocationCallbacks* pAllocator) : MVKVulkanAPIDeviceObject(device) {
|
||||||
// Set Metal memory parameters
|
// Set Metal memory parameters
|
||||||
VkMemoryPropertyFlags vkMemProps = _device->_pMemoryProperties->memoryTypes[pAllocateInfo->memoryTypeIndex].propertyFlags;
|
VkMemoryPropertyFlags vkMemProps = _device->_pMemoryProperties->memoryTypes[pAllocateInfo->memoryTypeIndex].propertyFlags;
|
||||||
_mtlResourceOptions = mvkMTLResourceOptionsFromVkMemoryPropertyFlags(vkMemProps);
|
_mtlResourceOptions = mvkMTLResourceOptionsFromVkMemoryPropertyFlags(vkMemProps);
|
||||||
@ -233,13 +235,13 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
|||||||
#if MVK_MACOS
|
#if MVK_MACOS
|
||||||
if (isMemoryHostCoherent() ) {
|
if (isMemoryHostCoherent() ) {
|
||||||
if (!((MVKImage*)dedicatedImage)->_isLinear) {
|
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 {
|
} else {
|
||||||
// Need to use the managed mode for images.
|
// Need to use the managed mode for images.
|
||||||
_mtlStorageMode = MTLStorageModeManaged;
|
_mtlStorageMode = MTLStorageModeManaged;
|
||||||
// Nonetheless, we need a buffer to be able to map the memory at will.
|
// Nonetheless, we need a buffer to be able to map the memory at will.
|
||||||
if (!ensureMTLBuffer() ) {
|
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 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
|
|||||||
|
|
||||||
// If memory needs to be coherent it must reside in an MTLBuffer, since an open-ended map() must work.
|
// If memory needs to be coherent it must reside in an MTLBuffer, since an open-ended map() must work.
|
||||||
if (isMemoryHostCoherent() && !ensureMTLBuffer() ) {
|
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) {
|
if (dedicatedBuffer) {
|
||||||
|
@ -26,10 +26,13 @@
|
|||||||
#pragma mark MVKFramebuffer
|
#pragma mark MVKFramebuffer
|
||||||
|
|
||||||
/** Represents a Vulkan framebuffer. */
|
/** Represents a Vulkan framebuffer. */
|
||||||
class MVKFramebuffer : public MVKBaseDeviceObject {
|
class MVKFramebuffer : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Returns the dimensions of this framebuffer. */
|
||||||
inline VkExtent2D getExtent2D() { return _extent; }
|
inline VkExtent2D getExtent2D() { return _extent; }
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKFramebuffer::MVKFramebuffer(MVKDevice* device,
|
MVKFramebuffer::MVKFramebuffer(MVKDevice* device,
|
||||||
const VkFramebufferCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
|
const VkFramebufferCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
|
||||||
_extent = { .width = pCreateInfo->width, .height = pCreateInfo->height };
|
_extent = { .width = pCreateInfo->width, .height = pCreateInfo->height };
|
||||||
_layerCount = pCreateInfo->layers;
|
_layerCount = pCreateInfo->layers;
|
||||||
|
|
||||||
|
@ -48,6 +48,9 @@ class MVKImage : public MVKResource {
|
|||||||
|
|
||||||
public:
|
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. */
|
/** Returns the Vulkan image type of this image. */
|
||||||
VkImageType getImageType();
|
VkImageType getImageType();
|
||||||
|
|
||||||
@ -246,10 +249,12 @@ protected:
|
|||||||
#pragma mark MVKImageView
|
#pragma mark MVKImageView
|
||||||
|
|
||||||
/** Represents a Vulkan image view. */
|
/** Represents a Vulkan image view. */
|
||||||
class MVKImageView : public MVKRefCountedDeviceObject {
|
class MVKImageView : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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
|
#pragma mark Metal
|
||||||
|
|
||||||
@ -311,10 +316,13 @@ protected:
|
|||||||
#pragma mark MVKSampler
|
#pragma mark MVKSampler
|
||||||
|
|
||||||
/** Represents a Vulkan sampler. */
|
/** Represents a Vulkan sampler. */
|
||||||
class MVKSampler : public MVKRefCountedDeviceObject {
|
class MVKSampler : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Returns the Metal sampler state. */
|
||||||
inline id<MTLSamplerState> getMTLSamplerState() { return _mtlSamplerState; }
|
inline id<MTLSamplerState> getMTLSamplerState() { return _mtlSamplerState; }
|
||||||
|
|
||||||
|
@ -19,8 +19,9 @@
|
|||||||
#include "MVKImage.h"
|
#include "MVKImage.h"
|
||||||
#include "MVKSwapchain.h"
|
#include "MVKSwapchain.h"
|
||||||
#include "MVKCommandBuffer.h"
|
#include "MVKCommandBuffer.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "mvk_datatypes.hpp"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
|
#include "MVKLogging.h"
|
||||||
#include "MVKEnvironment.h"
|
#include "MVKEnvironment.h"
|
||||||
#include "MVKLogging.h"
|
#include "MVKLogging.h"
|
||||||
#include "MVKCodec.h"
|
#include "MVKCodec.h"
|
||||||
@ -329,7 +330,7 @@ IOSurfaceRef MVKImage::getIOSurface() { return _ioSurface; }
|
|||||||
|
|
||||||
VkResult MVKImage::useIOSurface(IOSurfaceRef ioSurface) {
|
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
|
#if MVK_SUPPORT_IOSURFACE_BOOL
|
||||||
|
|
||||||
@ -337,11 +338,11 @@ VkResult MVKImage::useIOSurface(IOSurfaceRef ioSurface) {
|
|||||||
resetIOSurface();
|
resetIOSurface();
|
||||||
|
|
||||||
if (ioSurface) {
|
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 (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 mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface height %zu does not match VkImage height %d.", IOSurfaceGetHeight(ioSurface), _extent.height); }
|
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 mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface bytes per element %zu does not match VkImage bytes per element %d.", IOSurfaceGetBytesPerElement(ioSurface), mvkMTLPixelFormatBytesPerBlock(_mtlPixelFormat)); }
|
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 mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface element width %zu does not match VkImage element width %d.", IOSurfaceGetElementWidth(ioSurface), mvkMTLPixelFormatBlockTexelSize(_mtlPixelFormat).width); }
|
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 mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "vkUseIOSurfaceMVK() : IOSurface element height %zu does not match VkImage element height %d.", IOSurfaceGetElementHeight(ioSurface), mvkMTLPixelFormatBlockTexelSize(_mtlPixelFormat).height); }
|
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;
|
_ioSurface = ioSurface;
|
||||||
CFRetain(_ioSurface);
|
CFRetain(_ioSurface);
|
||||||
@ -472,7 +473,7 @@ void MVKImage::updateMTLTextureContent(MVKImageSubresource& subresource,
|
|||||||
// can upload the decompressed image data.
|
// can upload the decompressed image data.
|
||||||
std::unique_ptr<MVKCodec> codec = mvkCreateCodec(getVkFormat());
|
std::unique_ptr<MVKCodec> codec = mvkCreateCodec(getVkFormat());
|
||||||
if (!codec) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
VkSubresourceLayout destLayout;
|
VkSubresourceLayout destLayout;
|
||||||
@ -544,20 +545,20 @@ void MVKImage::getMTLTextureContent(MVKImageSubresource& subresource,
|
|||||||
MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MVKResource(device) {
|
MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MVKResource(device) {
|
||||||
|
|
||||||
if (pCreateInfo->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT) {
|
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 MVK_IOS
|
||||||
if ( (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) && (mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatCompressed) ) {
|
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
|
#else
|
||||||
if ( (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) && (mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatCompressed) && !mvkCanDecodeFormat(pCreateInfo->format) ) {
|
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
|
#endif
|
||||||
if ( (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) && (mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatDepthStencil) ) {
|
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
|
// Adjust the info components to be compatible with Metal, then use the modified versions
|
||||||
@ -572,7 +573,7 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV
|
|||||||
|
|
||||||
_mipLevels = max(pCreateInfo->mipLevels, minDim);
|
_mipLevels = max(pCreateInfo->mipLevels, minDim);
|
||||||
if ( (_mipLevels > 1) && (pCreateInfo->imageType == VK_IMAGE_TYPE_1D) ) {
|
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;
|
_mipLevels = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,9 +587,9 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV
|
|||||||
if ( (_samples > 1) && (_mtlTextureType != MTLTextureType2DMultisample) &&
|
if ( (_samples > 1) && (_mtlTextureType != MTLTextureType2DMultisample) &&
|
||||||
(pCreateInfo->imageType != VK_IMAGE_TYPE_2D || !_device->_pMetalFeatures->multisampleArrayTextures) ) {
|
(pCreateInfo->imageType != VK_IMAGE_TYPE_2D || !_device->_pMetalFeatures->multisampleArrayTextures) ) {
|
||||||
if (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) {
|
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 {
|
} 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;
|
_samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
if (pCreateInfo->imageType == VK_IMAGE_TYPE_2D) {
|
if (pCreateInfo->imageType == VK_IMAGE_TYPE_2D) {
|
||||||
@ -596,7 +597,7 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( (_samples > 1) && (mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatCompressed) ) {
|
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;
|
_samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -622,33 +623,33 @@ bool MVKImage::validateLinear(const VkImageCreateInfo* pCreateInfo) {
|
|||||||
if (pCreateInfo->tiling != VK_IMAGE_TILING_LINEAR) { return false; }
|
if (pCreateInfo->tiling != VK_IMAGE_TILING_LINEAR) { return false; }
|
||||||
|
|
||||||
if (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isDepthStencilAttachment) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mipLevels > 1) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_arrayLayers > 1) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_samples > 1) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MVK_MACOS
|
#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)) ) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -774,7 +775,7 @@ id<MTLTexture> MVKImageView::newMTLTexture() {
|
|||||||
// is constructed to validate image view capabilities
|
// is constructed to validate image view capabilities
|
||||||
MVKImageView::MVKImageView(MVKDevice* device,
|
MVKImageView::MVKImageView(MVKDevice* device,
|
||||||
const VkImageViewCreateInfo* pCreateInfo,
|
const VkImageViewCreateInfo* pCreateInfo,
|
||||||
const MVKConfiguration* pAltMVKConfig) : MVKRefCountedDeviceObject(device) {
|
const MVKConfiguration* pAltMVKConfig) : MVKVulkanAPIDeviceObject(device) {
|
||||||
_image = (MVKImage*)pCreateInfo->image;
|
_image = (MVKImage*)pCreateInfo->image;
|
||||||
_usage = _image ? _image->_usage : 0;
|
_usage = _image ? _image->_usage : 0;
|
||||||
|
|
||||||
@ -829,12 +830,12 @@ void MVKImageView::validateImageViewConfig(const VkImageViewCreateInfo* pCreateI
|
|||||||
// VK_KHR_maintenance1 supports taking 2D image views of 3D slices. No dice in Metal.
|
// 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 ((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) {
|
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)) {
|
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)) {
|
} 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.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -931,7 +932,7 @@ MTLPixelFormat MVKImageView::getSwizzledMTLPixelFormat(VkFormat format,
|
|||||||
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"
|
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"
|
" 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.");
|
" 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,
|
setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, errMsg, vkCmd,
|
||||||
mvkVkComponentSwizzleName(components.r), mvkVkComponentSwizzleName(components.g),
|
mvkVkComponentSwizzleName(components.r), mvkVkComponentSwizzleName(components.g),
|
||||||
mvkVkComponentSwizzleName(components.b), mvkVkComponentSwizzleName(components.a)));
|
mvkVkComponentSwizzleName(components.b), mvkVkComponentSwizzleName(components.a)));
|
||||||
}
|
}
|
||||||
@ -998,7 +999,7 @@ MTLSamplerDescriptor* MVKSampler::getMTLSamplerDescriptor(const VkSamplerCreateI
|
|||||||
if (_device->_pMetalFeatures->depthSampleCompare) {
|
if (_device->_pMetalFeatures->depthSampleCompare) {
|
||||||
mtlSampDesc.compareFunctionMVK = mvkMTLCompareFunctionFromVkCompareOp(pCreateInfo->compareOp);
|
mtlSampDesc.compareFunctionMVK = mvkMTLCompareFunctionFromVkCompareOp(pCreateInfo->compareOp);
|
||||||
} else {
|
} 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."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1020,7 +1021,7 @@ MTLSamplerDescriptor* MVKSampler::getMTLSamplerDescriptor(const VkSamplerCreateI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Constructs an instance on the specified image.
|
// 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)];
|
_mtlSamplerState = [getMTLDevice() newSamplerStateWithDescriptor: getMTLSamplerDescriptor(pCreateInfo)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,16 +18,19 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "MVKEnvironment.h"
|
||||||
#include "MVKLayers.h"
|
#include "MVKLayers.h"
|
||||||
#include "MVKSurface.h"
|
|
||||||
#include "MVKBaseObject.h"
|
#include "MVKBaseObject.h"
|
||||||
#include "vk_mvk_moltenvk.h"
|
#include "vk_mvk_moltenvk.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
class MVKPhysicalDevice;
|
class MVKPhysicalDevice;
|
||||||
class MVKDevice;
|
class MVKDevice;
|
||||||
|
class MVKSurface;
|
||||||
|
class MVKDebugReportCallback;
|
||||||
|
|
||||||
|
|
||||||
/** Tracks info about entry point function pointer addresses. */
|
/** Tracks info about entry point function pointer addresses. */
|
||||||
@ -48,10 +51,19 @@ typedef struct {
|
|||||||
#pragma mark MVKInstance
|
#pragma mark MVKInstance
|
||||||
|
|
||||||
/** Represents a Vulkan instance. */
|
/** Represents a Vulkan instance. */
|
||||||
class MVKInstance : public MVKDispatchableObject {
|
class MVKInstance : public MVKDispatchableVulkanAPIObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Returns the function pointer corresponding to the named entry point, or NULL if it doesn't exist. */
|
||||||
PFN_vkVoidFunction getProcAddr(const char* pName);
|
PFN_vkVoidFunction getProcAddr(const char* pName);
|
||||||
|
|
||||||
@ -72,14 +84,31 @@ public:
|
|||||||
/** Returns the driver layer. */
|
/** Returns the driver layer. */
|
||||||
MVKLayer* getDriverLayer() { return MVKLayerManager::globalManager()->getDriverLayer(); }
|
MVKLayer* getDriverLayer() { return MVKLayerManager::globalManager()->getDriverLayer(); }
|
||||||
|
|
||||||
/** Creates and returns a new object. */
|
|
||||||
MVKSurface* createSurface(const Vk_PLATFORM_SurfaceCreateInfoMVK* pCreateInfo,
|
MVKSurface* createSurface(const Vk_PLATFORM_SurfaceCreateInfoMVK* pCreateInfo,
|
||||||
const VkAllocationCallbacks* pAllocator);
|
const VkAllocationCallbacks* pAllocator);
|
||||||
|
|
||||||
/** Destroys the specified object. */
|
|
||||||
void destroySurface(MVKSurface* mvkSrfc,
|
void destroySurface(MVKSurface* mvkSrfc,
|
||||||
const VkAllocationCallbacks* pAllocator);
|
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. */
|
/** Returns the MoltenVK configuration settings. */
|
||||||
const MVKConfiguration* getMoltenVKConfiguration() { return &_mvkConfig; }
|
const MVKConfiguration* getMoltenVKConfiguration() { return &_mvkConfig; }
|
||||||
|
|
||||||
@ -115,6 +144,8 @@ protected:
|
|||||||
friend MVKDevice;
|
friend MVKDevice;
|
||||||
|
|
||||||
void initProcAddrs();
|
void initProcAddrs();
|
||||||
|
void initCreationDebugReportCallbacks(const VkInstanceCreateInfo* pCreateInfo);
|
||||||
|
VkDebugReportFlagsEXT getVkDebugReportFlagsFromASLLevel(int aslLvl);
|
||||||
MVKEntryPoint* getEntryPoint(const char* pName);
|
MVKEntryPoint* getEntryPoint(const char* pName);
|
||||||
void initConfig();
|
void initConfig();
|
||||||
void logVersions();
|
void logVersions();
|
||||||
@ -124,5 +155,40 @@ protected:
|
|||||||
VkApplicationInfo _appInfo;
|
VkApplicationInfo _appInfo;
|
||||||
std::vector<MVKPhysicalDevice*> _physicalDevices;
|
std::vector<MVKPhysicalDevice*> _physicalDevices;
|
||||||
std::unordered_map<std::string, MVKEntryPoint> _entryPoints;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "MVKEnvironment.h"
|
#include "MVKEnvironment.h"
|
||||||
#include "MVKSurface.h"
|
#include "MVKSurface.h"
|
||||||
#include "MVKOSExtensions.h"
|
#include "MVKOSExtensions.h"
|
||||||
|
#include "MVKLogging.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -79,6 +80,78 @@ void MVKInstance::destroySurface(MVKSurface* mvkSrfc,
|
|||||||
mvkSrfc->destroy();
|
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
|
#pragma mark Object Creation
|
||||||
|
|
||||||
@ -130,7 +203,9 @@ static NSArray<id<MTLDevice>>* getAvailableMTLDevices() {
|
|||||||
#endif // MVK_IOS
|
#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
|
_appInfo.apiVersion = MVK_VULKAN_API_VERSION; // Default
|
||||||
mvkSetOrClear(&_appInfo, pCreateInfo->pApplicationInfo);
|
mvkSetOrClear(&_appInfo, pCreateInfo->pApplicationInfo);
|
||||||
@ -147,7 +222,7 @@ MVKInstance::MVKInstance(const VkInstanceCreateInfo* pCreateInfo) {
|
|||||||
|
|
||||||
if (MVK_VULKAN_API_VERSION_CONFORM(MVK_VULKAN_API_VERSION) <
|
if (MVK_VULKAN_API_VERSION_CONFORM(MVK_VULKAN_API_VERSION) <
|
||||||
MVK_VULKAN_API_VERSION_CONFORM(_appInfo.apiVersion)) {
|
MVK_VULKAN_API_VERSION_CONFORM(_appInfo.apiVersion)) {
|
||||||
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INCOMPATIBLE_DRIVER,
|
setConfigurationResult(reportError(VK_ERROR_INCOMPATIBLE_DRIVER,
|
||||||
"Request for Vulkan version %s is not compatible with supported version %s.",
|
"Request for Vulkan version %s is not compatible with supported version %s.",
|
||||||
mvkGetVulkanVersionString(_appInfo.apiVersion).c_str(),
|
mvkGetVulkanVersionString(_appInfo.apiVersion).c_str(),
|
||||||
mvkGetVulkanVersionString(MVK_VULKAN_API_VERSION).c_str()));
|
mvkGetVulkanVersionString(MVK_VULKAN_API_VERSION).c_str()));
|
||||||
@ -160,12 +235,32 @@ MVKInstance::MVKInstance(const VkInstanceCreateInfo* pCreateInfo) {
|
|||||||
_physicalDevices.push_back(new MVKPhysicalDevice(this, mtlDev));
|
_physicalDevices.push_back(new MVKPhysicalDevice(this, mtlDev));
|
||||||
}
|
}
|
||||||
if (_physicalDevices.empty()) {
|
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:";
|
MVKLogInfo("Created VkInstance with the following %d Vulkan extensions enabled:%s",
|
||||||
logMsg += _enabledExtensions.enabledNamesString("\n\t\t", true);
|
_enabledExtensions.getEnabledCount(),
|
||||||
MVKLogInfo("%s", logMsg.c_str());
|
_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_ENTRY_POINT(func, ext1, ext2, isDev) _entryPoints[""#func] = { (PFN_vkVoidFunction)&func, ext1, ext2, isDev }
|
||||||
@ -179,7 +274,7 @@ MVKInstance::MVKInstance(const VkInstanceCreateInfo* pCreateInfo) {
|
|||||||
#define ADD_INST_EXT2_ENTRY_POINT(func, EXT1, EXT2) ADD_ENTRY_POINT(func, VK_ ##EXT1 ##_EXTENSION_NAME, VK_ ##EXT2 ##_EXTENSION_NAME, false)
|
#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)
|
#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() {
|
void MVKInstance::initProcAddrs() {
|
||||||
|
|
||||||
// Instance functions
|
// Instance functions
|
||||||
@ -335,6 +430,9 @@ void MVKInstance::initProcAddrs() {
|
|||||||
ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfacePresentModesKHR, KHR_SURFACE);
|
ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfacePresentModesKHR, KHR_SURFACE);
|
||||||
ADD_INST_EXT_ENTRY_POINT(vkGetPhysicalDeviceSurfaceCapabilities2KHR, KHR_GET_SURFACE_CAPABILITIES_2);
|
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(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
|
#ifdef VK_USE_PLATFORM_IOS_MVK
|
||||||
ADD_INST_EXT_ENTRY_POINT(vkCreateIOSSurfaceMVK, MVK_IOS_SURFACE);
|
ADD_INST_EXT_ENTRY_POINT(vkCreateIOSSurfaceMVK, MVK_IOS_SURFACE);
|
||||||
@ -382,16 +480,14 @@ void MVKInstance::initProcAddrs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MVKInstance::logVersions() {
|
void MVKInstance::logVersions() {
|
||||||
string logMsg = "MoltenVK version ";
|
MVKExtensionList* pExtns = getDriverLayer()->getSupportedExtensions();
|
||||||
logMsg += mvkGetMoltenVKVersionString(MVK_VERSION);
|
MVKLogInfo("MoltenVK version %s. Vulkan version %s.\n\tThe following %d Vulkan extensions are supported:%s",
|
||||||
logMsg += ". Vulkan version ";
|
mvkGetMoltenVKVersionString(MVK_VERSION).c_str(),
|
||||||
logMsg += mvkGetVulkanVersionString(MVK_VULKAN_API_VERSION);
|
mvkGetVulkanVersionString(MVK_VULKAN_API_VERSION).c_str(),
|
||||||
logMsg += ".\n\tThe following Vulkan extensions are supported:";
|
pExtns->getEnabledCount(),
|
||||||
logMsg += getDriverLayer()->getSupportedExtensions()->enabledNamesString("\n\t\t", true);
|
pExtns->enabledNamesString("\n\t\t", true).c_str());
|
||||||
MVKLogInfo("%s", logMsg.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init config.
|
|
||||||
void MVKInstance::initConfig() {
|
void MVKInstance::initConfig() {
|
||||||
MVK_SET_FROM_ENV_OR_BUILD_BOOL( _mvkConfig.debugMode, MVK_DEBUG);
|
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);
|
MVK_SET_FROM_ENV_OR_BUILD_BOOL( _mvkConfig.shaderConversionFlipVertexY, MVK_CONFIG_SHADER_CONVERSION_FLIP_VERTEX_Y);
|
||||||
@ -416,13 +512,17 @@ VkResult MVKInstance::verifyLayers(uint32_t count, const char* const* names) {
|
|||||||
VkResult result = VK_SUCCESS;
|
VkResult result = VK_SUCCESS;
|
||||||
for (uint32_t i = 0; i < count; i++) {
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
if ( !MVKLayerManager::globalManager()->getLayerNamed(names[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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKInstance::~MVKInstance() {
|
MVKInstance::~MVKInstance() {
|
||||||
|
_useCreationCallbacks = true;
|
||||||
mvkDestroyContainerContents(_physicalDevices);
|
mvkDestroyContainerContents(_physicalDevices);
|
||||||
|
|
||||||
|
lock_guard<mutex> lock(_drcbLock);
|
||||||
|
mvkDestroyContainerContents(_debugReportCallbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,10 +42,13 @@ struct MVKShaderImplicitRezBinding {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Represents a Vulkan pipeline layout. */
|
/** Represents a Vulkan pipeline layout. */
|
||||||
class MVKPipelineLayout : public MVKBaseDeviceObject {
|
class MVKPipelineLayout : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Binds descriptor sets to a command encoder. */
|
||||||
void bindDescriptorSets(MVKCommandEncoder* cmdEncoder,
|
void bindDescriptorSets(MVKCommandEncoder* cmdEncoder,
|
||||||
MVKVector<MVKDescriptorSet*>& descriptorSets,
|
MVKVector<MVKDescriptorSet*>& descriptorSets,
|
||||||
@ -113,10 +116,13 @@ static const uint32_t kMVKTessEvalLevelBufferIndex = 28;
|
|||||||
static const uint32_t kMVKTessEvalNumReservedBuffers = 3;
|
static const uint32_t kMVKTessEvalNumReservedBuffers = 3;
|
||||||
|
|
||||||
/** Represents an abstract Vulkan pipeline. */
|
/** Represents an abstract Vulkan pipeline. */
|
||||||
class MVKPipeline : public MVKBaseDeviceObject {
|
class MVKPipeline : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** 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;
|
virtual void getStages(MVKVector<uint32_t>& stages) = 0;
|
||||||
|
|
||||||
@ -130,7 +136,7 @@ public:
|
|||||||
bool fullImageViewSwizzle() const { return _fullImageViewSwizzle; }
|
bool fullImageViewSwizzle() const { return _fullImageViewSwizzle; }
|
||||||
|
|
||||||
/** Constructs an instance for the device. layout, and parent (which may be NULL). */
|
/** 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),
|
_pipelineCache(pipelineCache),
|
||||||
_fullImageViewSwizzle(device->_pMVKConfig->fullImageViewSwizzle) {}
|
_fullImageViewSwizzle(device->_pMVKConfig->fullImageViewSwizzle) {}
|
||||||
|
|
||||||
@ -301,10 +307,13 @@ protected:
|
|||||||
#pragma mark MVKPipelineCache
|
#pragma mark MVKPipelineCache
|
||||||
|
|
||||||
/** Represents a Vulkan pipeline cache. */
|
/** Represents a Vulkan pipeline cache. */
|
||||||
class MVKPipelineCache : public MVKBaseDeviceObject {
|
class MVKPipelineCache : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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
|
* 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,
|
* memory location, and returns the number of bytes serialized in pDataSize. If pData is null,
|
||||||
@ -360,9 +369,9 @@ public:
|
|||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKRenderPipelineCompiler(MVKDevice* device) : MVKMetalCompiler(device) {
|
MVKRenderPipelineCompiler(MVKVulkanAPIDeviceObject* owner) : MVKMetalCompiler(owner) {
|
||||||
_compilerType = "Render pipeline";
|
_compilerType = "Render pipeline";
|
||||||
_pPerformanceTracker = &_device->_performanceStatistics.shaderCompilation.pipelineCompile;
|
_pPerformanceTracker = &_owner->getDevice()->_performanceStatistics.shaderCompilation.pipelineCompile;
|
||||||
}
|
}
|
||||||
|
|
||||||
~MVKRenderPipelineCompiler() override;
|
~MVKRenderPipelineCompiler() override;
|
||||||
@ -405,9 +414,9 @@ public:
|
|||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKComputePipelineCompiler(MVKDevice* device) : MVKMetalCompiler(device) {
|
MVKComputePipelineCompiler(MVKVulkanAPIDeviceObject* owner) : MVKMetalCompiler(owner) {
|
||||||
_compilerType = "Compute pipeline";
|
_compilerType = "Compute pipeline";
|
||||||
_pPerformanceTracker = &_device->_performanceStatistics.shaderCompilation.pipelineCompile;
|
_pPerformanceTracker = &_owner->getDevice()->_performanceStatistics.shaderCompilation.pipelineCompile;
|
||||||
}
|
}
|
||||||
|
|
||||||
~MVKComputePipelineCompiler() override;
|
~MVKComputePipelineCompiler() override;
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "MVKOSExtensions.h"
|
#include "MVKOSExtensions.h"
|
||||||
#include "MVKStrings.h"
|
#include "MVKStrings.h"
|
||||||
#include "MTLRenderPipelineDescriptor+MoltenVK.h"
|
#include "MTLRenderPipelineDescriptor+MoltenVK.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "mvk_datatypes.hpp"
|
||||||
|
|
||||||
#include <cereal/archives/binary.hpp>
|
#include <cereal/archives/binary.hpp>
|
||||||
#include <cereal/types/string.hpp>
|
#include <cereal/types/string.hpp>
|
||||||
@ -107,7 +107,7 @@ void MVKPipelineLayout::populateShaderConverterContext(SPIRVToMSLConverterContex
|
|||||||
}
|
}
|
||||||
|
|
||||||
MVKPipelineLayout::MVKPipelineLayout(MVKDevice* device,
|
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
|
// Add descriptor set layouts, accumulating the resource index offsets used by the
|
||||||
// corresponding DSL, and associating the current accumulated resource index offsets
|
// corresponding DSL, and associating the current accumulated resource index offsets
|
||||||
@ -277,12 +277,12 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
|
|||||||
std::string reflectErrorLog;
|
std::string reflectErrorLog;
|
||||||
if (_pTessCtlSS && _pTessEvalSS) {
|
if (_pTessCtlSS && _pTessEvalSS) {
|
||||||
if (!getTessReflectionData(((MVKShaderModule*)_pTessCtlSS->module)->getSPIRV(), _pTessCtlSS->pName, ((MVKShaderModule*)_pTessEvalSS->module)->getSPIRV(), _pTessEvalSS->pName, reflectData, reflectErrorLog) ) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
// Unfortunately, we can't support line tessellation at this time.
|
// Unfortunately, we can't support line tessellation at this time.
|
||||||
if (reflectData.patchKind == spv::ExecutionModeIsolines) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,7 +326,7 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
|
|||||||
if (_device->_enabledFeatures.depthClamp) {
|
if (_device->_enabledFeatures.depthClamp) {
|
||||||
_mtlDepthClipMode = MTLDepthClipModeClamp;
|
_mtlDepthClipMode = MTLDepthClipModeClamp;
|
||||||
} else {
|
} 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 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
|
|||||||
// Either returns an existing pipeline state or compiles a new one.
|
// Either returns an existing pipeline state or compiles a new one.
|
||||||
id<MTLRenderPipelineState> MVKGraphicsPipeline::getOrCompilePipeline(MTLRenderPipelineDescriptor* plDesc, id<MTLRenderPipelineState>& plState) {
|
id<MTLRenderPipelineState> MVKGraphicsPipeline::getOrCompilePipeline(MTLRenderPipelineDescriptor* plDesc, id<MTLRenderPipelineState>& plState) {
|
||||||
if (!plState) {
|
if (!plState) {
|
||||||
MVKRenderPipelineCompiler* plc = new MVKRenderPipelineCompiler(_device);
|
MVKRenderPipelineCompiler* plc = new MVKRenderPipelineCompiler(this);
|
||||||
plState = plc->newMTLRenderPipelineState(plDesc); // retained
|
plState = plc->newMTLRenderPipelineState(plDesc); // retained
|
||||||
setConfigurationResult(plc->getConfigurationResult());
|
|
||||||
plc->destroy();
|
plc->destroy();
|
||||||
}
|
}
|
||||||
return plState;
|
return plState;
|
||||||
@ -374,9 +373,8 @@ id<MTLRenderPipelineState> MVKGraphicsPipeline::getOrCompilePipeline(MTLRenderPi
|
|||||||
// Either returns an existing pipeline state or compiles a new one.
|
// Either returns an existing pipeline state or compiles a new one.
|
||||||
id<MTLComputePipelineState> MVKGraphicsPipeline::getOrCompilePipeline(MTLComputePipelineDescriptor* plDesc, id<MTLComputePipelineState>& plState) {
|
id<MTLComputePipelineState> MVKGraphicsPipeline::getOrCompilePipeline(MTLComputePipelineDescriptor* plDesc, id<MTLComputePipelineState>& plState) {
|
||||||
if (!plState) {
|
if (!plState) {
|
||||||
MVKComputePipelineCompiler* plc = new MVKComputePipelineCompiler(_device);
|
MVKComputePipelineCompiler* plc = new MVKComputePipelineCompiler(this);
|
||||||
plState = plc->newMTLComputePipelineState(plDesc); // retained
|
plState = plc->newMTLComputePipelineState(plDesc); // retained
|
||||||
setConfigurationResult(plc->getConfigurationResult());
|
|
||||||
plc->destroy();
|
plc->destroy();
|
||||||
}
|
}
|
||||||
return plState;
|
return plState;
|
||||||
@ -551,7 +549,7 @@ MTLComputePipelineDescriptor* MVKGraphicsPipeline::getMTLTessControlStageDescrip
|
|||||||
std::string errorLog;
|
std::string errorLog;
|
||||||
// Unfortunately, MoltenVKShaderConverter doesn't know about MVKVector, so we can't use that here.
|
// 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) ) {
|
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;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,7 +588,7 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLTessRasterStageDescripto
|
|||||||
std::vector<SPIRVShaderOutput> tcOutputs;
|
std::vector<SPIRVShaderOutput> tcOutputs;
|
||||||
std::string errorLog;
|
std::string errorLog;
|
||||||
if (!getShaderOutputs(((MVKShaderModule*)_pTessCtlSS->module)->getSPIRV(), spv::ExecutionModelTessellationControl, _pTessCtlSS->pName, tcOutputs, 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;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,7 +703,7 @@ bool MVKGraphicsPipeline::addVertexShaderToPipeline(MTLRenderPipelineDescriptor*
|
|||||||
addVertexInputToShaderConverterContext(shaderContext, pCreateInfo);
|
addVertexInputToShaderConverterContext(shaderContext, pCreateInfo);
|
||||||
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pVertexSS->module)->getMTLFunction(&shaderContext, _pVertexSS->pSpecializationInfo, _pipelineCache).mtlFunction;
|
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pVertexSS->module)->getMTLFunction(&shaderContext, _pVertexSS->pSpecializationInfo, _pipelineCache).mtlFunction;
|
||||||
if ( !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;
|
return false;
|
||||||
}
|
}
|
||||||
plDesc.vertexFunction = mtlFunction;
|
plDesc.vertexFunction = mtlFunction;
|
||||||
@ -714,16 +712,16 @@ bool MVKGraphicsPipeline::addVertexShaderToPipeline(MTLRenderPipelineDescriptor*
|
|||||||
_needsVertexOutputBuffer = shaderContext.options.needsOutputBuffer;
|
_needsVertexOutputBuffer = shaderContext.options.needsOutputBuffer;
|
||||||
// If we need the auxiliary buffer and there's no place to put it, we're in serious trouble.
|
// 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) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
// Ditto captured output buffer.
|
// Ditto captured output buffer.
|
||||||
if (_needsVertexOutputBuffer && _outputBufferIndex.stages[kMVKShaderStageVertex] >= _device->_pMetalFeatures->maxPerStageBufferCount - vbCnt) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if (_needsVertexOutputBuffer && _indirectParamsIndex.stages[kMVKShaderStageVertex] >= _device->_pMetalFeatures->maxPerStageBufferCount - vbCnt) {
|
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 false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -741,7 +739,7 @@ bool MVKGraphicsPipeline::addTessCtlShaderToPipeline(MTLComputePipelineDescripto
|
|||||||
addPrevStageOutputToShaderConverterContext(shaderContext, vtxOutputs);
|
addPrevStageOutputToShaderConverterContext(shaderContext, vtxOutputs);
|
||||||
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pTessCtlSS->module)->getMTLFunction(&shaderContext, _pTessCtlSS->pSpecializationInfo, _pipelineCache).mtlFunction;
|
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pTessCtlSS->module)->getMTLFunction(&shaderContext, _pTessCtlSS->pSpecializationInfo, _pipelineCache).mtlFunction;
|
||||||
if ( !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;
|
return false;
|
||||||
}
|
}
|
||||||
plDesc.computeFunction = mtlFunction;
|
plDesc.computeFunction = mtlFunction;
|
||||||
@ -750,23 +748,23 @@ bool MVKGraphicsPipeline::addTessCtlShaderToPipeline(MTLComputePipelineDescripto
|
|||||||
_needsTessCtlPatchOutputBuffer = shaderContext.options.needsPatchOutputBuffer;
|
_needsTessCtlPatchOutputBuffer = shaderContext.options.needsPatchOutputBuffer;
|
||||||
_needsTessCtlInput = shaderContext.options.needsInputThreadgroupMem;
|
_needsTessCtlInput = shaderContext.options.needsInputThreadgroupMem;
|
||||||
if (_needsTessCtlAuxBuffer && _auxBufferIndex.stages[kMVKShaderStageTessCtl] >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if (_indirectParamsIndex.stages[kMVKShaderStageTessCtl] >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if (_needsTessCtlOutputBuffer && _outputBufferIndex.stages[kMVKShaderStageTessCtl] >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if (_needsTessCtlPatchOutputBuffer && _tessCtlPatchOutputBufferIndex >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if (_tessCtlLevelBufferIndex >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
|
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 false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -781,7 +779,7 @@ bool MVKGraphicsPipeline::addTessEvalShaderToPipeline(MTLRenderPipelineDescripto
|
|||||||
addPrevStageOutputToShaderConverterContext(shaderContext, tcOutputs);
|
addPrevStageOutputToShaderConverterContext(shaderContext, tcOutputs);
|
||||||
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pTessEvalSS->module)->getMTLFunction(&shaderContext, _pTessEvalSS->pSpecializationInfo, _pipelineCache).mtlFunction;
|
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pTessEvalSS->module)->getMTLFunction(&shaderContext, _pTessEvalSS->pSpecializationInfo, _pipelineCache).mtlFunction;
|
||||||
if ( !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;
|
return false;
|
||||||
}
|
}
|
||||||
// Yeah, you read that right. Tess. eval functions are a kind of vertex function in Metal.
|
// Yeah, you read that right. Tess. eval functions are a kind of vertex function in Metal.
|
||||||
@ -790,7 +788,7 @@ bool MVKGraphicsPipeline::addTessEvalShaderToPipeline(MTLRenderPipelineDescripto
|
|||||||
_needsTessEvalAuxBuffer = shaderContext.options.needsAuxBuffer;
|
_needsTessEvalAuxBuffer = shaderContext.options.needsAuxBuffer;
|
||||||
// If we need the auxiliary buffer and there's no place to put it, we're in serious trouble.
|
// 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) {
|
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 false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -804,13 +802,13 @@ bool MVKGraphicsPipeline::addFragmentShaderToPipeline(MTLRenderPipelineDescripto
|
|||||||
shaderContext.options.shouldCaptureOutput = false;
|
shaderContext.options.shouldCaptureOutput = false;
|
||||||
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pFragmentSS->module)->getMTLFunction(&shaderContext, _pFragmentSS->pSpecializationInfo, _pipelineCache).mtlFunction;
|
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pFragmentSS->module)->getMTLFunction(&shaderContext, _pFragmentSS->pSpecializationInfo, _pipelineCache).mtlFunction;
|
||||||
if ( !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;
|
return false;
|
||||||
}
|
}
|
||||||
plDesc.fragmentFunction = mtlFunction;
|
plDesc.fragmentFunction = mtlFunction;
|
||||||
_needsFragmentAuxBuffer = shaderContext.options.needsAuxBuffer;
|
_needsFragmentAuxBuffer = shaderContext.options.needsAuxBuffer;
|
||||||
if (_needsFragmentAuxBuffer && _auxBufferIndex.stages[kMVKShaderStageFragment] >= _device->_pMetalFeatures->maxPerStageBufferCount) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -847,7 +845,7 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(MTLRenderPipelineDescriptor*
|
|||||||
for (uint32_t j = 0; j < vbCnt; j++, pVKVB++) {
|
for (uint32_t j = 0; j < vbCnt; j++, pVKVB++) {
|
||||||
if (pVKVB->binding == pVKVA->binding) {
|
if (pVKVB->binding == pVKVA->binding) {
|
||||||
if (pVKVA->offset >= pVKVB->stride) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -871,7 +869,7 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(MTLRenderPipelineDescriptor*
|
|||||||
// Vulkan allows any stride, but Metal only allows multiples of 4.
|
// 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.
|
// TODO: We should try to expand the buffer to the required alignment in that case.
|
||||||
if ((pVKVB->stride % 4) != 0) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1168,16 +1166,15 @@ MVKComputePipeline::MVKComputePipeline(MVKDevice* device,
|
|||||||
_mtlPipelineState = nil;
|
_mtlPipelineState = nil;
|
||||||
|
|
||||||
if (shaderFunc.mtlFunction) {
|
if (shaderFunc.mtlFunction) {
|
||||||
MVKComputePipelineCompiler* plc = new MVKComputePipelineCompiler(_device);
|
MVKComputePipelineCompiler* plc = new MVKComputePipelineCompiler(this);
|
||||||
_mtlPipelineState = plc->newMTLComputePipelineState(shaderFunc.mtlFunction); // retained
|
_mtlPipelineState = plc->newMTLComputePipelineState(shaderFunc.mtlFunction); // retained
|
||||||
setConfigurationResult(plc->getConfigurationResult());
|
|
||||||
plc->destroy();
|
plc->destroy();
|
||||||
} else {
|
} 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) {
|
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 @@ MVKShaderLibrary* MVKPipelineCache::getShaderLibrary(SPIRVToMSLConverterContext*
|
|||||||
MVKShaderLibraryCache* MVKPipelineCache::getShaderLibraryCache(MVKShaderModuleKey smKey) {
|
MVKShaderLibraryCache* MVKPipelineCache::getShaderLibraryCache(MVKShaderModuleKey smKey) {
|
||||||
MVKShaderLibraryCache* slCache = _shaderCache[smKey];
|
MVKShaderLibraryCache* slCache = _shaderCache[smKey];
|
||||||
if ( !slCache ) {
|
if ( !slCache ) {
|
||||||
slCache = new MVKShaderLibraryCache(_device);
|
slCache = new MVKShaderLibraryCache(this);
|
||||||
_shaderCache[smKey] = slCache;
|
_shaderCache[smKey] = slCache;
|
||||||
}
|
}
|
||||||
return slCache;
|
return slCache;
|
||||||
@ -1311,7 +1308,11 @@ void serialize(Archive & archive, MVKShaderModuleKey& k) {
|
|||||||
|
|
||||||
// Helper class to iterate through the shader libraries in a shader library cache in order to serialize them.
|
// 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.
|
// 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:
|
protected:
|
||||||
friend MVKPipelineCache;
|
friend MVKPipelineCache;
|
||||||
|
|
||||||
@ -1361,7 +1362,7 @@ VkResult MVKPipelineCache::writeData(size_t* pDataSize, void* pData) {
|
|||||||
|
|
||||||
} catch (cereal::Exception& ex) {
|
} catch (cereal::Exception& ex) {
|
||||||
*pDataSize = 0;
|
*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 @@ void MVKPipelineCache::readData(const VkPipelineCacheCreateInfo* pCreateInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (cereal::Exception& ex) {
|
} 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 @@ VkResult MVKPipelineCache::mergePipelineCaches(uint32_t srcCacheCount, const VkP
|
|||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKPipelineCache::MVKPipelineCache(MVKDevice* device, const VkPipelineCacheCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
|
MVKPipelineCache::MVKPipelineCache(MVKDevice* device, const VkPipelineCacheCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
|
||||||
readData(pCreateInfo);
|
readData(pCreateInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1516,7 +1517,7 @@ id<MTLRenderPipelineState> MVKRenderPipelineCompiler::newMTLRenderPipelineState(
|
|||||||
unique_lock<mutex> lock(_completionLock);
|
unique_lock<mutex> lock(_completionLock);
|
||||||
|
|
||||||
compile(lock, ^{
|
compile(lock, ^{
|
||||||
[getMTLDevice() newRenderPipelineStateWithDescriptor: mtlRPLDesc
|
[_owner->getMTLDevice() newRenderPipelineStateWithDescriptor: mtlRPLDesc
|
||||||
completionHandler: ^(id<MTLRenderPipelineState> ps, NSError* error) {
|
completionHandler: ^(id<MTLRenderPipelineState> ps, NSError* error) {
|
||||||
bool isLate = compileComplete(ps, error);
|
bool isLate = compileComplete(ps, error);
|
||||||
if (isLate) { destroy(); }
|
if (isLate) { destroy(); }
|
||||||
@ -1547,7 +1548,7 @@ id<MTLComputePipelineState> MVKComputePipelineCompiler::newMTLComputePipelineSta
|
|||||||
unique_lock<mutex> lock(_completionLock);
|
unique_lock<mutex> lock(_completionLock);
|
||||||
|
|
||||||
compile(lock, ^{
|
compile(lock, ^{
|
||||||
[getMTLDevice() newComputePipelineStateWithFunction: mtlFunction
|
[_owner->getMTLDevice() newComputePipelineStateWithFunction: mtlFunction
|
||||||
completionHandler: ^(id<MTLComputePipelineState> ps, NSError* error) {
|
completionHandler: ^(id<MTLComputePipelineState> ps, NSError* error) {
|
||||||
bool isLate = compileComplete(ps, error);
|
bool isLate = compileComplete(ps, error);
|
||||||
if (isLate) { destroy(); }
|
if (isLate) { destroy(); }
|
||||||
@ -1561,7 +1562,7 @@ id<MTLComputePipelineState> MVKComputePipelineCompiler::newMTLComputePipelineSta
|
|||||||
unique_lock<mutex> lock(_completionLock);
|
unique_lock<mutex> lock(_completionLock);
|
||||||
|
|
||||||
compile(lock, ^{
|
compile(lock, ^{
|
||||||
[getMTLDevice() newComputePipelineStateWithDescriptor: plDesc
|
[_owner->getMTLDevice() newComputePipelineStateWithDescriptor: plDesc
|
||||||
options: MTLPipelineOptionNone
|
options: MTLPipelineOptionNone
|
||||||
completionHandler: ^(id<MTLComputePipelineState> ps, MTLComputePipelineReflection*, NSError* error) {
|
completionHandler: ^(id<MTLComputePipelineState> ps, MTLComputePipelineReflection*, NSError* error) {
|
||||||
bool isLate = compileComplete(ps, error);
|
bool isLate = compileComplete(ps, error);
|
||||||
|
@ -39,10 +39,13 @@ class MVKCommandEncoder;
|
|||||||
* Subclasses are specialized for specific query types.
|
* Subclasses are specialized for specific query types.
|
||||||
* Subclasses will generally override the beginQuery(), endQuery(), and getResult(uint32_t, void*, bool) member functions.
|
* Subclasses will generally override the beginQuery(), endQuery(), and getResult(uint32_t, void*, bool) member functions.
|
||||||
*/
|
*/
|
||||||
class MVKQueryPool : public MVKBaseDeviceObject {
|
class MVKQueryPool : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Begins the specified query. */
|
||||||
virtual void beginQuery(uint32_t query, VkQueryControlFlags flags, MVKCommandEncoder* cmdEncoder) {}
|
virtual void beginQuery(uint32_t query, VkQueryControlFlags flags, MVKCommandEncoder* cmdEncoder) {}
|
||||||
|
|
||||||
@ -79,7 +82,7 @@ public:
|
|||||||
|
|
||||||
MVKQueryPool(MVKDevice* device,
|
MVKQueryPool(MVKDevice* device,
|
||||||
const VkQueryPoolCreateInfo* pCreateInfo,
|
const VkQueryPoolCreateInfo* pCreateInfo,
|
||||||
const uint32_t queryElementCount) : MVKBaseDeviceObject(device),
|
const uint32_t queryElementCount) : MVKVulkanAPIDeviceObject(device),
|
||||||
_availability(pCreateInfo->queryCount),
|
_availability(pCreateInfo->queryCount),
|
||||||
_queryElementCount(queryElementCount) {}
|
_queryElementCount(queryElementCount) {}
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ void MVKQueryPool::copyQueryPoolResults(uint32_t firstQuery,
|
|||||||
size_t dataSize = destStride * queryCount;
|
size_t dataSize = destStride * queryCount;
|
||||||
getResults(firstQuery, queryCount, dataSize, pData, destStride, flags);
|
getResults(firstQuery, queryCount, dataSize, pData, destStride, flags);
|
||||||
} else {
|
} else {
|
||||||
mvkNotifyErrorWithText(VK_ERROR_MEMORY_MAP_FAILED, "Private GPU-only memory cannot be used for query pool results.");
|
reportError(VK_ERROR_MEMORY_MAP_FAILED, "Private GPU-only memory cannot be used for query pool results.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ void MVKOcclusionQueryPool::beginQueryAddedTo(uint32_t query, MVKCommandBuffer*
|
|||||||
NSUInteger offset = getVisibilityResultOffset(query);
|
NSUInteger offset = getVisibilityResultOffset(query);
|
||||||
NSUInteger maxOffset = getDevice()->_pMetalFeatures->maxQueryBufferSize - kMVKQuerySlotSizeInBytes;
|
NSUInteger maxOffset = getDevice()->_pMetalFeatures->maxQueryBufferSize - kMVKQuerySlotSizeInBytes;
|
||||||
if (offset > maxOffset) {
|
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) {
|
if (cmdBuffer->_initialVisibilityResultMTLBuffer == nil) {
|
||||||
@ -221,7 +221,7 @@ MVKOcclusionQueryPool::MVKOcclusionQueryPool(MVKDevice* device,
|
|||||||
queryCount = uint32_t(newBuffLen / kMVKQuerySlotSizeInBytes);
|
queryCount = uint32_t(newBuffLen / kMVKQuerySlotSizeInBytes);
|
||||||
|
|
||||||
if (reqBuffLen > maxBuffLen) {
|
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);
|
NSUInteger mtlBuffLen = mvkAlignByteOffset(newBuffLen, _device->_pMetalFeatures->mtlBufferAlignment);
|
||||||
@ -245,7 +245,7 @@ MVKOcclusionQueryPool::~MVKOcclusionQueryPool() {
|
|||||||
MVKPipelineStatisticsQueryPool::MVKPipelineStatisticsQueryPool(MVKDevice* device,
|
MVKPipelineStatisticsQueryPool::MVKPipelineStatisticsQueryPool(MVKDevice* device,
|
||||||
const VkQueryPoolCreateInfo* pCreateInfo) : MVKQueryPool(device, pCreateInfo, 1) {
|
const VkQueryPoolCreateInfo* pCreateInfo) : MVKQueryPool(device, pCreateInfo, 1) {
|
||||||
if ( !_device->_enabledFeatures.pipelineStatisticsQuery ) {
|
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."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,5 +255,5 @@ MVKPipelineStatisticsQueryPool::MVKPipelineStatisticsQueryPool(MVKDevice* device
|
|||||||
|
|
||||||
MVKUnsupportedQueryPool::MVKUnsupportedQueryPool(MVKDevice* device,
|
MVKUnsupportedQueryPool::MVKUnsupportedQueryPool(MVKDevice* device,
|
||||||
const VkQueryPoolCreateInfo* pCreateInfo) : MVKQueryPool(device, pCreateInfo, 1) {
|
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));
|
||||||
}
|
}
|
||||||
|
@ -38,10 +38,13 @@ class MVKGPUCaptureScope;
|
|||||||
#pragma mark MVKQueueFamily
|
#pragma mark MVKQueueFamily
|
||||||
|
|
||||||
/** Represents a Vulkan queue family. */
|
/** Represents a Vulkan queue family. */
|
||||||
class MVKQueueFamily : public MVKConfigurableObject {
|
class MVKQueueFamily : public MVKBaseObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** Returns the Vulkan API opaque object controlling this object. */
|
||||||
|
MVKVulkanAPIObject* getVulkanAPIObject() override { return _physicalDevice->getVulkanAPIObject(); }
|
||||||
|
|
||||||
/** Returns the index of this queue family. */
|
/** Returns the index of this queue family. */
|
||||||
inline uint32_t getIndex() { return _queueFamilyIndex; }
|
inline uint32_t getIndex() { return _queueFamilyIndex; }
|
||||||
|
|
||||||
@ -71,10 +74,16 @@ protected:
|
|||||||
#pragma mark MVKQueue
|
#pragma mark MVKQueue
|
||||||
|
|
||||||
/** Represents a Vulkan queue. */
|
/** Represents a Vulkan queue. */
|
||||||
class MVKQueue : public MVKDispatchableDeviceObject {
|
class MVKQueue : public MVKDispatchableVulkanAPIObject, public MVKDeviceTrackingMixin {
|
||||||
|
|
||||||
public:
|
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
|
#pragma mark Queue submissions
|
||||||
|
|
||||||
/** Submits the specified command buffers to the queue. */
|
/** Submits the specified command buffers to the queue. */
|
||||||
@ -122,6 +131,7 @@ protected:
|
|||||||
friend class MVKQueueCommandBufferSubmission;
|
friend class MVKQueueCommandBufferSubmission;
|
||||||
friend class MVKQueuePresentSurfaceSubmission;
|
friend class MVKQueuePresentSurfaceSubmission;
|
||||||
|
|
||||||
|
MVKBaseObject* getBaseObject() override { return this; };
|
||||||
void initName();
|
void initName();
|
||||||
void initExecQueue();
|
void initExecQueue();
|
||||||
void initMTLCommandQueue();
|
void initMTLCommandQueue();
|
||||||
@ -145,10 +155,13 @@ protected:
|
|||||||
#pragma mark MVKQueueSubmission
|
#pragma mark MVKQueueSubmission
|
||||||
|
|
||||||
/** This is an abstract class for an operation that can be submitted to an MVKQueue. */
|
/** This is an abstract class for an operation that can be submitted to an MVKQueue. */
|
||||||
class MVKQueueSubmission : public MVKBaseDeviceObject {
|
class MVKQueueSubmission : public MVKConfigurableObject {
|
||||||
|
|
||||||
public:
|
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.
|
* Executes this action on the queue and then disposes of this instance.
|
||||||
*
|
*
|
||||||
@ -156,20 +169,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void execute() = 0;
|
virtual void execute() = 0;
|
||||||
|
|
||||||
MVKQueueSubmission(MVKDevice* device,
|
MVKQueueSubmission(MVKQueue* queue,
|
||||||
MVKQueue* queue,
|
|
||||||
uint32_t waitSemaphoreCount,
|
uint32_t waitSemaphoreCount,
|
||||||
const VkSemaphore* pWaitSemaphores);
|
const VkSemaphore* pWaitSemaphores);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class MVKQueue;
|
friend class MVKQueue;
|
||||||
|
|
||||||
void recordResult(VkResult vkResult);
|
|
||||||
|
|
||||||
MVKQueue* _queue;
|
MVKQueue* _queue;
|
||||||
MVKQueueSubmission* _prev;
|
MVKQueueSubmission* _prev;
|
||||||
MVKQueueSubmission* _next;
|
MVKQueueSubmission* _next;
|
||||||
VkResult _submissionResult;
|
|
||||||
MVKVectorInline<MVKSemaphore*, 8> _waitSemaphores;
|
MVKVectorInline<MVKSemaphore*, 8> _waitSemaphores;
|
||||||
bool _isAwaitingSemaphores;
|
bool _isAwaitingSemaphores;
|
||||||
};
|
};
|
||||||
@ -185,17 +194,16 @@ public:
|
|||||||
void execute() override;
|
void execute() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance for the device and queue.
|
* Constructs an instance for the queue.
|
||||||
* pSubmit may be VK_NULL_HANDLE to create an instance that triggers a fence without submitting any actual command buffers.
|
* pSubmit may be VK_NULL_HANDLE to create an instance that triggers a fence without submitting any actual command buffers.
|
||||||
*/
|
*/
|
||||||
MVKQueueCommandBufferSubmission(MVKDevice* device,
|
MVKQueueCommandBufferSubmission(MVKQueue* queue,
|
||||||
MVKQueue* queue,
|
|
||||||
const VkSubmitInfo* pSubmit,
|
const VkSubmitInfo* pSubmit,
|
||||||
VkFence fence,
|
VkFence fence,
|
||||||
MVKCommandUse cmdBuffUse);
|
MVKCommandUse cmdBuffUse);
|
||||||
|
|
||||||
/** Constructs an instance for the device and queue, with a fence, but without actual command buffers. */
|
/** Constructs an instance for the queue, with a fence, but without actual command buffers. */
|
||||||
MVKQueueCommandBufferSubmission(MVKDevice* device, MVKQueue* queue, VkFence fence);
|
MVKQueueCommandBufferSubmission(MVKQueue* queue, VkFence fence);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend MVKCommandBuffer;
|
friend MVKCommandBuffer;
|
||||||
@ -222,9 +230,7 @@ class MVKQueuePresentSurfaceSubmission : public MVKQueueSubmission {
|
|||||||
public:
|
public:
|
||||||
void execute() override;
|
void execute() override;
|
||||||
|
|
||||||
/** Constructs an instance for the device and queue. */
|
MVKQueuePresentSurfaceSubmission(MVKQueue* queue,
|
||||||
MVKQueuePresentSurfaceSubmission(MVKDevice* device,
|
|
||||||
MVKQueue* queue,
|
|
||||||
const VkPresentInfoKHR* pPresentInfo);
|
const VkPresentInfoKHR* pPresentInfo);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -74,7 +74,7 @@ static inline void execute(MVKQueueSubmission* qSubmit) { @autoreleasepool { qSu
|
|||||||
VkResult MVKQueue::submit(MVKQueueSubmission* qSubmit) {
|
VkResult MVKQueue::submit(MVKQueueSubmission* qSubmit) {
|
||||||
if ( !qSubmit ) { return VK_SUCCESS; } // Ignore nils
|
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) {
|
if (_execQueue) {
|
||||||
dispatch_async(_execQueue, ^{ execute(qSubmit); } );
|
dispatch_async(_execQueue, ^{ execute(qSubmit); } );
|
||||||
} else {
|
} else {
|
||||||
@ -88,20 +88,20 @@ VkResult MVKQueue::submit(uint32_t submitCount, const VkSubmitInfo* pSubmits,
|
|||||||
|
|
||||||
// Fence-only submission
|
// Fence-only submission
|
||||||
if (submitCount == 0 && fence) {
|
if (submitCount == 0 && fence) {
|
||||||
return submit(new MVKQueueCommandBufferSubmission(_device, this, VK_NULL_HANDLE, fence, cmdBuffUse));
|
return submit(new MVKQueueCommandBufferSubmission(this, VK_NULL_HANDLE, fence, cmdBuffUse));
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult rslt = VK_SUCCESS;
|
VkResult rslt = VK_SUCCESS;
|
||||||
for (uint32_t sIdx = 0; sIdx < submitCount; sIdx++) {
|
for (uint32_t sIdx = 0; sIdx < submitCount; sIdx++) {
|
||||||
VkFence fenceOrNil = (sIdx == (submitCount - 1)) ? fence : VK_NULL_HANDLE; // last one gets the fence
|
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; }
|
if (rslt == VK_SUCCESS) { rslt = subRslt; }
|
||||||
}
|
}
|
||||||
return rslt;
|
return rslt;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult MVKQueue::submit(const VkPresentInfoKHR* pPresentInfo) {
|
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.
|
// Create an empty submit struct and fence, submit to queue and wait on fence.
|
||||||
@ -127,7 +127,7 @@ VkResult MVKQueue::waitIdle(MVKCommandUse cmdBuffUse) {
|
|||||||
MVKFence mvkFence(_device, &vkFenceInfo);
|
MVKFence mvkFence(_device, &vkFenceInfo);
|
||||||
VkFence fence = (VkFence)&mvkFence;
|
VkFence fence = (VkFence)&mvkFence;
|
||||||
submit(1, &vkSbmtInfo, fence, cmdBuffUse);
|
submit(1, &vkSbmtInfo, fence, cmdBuffUse);
|
||||||
return mvkWaitForFences(1, &fence, false);
|
return mvkWaitForFences(_device, 1, &fence, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ VkResult MVKQueue::waitIdle(MVKCommandUse cmdBuffUse) {
|
|||||||
#define MVK_DISPATCH_QUEUE_QOS_CLASS QOS_CLASS_USER_INITIATED
|
#define MVK_DISPATCH_QUEUE_QOS_CLASS QOS_CLASS_USER_INITIATED
|
||||||
|
|
||||||
MVKQueue::MVKQueue(MVKDevice* device, MVKQueueFamily* queueFamily, uint32_t index, float priority)
|
MVKQueue::MVKQueue(MVKDevice* device, MVKQueueFamily* queueFamily, uint32_t index, float priority)
|
||||||
: MVKDispatchableDeviceObject(device) {
|
: MVKDeviceTrackingMixin(device) {
|
||||||
|
|
||||||
_queueFamily = queueFamily;
|
_queueFamily = queueFamily;
|
||||||
_index = index;
|
_index = index;
|
||||||
@ -178,7 +178,7 @@ void MVKQueue::initMTLCommandQueue() {
|
|||||||
|
|
||||||
// Initializes Xcode GPU capture scopes
|
// Initializes Xcode GPU capture scopes
|
||||||
void MVKQueue::initGPUCaptureScopes() {
|
void MVKQueue::initGPUCaptureScopes() {
|
||||||
const MVKConfiguration* pMVKConfig = _device->getInstance()->getMoltenVKConfiguration();
|
const MVKConfiguration* pMVKConfig = getInstance()->getMoltenVKConfiguration();
|
||||||
|
|
||||||
_submissionCaptureScope = new MVKGPUCaptureScope(this, "CommandBuffer-Submission");
|
_submissionCaptureScope = new MVKGPUCaptureScope(this, "CommandBuffer-Submission");
|
||||||
|
|
||||||
@ -208,14 +208,12 @@ void MVKQueue::destroyExecQueue() {
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKQueueSubmission
|
#pragma mark MVKQueueSubmission
|
||||||
|
|
||||||
MVKQueueSubmission::MVKQueueSubmission(MVKDevice* device,
|
MVKQueueSubmission::MVKQueueSubmission(MVKQueue* queue,
|
||||||
MVKQueue* queue,
|
|
||||||
uint32_t waitSemaphoreCount,
|
uint32_t waitSemaphoreCount,
|
||||||
const VkSemaphore* pWaitSemaphores) : MVKBaseDeviceObject(device) {
|
const VkSemaphore* pWaitSemaphores) {
|
||||||
_queue = queue;
|
_queue = queue;
|
||||||
_prev = VK_NULL_HANDLE;
|
_prev = VK_NULL_HANDLE;
|
||||||
_next = VK_NULL_HANDLE;
|
_next = VK_NULL_HANDLE;
|
||||||
_submissionResult = VK_SUCCESS;
|
|
||||||
|
|
||||||
_isAwaitingSemaphores = waitSemaphoreCount > 0;
|
_isAwaitingSemaphores = waitSemaphoreCount > 0;
|
||||||
_waitSemaphores.reserve(waitSemaphoreCount);
|
_waitSemaphores.reserve(waitSemaphoreCount);
|
||||||
@ -224,10 +222,6 @@ MVKQueueSubmission::MVKQueueSubmission(MVKDevice* device,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKQueueSubmission::recordResult(VkResult vkResult) {
|
|
||||||
if (_submissionResult == VK_SUCCESS) { _submissionResult = vkResult; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKQueueCommandBufferSubmission
|
#pragma mark MVKQueueCommandBufferSubmission
|
||||||
@ -308,13 +302,11 @@ void MVKQueueCommandBufferSubmission::finish() {
|
|||||||
this->destroy();
|
this->destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKQueueCommandBufferSubmission::MVKQueueCommandBufferSubmission(MVKDevice* device,
|
MVKQueueCommandBufferSubmission::MVKQueueCommandBufferSubmission(MVKQueue* queue,
|
||||||
MVKQueue* queue,
|
|
||||||
const VkSubmitInfo* pSubmit,
|
const VkSubmitInfo* pSubmit,
|
||||||
VkFence fence,
|
VkFence fence,
|
||||||
MVKCommandUse cmdBuffUse)
|
MVKCommandUse cmdBuffUse)
|
||||||
: MVKQueueSubmission(device,
|
: MVKQueueSubmission(queue,
|
||||||
queue,
|
|
||||||
(pSubmit ? pSubmit->waitSemaphoreCount : 0),
|
(pSubmit ? pSubmit->waitSemaphoreCount : 0),
|
||||||
(pSubmit ? pSubmit->pWaitSemaphores : nullptr)) {
|
(pSubmit ? pSubmit->pWaitSemaphores : nullptr)) {
|
||||||
|
|
||||||
@ -325,7 +317,7 @@ MVKQueueCommandBufferSubmission::MVKQueueCommandBufferSubmission(MVKDevice* devi
|
|||||||
for (uint32_t i = 0; i < cbCnt; i++) {
|
for (uint32_t i = 0; i < cbCnt; i++) {
|
||||||
MVKCommandBuffer* cb = MVKCommandBuffer::getMVKCommandBuffer(pSubmit->pCommandBuffers[i]);
|
MVKCommandBuffer* cb = MVKCommandBuffer::getMVKCommandBuffer(pSubmit->pCommandBuffers[i]);
|
||||||
_cmdBuffers.push_back(cb);
|
_cmdBuffers.push_back(cb);
|
||||||
recordResult(cb->getRecordingResult());
|
setConfigurationResult(cb->getConfigurationResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ssCnt = pSubmit->signalSemaphoreCount;
|
uint32_t ssCnt = pSubmit->signalSemaphoreCount;
|
||||||
@ -352,7 +344,8 @@ MVKQueueCommandBufferSubmission::MVKQueueCommandBufferSubmission(MVKDevice* devi
|
|||||||
void MVKQueuePresentSurfaceSubmission::execute() {
|
void MVKQueuePresentSurfaceSubmission::execute() {
|
||||||
id<MTLCommandQueue> mtlQ = _queue->getMTLCommandQueue();
|
id<MTLCommandQueue> mtlQ = _queue->getMTLCommandQueue();
|
||||||
|
|
||||||
if (_device->_pMVKConfig->presentWithCommandBuffer || _device->_pMVKConfig->displayWatermark) {
|
MVKDevice* mvkDev = _queue->getDevice();
|
||||||
|
if (mvkDev->_pMVKConfig->presentWithCommandBuffer || mvkDev->_pMVKConfig->displayWatermark) {
|
||||||
// Create a command buffer, present surfaces via the command buffer,
|
// Create a command buffer, present surfaces via the command buffer,
|
||||||
// then wait on the semaphores before committing.
|
// then wait on the semaphores before committing.
|
||||||
id<MTLCommandBuffer> mtlCmdBuff = [mtlQ commandBufferWithUnretainedReferences];
|
id<MTLCommandBuffer> mtlCmdBuff = [mtlQ commandBufferWithUnretainedReferences];
|
||||||
@ -377,13 +370,9 @@ void MVKQueuePresentSurfaceSubmission::execute() {
|
|||||||
this->destroy();
|
this->destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKQueuePresentSurfaceSubmission::MVKQueuePresentSurfaceSubmission(MVKDevice* device,
|
MVKQueuePresentSurfaceSubmission::MVKQueuePresentSurfaceSubmission(MVKQueue* queue,
|
||||||
MVKQueue* queue,
|
|
||||||
const VkPresentInfoKHR* pPresentInfo)
|
const VkPresentInfoKHR* pPresentInfo)
|
||||||
: MVKQueueSubmission(device,
|
: MVKQueueSubmission(queue, pPresentInfo->waitSemaphoreCount, pPresentInfo->pWaitSemaphores) {
|
||||||
queue,
|
|
||||||
pPresentInfo->waitSemaphoreCount,
|
|
||||||
pPresentInfo->pWaitSemaphores) {
|
|
||||||
|
|
||||||
// Populate the array of swapchain images, testing each one for a change in surface size
|
// Populate the array of swapchain images, testing each one for a change in surface size
|
||||||
_surfaceImages.reserve(pPresentInfo->swapchainCount);
|
_surfaceImages.reserve(pPresentInfo->swapchainCount);
|
||||||
@ -392,9 +381,9 @@ MVKQueuePresentSurfaceSubmission::MVKQueuePresentSurfaceSubmission(MVKDevice* de
|
|||||||
_surfaceImages.push_back(mvkSC->getImage(pPresentInfo->pImageIndices[i]));
|
_surfaceImages.push_back(mvkSC->getImage(pPresentInfo->pImageIndices[i]));
|
||||||
// Surface loss takes precedence over out-of-date errors.
|
// Surface loss takes precedence over out-of-date errors.
|
||||||
if (mvkSC->getIsSurfaceLost()) {
|
if (mvkSC->getIsSurfaceLost()) {
|
||||||
_submissionResult = VK_ERROR_SURFACE_LOST_KHR;
|
setConfigurationResult(VK_ERROR_SURFACE_LOST_KHR);
|
||||||
} else if (mvkSC->getHasSurfaceSizeChanged() && _submissionResult != VK_ERROR_SURFACE_LOST_KHR) {
|
} else if (mvkSC->getHasSurfaceSizeChanged() && getConfigurationResult() != VK_ERROR_SURFACE_LOST_KHR) {
|
||||||
_submissionResult = VK_ERROR_OUT_OF_DATE_KHR;
|
setConfigurationResult(VK_ERROR_OUT_OF_DATE_KHR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,10 @@ class MVKRenderSubpass : public MVKBaseObject {
|
|||||||
|
|
||||||
public:
|
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. */
|
/** Returns the number of color attachments, which may be zero for depth-only rendering. */
|
||||||
inline uint32_t getColorAttachmentCount() { return uint32_t(_colorAttachments.size()); }
|
inline uint32_t getColorAttachmentCount() { return uint32_t(_colorAttachments.size()); }
|
||||||
|
|
||||||
@ -97,7 +101,9 @@ private:
|
|||||||
class MVKRenderPassAttachment : public MVKBaseObject {
|
class MVKRenderPassAttachment : public MVKBaseObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
friend MVKRenderSubpass;
|
|
||||||
|
/** Returns the Vulkan API opaque object controlling this object. */
|
||||||
|
MVKVulkanAPIObject* getVulkanAPIObject() override;
|
||||||
|
|
||||||
/** Returns the Vulkan format of this attachment. */
|
/** Returns the Vulkan format of this attachment. */
|
||||||
VkFormat getFormat();
|
VkFormat getFormat();
|
||||||
@ -137,10 +143,13 @@ protected:
|
|||||||
#pragma mark MVKRenderPass
|
#pragma mark MVKRenderPass
|
||||||
|
|
||||||
/** Represents a Vulkan render pass. */
|
/** Represents a Vulkan render pass. */
|
||||||
class MVKRenderPass : public MVKBaseDeviceObject {
|
class MVKRenderPass : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Returns the granularity of the render area of this instance. */
|
||||||
VkExtent2D getRenderAreaGranularity();
|
VkExtent2D getRenderAreaGranularity();
|
||||||
|
|
||||||
@ -150,7 +159,7 @@ public:
|
|||||||
/** Constructs an instance for the specified device. */
|
/** Constructs an instance for the specified device. */
|
||||||
MVKRenderPass(MVKDevice* device, const VkRenderPassCreateInfo* pCreateInfo);
|
MVKRenderPass(MVKDevice* device, const VkRenderPassCreateInfo* pCreateInfo);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
|
||||||
friend class MVKRenderSubpass;
|
friend class MVKRenderSubpass;
|
||||||
friend class MVKRenderPassAttachment;
|
friend class MVKRenderPassAttachment;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "MVKFramebuffer.h"
|
#include "MVKFramebuffer.h"
|
||||||
#include "MVKCommandBuffer.h"
|
#include "MVKCommandBuffer.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "mvk_datatypes.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -28,6 +28,8 @@ using namespace std;
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKRenderSubpass
|
#pragma mark MVKRenderSubpass
|
||||||
|
|
||||||
|
MVKVulkanAPIObject* MVKRenderSubpass::getVulkanAPIObject() { return _renderPass->getVulkanAPIObject(); };
|
||||||
|
|
||||||
VkFormat MVKRenderSubpass::getColorAttachmentFormat(uint32_t colorAttIdx) {
|
VkFormat MVKRenderSubpass::getColorAttachmentFormat(uint32_t colorAttIdx) {
|
||||||
if (colorAttIdx < _colorAttachments.size()) {
|
if (colorAttIdx < _colorAttachments.size()) {
|
||||||
uint32_t rpAttIdx = _colorAttachments[colorAttIdx].attachment;
|
uint32_t rpAttIdx = _colorAttachments[colorAttIdx].attachment;
|
||||||
@ -213,7 +215,7 @@ bool MVKRenderSubpass::isUsingAttachmentAt(uint32_t rpAttIdx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass,
|
MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass,
|
||||||
const VkSubpassDescription* pCreateInfo) : MVKBaseObject() {
|
const VkSubpassDescription* pCreateInfo) {
|
||||||
_renderPass = renderPass;
|
_renderPass = renderPass;
|
||||||
_subpassIndex = (uint32_t)_renderPass->_subpasses.size();
|
_subpassIndex = (uint32_t)_renderPass->_subpasses.size();
|
||||||
|
|
||||||
@ -251,6 +253,8 @@ MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass,
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKRenderPassAttachment
|
#pragma mark MVKRenderPassAttachment
|
||||||
|
|
||||||
|
MVKVulkanAPIObject* MVKRenderPassAttachment::getVulkanAPIObject() { return _renderPass->getVulkanAPIObject(); };
|
||||||
|
|
||||||
VkFormat MVKRenderPassAttachment::getFormat() { return _info.format; }
|
VkFormat MVKRenderPassAttachment::getFormat() { return _info.format; }
|
||||||
|
|
||||||
VkSampleCountFlagBits MVKRenderPassAttachment::getSampleCount() { return _info.samples; }
|
VkSampleCountFlagBits MVKRenderPassAttachment::getSampleCount() { return _info.samples; }
|
||||||
@ -302,7 +306,7 @@ bool MVKRenderPassAttachment::shouldUseClearAttachment(MVKRenderSubpass* subpass
|
|||||||
}
|
}
|
||||||
|
|
||||||
MVKRenderPassAttachment::MVKRenderPassAttachment(MVKRenderPass* renderPass,
|
MVKRenderPassAttachment::MVKRenderPassAttachment(MVKRenderPass* renderPass,
|
||||||
const VkAttachmentDescription* pCreateInfo) : MVKBaseObject() {
|
const VkAttachmentDescription* pCreateInfo) {
|
||||||
_renderPass = renderPass;
|
_renderPass = renderPass;
|
||||||
_attachmentIndex = uint32_t(_renderPass->_attachments.size());
|
_attachmentIndex = uint32_t(_renderPass->_attachments.size());
|
||||||
|
|
||||||
@ -329,7 +333,7 @@ VkExtent2D MVKRenderPass::getRenderAreaGranularity() { return { 1, 1 }; }
|
|||||||
MVKRenderSubpass* MVKRenderPass::getSubpass(uint32_t subpassIndex) { return &_subpasses[subpassIndex]; }
|
MVKRenderSubpass* MVKRenderPass::getSubpass(uint32_t subpassIndex) { return &_subpasses[subpassIndex]; }
|
||||||
|
|
||||||
MVKRenderPass::MVKRenderPass(MVKDevice* device,
|
MVKRenderPass::MVKRenderPass(MVKDevice* device,
|
||||||
const VkRenderPassCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
|
const VkRenderPassCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {
|
||||||
|
|
||||||
// Add subpasses and dependencies first
|
// Add subpasses and dependencies first
|
||||||
_subpasses.reserve(pCreateInfo->subpassCount);
|
_subpasses.reserve(pCreateInfo->subpassCount);
|
||||||
|
@ -28,7 +28,7 @@ class MVKCommandEncoder;
|
|||||||
#pragma mark MVKResource
|
#pragma mark MVKResource
|
||||||
|
|
||||||
/** Represents an abstract Vulkan resource. Specialized subclasses include MVKBuffer and MVKImage. */
|
/** Represents an abstract Vulkan resource. Specialized subclasses include MVKBuffer and MVKImage. */
|
||||||
class MVKResource : public MVKRefCountedDeviceObject {
|
class MVKResource : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ public:
|
|||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKResource(MVKDevice* device) : MVKRefCountedDeviceObject(device) {}
|
MVKResource(MVKDevice* device) : MVKVulkanAPIDeviceObject(device) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool needsHostReadSync(VkPipelineStageFlags srcStageMask,
|
virtual bool needsHostReadSync(VkPipelineStageFlags srcStageMask,
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "MVKResource.h"
|
#include "MVKResource.h"
|
||||||
#include "MVKCommandBuffer.h"
|
#include "MVKCommandBuffer.h"
|
||||||
|
#include "MVKEnvironment.h"
|
||||||
|
|
||||||
|
|
||||||
struct MVKBindDeviceMemoryInfo {
|
struct MVKBindDeviceMemoryInfo {
|
||||||
|
@ -45,17 +45,23 @@ typedef struct {
|
|||||||
extern const MVKMTLFunction MVKMTLFunctionNull;
|
extern const MVKMTLFunction MVKMTLFunctionNull;
|
||||||
|
|
||||||
/** Wraps a single MTLLibrary. */
|
/** Wraps a single MTLLibrary. */
|
||||||
class MVKShaderLibrary : public MVKBaseDeviceObject {
|
class MVKShaderLibrary : public MVKBaseObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** Returns the Vulkan API opaque object controlling this object. */
|
||||||
|
MVKVulkanAPIObject* getVulkanAPIObject() override { return _owner->getVulkanAPIObject(); };
|
||||||
|
|
||||||
/** Returns the Metal shader function, possibly specialized. */
|
/** Returns the Metal shader function, possibly specialized. */
|
||||||
MVKMTLFunction getMTLFunction(const VkSpecializationInfo* pSpecializationInfo);
|
MVKMTLFunction getMTLFunction(const VkSpecializationInfo* pSpecializationInfo);
|
||||||
|
|
||||||
/** Constructs an instance from the specified MSL source code. */
|
/** 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. */
|
/** Constructs an instance from the specified compiled MSL code data. */
|
||||||
MVKShaderLibrary(MVKDevice* device,
|
MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner,
|
||||||
const void* mslCompiledCodeData,
|
const void* mslCompiledCodeData,
|
||||||
size_t mslCompiledCodeLength);
|
size_t mslCompiledCodeLength);
|
||||||
|
|
||||||
@ -70,6 +76,7 @@ protected:
|
|||||||
void handleCompilationError(NSError* err, const char* opDesc);
|
void handleCompilationError(NSError* err, const char* opDesc);
|
||||||
MTLFunctionConstant* getFunctionConstant(NSArray<MTLFunctionConstant*>* mtlFCs, NSUInteger mtlFCID);
|
MTLFunctionConstant* getFunctionConstant(NSArray<MTLFunctionConstant*>* mtlFCs, NSUInteger mtlFCID);
|
||||||
|
|
||||||
|
MVKVulkanAPIDeviceObject* _owner;
|
||||||
id<MTLLibrary> _mtlLibrary;
|
id<MTLLibrary> _mtlLibrary;
|
||||||
SPIRVEntryPoint _entryPoint;
|
SPIRVEntryPoint _entryPoint;
|
||||||
std::string _msl;
|
std::string _msl;
|
||||||
@ -80,10 +87,13 @@ protected:
|
|||||||
#pragma mark MVKShaderLibraryCache
|
#pragma mark MVKShaderLibraryCache
|
||||||
|
|
||||||
/** Represents a cache of shader libraries for one shader module. */
|
/** Represents a cache of shader libraries for one shader module. */
|
||||||
class MVKShaderLibraryCache : public MVKBaseDeviceObject {
|
class MVKShaderLibraryCache : public MVKBaseObject {
|
||||||
|
|
||||||
public:
|
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,
|
* 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.
|
* lazily creating the shader library from source code in the shader module, if needed.
|
||||||
@ -95,7 +105,7 @@ public:
|
|||||||
MVKShaderModule* shaderModule,
|
MVKShaderModule* shaderModule,
|
||||||
bool* pWasAdded = nullptr);
|
bool* pWasAdded = nullptr);
|
||||||
|
|
||||||
MVKShaderLibraryCache(MVKDevice* device) : MVKBaseDeviceObject(device) {};
|
MVKShaderLibraryCache(MVKVulkanAPIDeviceObject* owner) : _owner(owner) {};
|
||||||
|
|
||||||
~MVKShaderLibraryCache() override;
|
~MVKShaderLibraryCache() override;
|
||||||
|
|
||||||
@ -109,6 +119,7 @@ protected:
|
|||||||
const SPIRVEntryPoint& entryPoint);
|
const SPIRVEntryPoint& entryPoint);
|
||||||
void merge(MVKShaderLibraryCache* other);
|
void merge(MVKShaderLibraryCache* other);
|
||||||
|
|
||||||
|
MVKVulkanAPIDeviceObject* _owner;
|
||||||
std::mutex _accessLock;
|
std::mutex _accessLock;
|
||||||
std::vector<std::pair<SPIRVToMSLConverterContext, MVKShaderLibrary*>> _shaderLibraries;
|
std::vector<std::pair<SPIRVToMSLConverterContext, MVKShaderLibrary*>> _shaderLibraries;
|
||||||
};
|
};
|
||||||
@ -140,9 +151,13 @@ namespace std {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Represents a Vulkan shader module. */
|
/** Represents a Vulkan shader module. */
|
||||||
class MVKShaderModule : public MVKBaseDeviceObject {
|
class MVKShaderModule : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Returns the Metal shader function, possibly specialized. */
|
||||||
MVKMTLFunction getMTLFunction(SPIRVToMSLConverterContext* pContext,
|
MVKMTLFunction getMTLFunction(SPIRVToMSLConverterContext* pContext,
|
||||||
const VkSpecializationInfo* pSpecializationInfo,
|
const VkSpecializationInfo* pSpecializationInfo,
|
||||||
@ -207,9 +222,9 @@ public:
|
|||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKShaderLibraryCompiler(MVKDevice* device) : MVKMetalCompiler(device) {
|
MVKShaderLibraryCompiler(MVKVulkanAPIDeviceObject* owner) : MVKMetalCompiler(owner) {
|
||||||
_compilerType = "Shader library";
|
_compilerType = "Shader library";
|
||||||
_pPerformanceTracker = &_device->_performanceStatistics.shaderCompilation.mslCompile;
|
_pPerformanceTracker = &_owner->getDevice()->_performanceStatistics.shaderCompilation.mslCompile;
|
||||||
}
|
}
|
||||||
|
|
||||||
~MVKShaderLibraryCompiler() override;
|
~MVKShaderLibraryCompiler() override;
|
||||||
@ -245,9 +260,9 @@ public:
|
|||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKFunctionSpecializer(MVKDevice* device) : MVKMetalCompiler(device) {
|
MVKFunctionSpecializer(MVKVulkanAPIDeviceObject* owner) : MVKMetalCompiler(owner) {
|
||||||
_compilerType = "Function specialization";
|
_compilerType = "Function specialization";
|
||||||
_pPerformanceTracker = &_device->_performanceStatistics.shaderCompilation.functionSpecialization;
|
_pPerformanceTracker = &_owner->getDevice()->_performanceStatistics.shaderCompilation.functionSpecialization;
|
||||||
}
|
}
|
||||||
|
|
||||||
~MVKFunctionSpecializer() override;
|
~MVKFunctionSpecializer() override;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "MVKShaderModule.h"
|
#include "MVKShaderModule.h"
|
||||||
#include "MVKPipeline.h"
|
#include "MVKPipeline.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
|
#include "MVKLogging.h"
|
||||||
#include "vk_mvk_moltenvk.h"
|
#include "vk_mvk_moltenvk.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -53,15 +54,17 @@ MVKMTLFunction MVKShaderLibrary::getMTLFunction(const VkSpecializationInfo* pSpe
|
|||||||
// as a function name), and retrieve the unspecialized Metal function with that name.
|
// as a function name), and retrieve the unspecialized Metal function with that name.
|
||||||
NSString* mtlFuncName = @(_entryPoint.mtlFunctionName.c_str());
|
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];
|
id<MTLFunction> mtlFunc = [[_mtlLibrary newFunctionWithName: mtlFuncName] autorelease];
|
||||||
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
|
mvkDev->addActivityPerformance(mvkDev->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
|
||||||
|
|
||||||
if (mtlFunc) {
|
if (mtlFunc) {
|
||||||
// If the Metal device supports shader specialization, and the Metal function expects to be
|
// 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,
|
// specialized, populate Metal function constant values from the Vulkan specialization info,
|
||||||
// and compiled a specialized Metal function, otherwise simply use the unspecialized Metal function.
|
// 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;
|
NSArray<MTLFunctionConstant*>* mtlFCs = mtlFunc.functionConstantsDictionary.allValues;
|
||||||
if (mtlFCs.count) {
|
if (mtlFCs.count) {
|
||||||
// The Metal shader contains function constants and expects to be specialized
|
// The Metal shader contains function constants and expects to be specialized
|
||||||
@ -83,14 +86,13 @@ MVKMTLFunction MVKShaderLibrary::getMTLFunction(const VkSpecializationInfo* pSpe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compile the specialized Metal function, and use it instead of the unspecialized Metal function.
|
// 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];
|
mtlFunc = [fs->newMTLFunction(_mtlLibrary, mtlFuncName, mtlFCVals) autorelease];
|
||||||
setConfigurationResult(fs->getConfigurationResult());
|
|
||||||
fs->destroy();
|
fs->destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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),
|
return { mtlFunc, MTLSizeMake(getWorkgroupDimensionSize(_entryPoint.workgroupSize.width, pSpecializationInfo),
|
||||||
@ -106,34 +108,34 @@ MTLFunctionConstant* MVKShaderLibrary::getFunctionConstant(NSArray<MTLFunctionCo
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKShaderLibrary::MVKShaderLibrary(MVKDevice* device, const string& mslSourceCode, const SPIRVEntryPoint& entryPoint) : MVKBaseDeviceObject(device) {
|
MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner, const string& mslSourceCode, const SPIRVEntryPoint& entryPoint) : _owner(owner) {
|
||||||
MVKShaderLibraryCompiler* slc = new MVKShaderLibraryCompiler(_device);
|
MVKShaderLibraryCompiler* slc = new MVKShaderLibraryCompiler(_owner);
|
||||||
_mtlLibrary = slc->newMTLLibrary(@(mslSourceCode.c_str())); // retained
|
_mtlLibrary = slc->newMTLLibrary(@(mslSourceCode.c_str())); // retained
|
||||||
setConfigurationResult(slc->getConfigurationResult());
|
|
||||||
slc->destroy();
|
slc->destroy();
|
||||||
|
|
||||||
_entryPoint = entryPoint;
|
_entryPoint = entryPoint;
|
||||||
_msl = mslSourceCode;
|
_msl = mslSourceCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKShaderLibrary::MVKShaderLibrary(MVKDevice* device,
|
MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner,
|
||||||
const void* mslCompiledCodeData,
|
const void* mslCompiledCodeData,
|
||||||
size_t mslCompiledCodeLength) : MVKBaseDeviceObject(device) {
|
size_t mslCompiledCodeLength) : _owner(owner) {
|
||||||
uint64_t startTime = _device->getPerformanceTimestamp();
|
MVKDevice* mvkDev = _owner->getDevice();
|
||||||
|
uint64_t startTime = mvkDev->getPerformanceTimestamp();
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
dispatch_data_t shdrData = dispatch_data_create(mslCompiledCodeData,
|
dispatch_data_t shdrData = dispatch_data_create(mslCompiledCodeData,
|
||||||
mslCompiledCodeLength,
|
mslCompiledCodeLength,
|
||||||
NULL,
|
NULL,
|
||||||
DISPATCH_DATA_DESTRUCTOR_DEFAULT);
|
DISPATCH_DATA_DESTRUCTOR_DEFAULT);
|
||||||
NSError* err = nil;
|
NSError* err = nil;
|
||||||
_mtlLibrary = [getMTLDevice() newLibraryWithData: shdrData error: &err]; // retained
|
_mtlLibrary = [mvkDev->getMTLDevice() newLibraryWithData: shdrData error: &err]; // retained
|
||||||
handleCompilationError(err, "Compiled shader module creation");
|
handleCompilationError(err, "Compiled shader module creation");
|
||||||
[shdrData release];
|
[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];
|
_mtlLibrary = [other._mtlLibrary retain];
|
||||||
_entryPoint = other._entryPoint;
|
_entryPoint = other._entryPoint;
|
||||||
_msl = other._msl;
|
_msl = other._msl;
|
||||||
@ -148,7 +150,7 @@ void MVKShaderLibrary::handleCompilationError(NSError* err, const char* opDesc)
|
|||||||
if (_mtlLibrary) {
|
if (_mtlLibrary) {
|
||||||
MVKLogInfo("%s succeeded with warnings (Error code %li):\n%s", opDesc, (long)err.code, err.localizedDescription.UTF8String);
|
MVKLogInfo("%s succeeded with warnings (Error code %li):\n%s", opDesc, (long)err.code, err.localizedDescription.UTF8String);
|
||||||
} else {
|
} else {
|
||||||
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED,
|
_owner->setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED,
|
||||||
"%s failed (Error code %li):\n%s",
|
"%s failed (Error code %li):\n%s",
|
||||||
opDesc, (long)err.code,
|
opDesc, (long)err.code,
|
||||||
err.localizedDescription.UTF8String));
|
err.localizedDescription.UTF8String));
|
||||||
@ -196,7 +198,7 @@ MVKShaderLibrary* MVKShaderLibraryCache::findShaderLibrary(SPIRVToMSLConverterCo
|
|||||||
MVKShaderLibrary* MVKShaderLibraryCache::addShaderLibrary(SPIRVToMSLConverterContext* pContext,
|
MVKShaderLibrary* MVKShaderLibraryCache::addShaderLibrary(SPIRVToMSLConverterContext* pContext,
|
||||||
const string& mslSourceCode,
|
const string& mslSourceCode,
|
||||||
const SPIRVEntryPoint& entryPoint) {
|
const SPIRVEntryPoint& entryPoint) {
|
||||||
MVKShaderLibrary* shLib = new MVKShaderLibrary(_device, mslSourceCode, entryPoint);
|
MVKShaderLibrary* shLib = new MVKShaderLibrary(_owner, mslSourceCode, entryPoint);
|
||||||
_shaderLibraries.emplace_back(*pContext, shLib);
|
_shaderLibraries.emplace_back(*pContext, shLib);
|
||||||
return shLib;
|
return shLib;
|
||||||
}
|
}
|
||||||
@ -250,7 +252,7 @@ bool MVKShaderModule::convert(SPIRVToMSLConverterContext* pContext) {
|
|||||||
if (wasConverted) {
|
if (wasConverted) {
|
||||||
if (shouldLogCode) { MVKLogInfo("%s", _converter.getResultLog().data()); }
|
if (shouldLogCode) { MVKLogInfo("%s", _converter.getResultLog().data()); }
|
||||||
} else {
|
} 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;
|
return wasConverted;
|
||||||
}
|
}
|
||||||
@ -259,7 +261,7 @@ bool MVKShaderModule::convert(SPIRVToMSLConverterContext* pContext) {
|
|||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKShaderModule::MVKShaderModule(MVKDevice* device,
|
MVKShaderModule::MVKShaderModule(MVKDevice* device,
|
||||||
const VkShaderModuleCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device), _shaderLibraryCache(device) {
|
const VkShaderModuleCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device), _shaderLibraryCache(this) {
|
||||||
|
|
||||||
_defaultLibrary = nullptr;
|
_defaultLibrary = nullptr;
|
||||||
|
|
||||||
@ -268,7 +270,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
|
|||||||
|
|
||||||
// Ensure something is there.
|
// Ensure something is there.
|
||||||
if ( (pCreateInfo->pCode == VK_NULL_HANDLE) || (codeSize < 4) ) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,7 +301,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
|
|||||||
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
|
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
|
||||||
|
|
||||||
_converter.setMSL(pMSLCode, nullptr);
|
_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;
|
break;
|
||||||
}
|
}
|
||||||
@ -313,12 +315,12 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
|
|||||||
codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash);
|
codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash);
|
||||||
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
|
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
|
||||||
|
|
||||||
_defaultLibrary = new MVKShaderLibrary(_device, (void*)(pMSLCode), mslCodeLen);
|
_defaultLibrary = new MVKShaderLibrary(this, (void*)(pMSLCode), mslCodeLen);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,8 +339,8 @@ id<MTLLibrary> MVKShaderLibraryCompiler::newMTLLibrary(NSString* mslSourceCode)
|
|||||||
unique_lock<mutex> lock(_completionLock);
|
unique_lock<mutex> lock(_completionLock);
|
||||||
|
|
||||||
compile(lock, ^{
|
compile(lock, ^{
|
||||||
[getMTLDevice() newLibraryWithSource: mslSourceCode
|
[_owner->getMTLDevice() newLibraryWithSource: mslSourceCode
|
||||||
options: getDevice()->getMTLCompileOptions()
|
options: _owner->getDevice()->getMTLCompileOptions()
|
||||||
completionHandler: ^(id<MTLLibrary> mtlLib, NSError* error) {
|
completionHandler: ^(id<MTLLibrary> mtlLib, NSError* error) {
|
||||||
bool isLate = compileComplete(mtlLib, error);
|
bool isLate = compileComplete(mtlLib, error);
|
||||||
if (isLate) { destroy(); }
|
if (isLate) { destroy(); }
|
||||||
|
@ -18,29 +18,23 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "mvk_vulkan.h"
|
|
||||||
#include "MVKBaseObject.h"
|
#include "MVKBaseObject.h"
|
||||||
|
#include "MVKEnvironment.h"
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#import <Metal/Metal.h>
|
||||||
|
#import <QuartzCore/CAMetalLayer.h>
|
||||||
|
|
||||||
// Expose MoltenVK Apple surface extension functionality
|
|
||||||
#ifdef VK_USE_PLATFORM_IOS_MVK
|
#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>
|
# import <UIKit/UIView.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VK_USE_PLATFORM_MACOS_MVK
|
#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>
|
# import <AppKit/NSView.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
|
||||||
#import <QuartzCore/CAMetalLayer.h>
|
|
||||||
|
|
||||||
class MVKInstance;
|
class MVKInstance;
|
||||||
|
|
||||||
@class MVKBlockObserver;
|
@class MVKBlockObserver;
|
||||||
@ -49,10 +43,16 @@ class MVKInstance;
|
|||||||
#pragma mark MVKSurface
|
#pragma mark MVKSurface
|
||||||
|
|
||||||
/** Represents a Vulkan WSI surface. */
|
/** Represents a Vulkan WSI surface. */
|
||||||
class MVKSurface : public MVKConfigurableObject {
|
class MVKSurface : public MVKVulkanAPIObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Returns the CAMetalLayer underlying this surface. */
|
||||||
inline CAMetalLayer* getCAMetalLayer() {
|
inline CAMetalLayer* getCAMetalLayer() {
|
||||||
std::lock_guard<std::mutex> lock(_lock);
|
std::lock_guard<std::mutex> lock(_lock);
|
||||||
@ -69,6 +69,7 @@ public:
|
|||||||
~MVKSurface() override;
|
~MVKSurface() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
MVKInstance* _mvkInstance;
|
||||||
CAMetalLayer* _mtlCAMetalLayer;
|
CAMetalLayer* _mtlCAMetalLayer;
|
||||||
std::mutex _lock;
|
std::mutex _lock;
|
||||||
MVKBlockObserver* _layerObserver;
|
MVKBlockObserver* _layerObserver;
|
||||||
|
@ -19,30 +19,19 @@
|
|||||||
#include "MVKSurface.h"
|
#include "MVKSurface.h"
|
||||||
#include "MVKInstance.h"
|
#include "MVKInstance.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
|
#include "MVKLogging.h"
|
||||||
#include "MVKOSExtensions.h"
|
#include "MVKOSExtensions.h"
|
||||||
#import "MVKBlockObserver.h"
|
#import "MVKBlockObserver.h"
|
||||||
|
|
||||||
|
#define STR(NAME) #NAME
|
||||||
|
|
||||||
|
|
||||||
#pragma mark MVKSurface
|
#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).
|
// pCreateInfo->pView can be either a CAMetalLayer or a view (NSView/UIView).
|
||||||
MVKSurface::MVKSurface(MVKInstance* mvkInstance,
|
MVKSurface::MVKSurface(MVKInstance* mvkInstance,
|
||||||
const Vk_PLATFORM_SurfaceCreateInfoMVK* pCreateInfo,
|
const Vk_PLATFORM_SurfaceCreateInfoMVK* pCreateInfo,
|
||||||
const VkAllocationCallbacks* pAllocator) {
|
const VkAllocationCallbacks* pAllocator) : _mvkInstance(mvkInstance) {
|
||||||
|
|
||||||
// Get the platform object contained in pView
|
// Get the platform object contained in pView
|
||||||
id<NSObject> obj = (id<NSObject>)pCreateInfo->pView;
|
id<NSObject> obj = (id<NSObject>)pCreateInfo->pView;
|
||||||
@ -50,7 +39,8 @@ MVKSurface::MVKSurface(MVKInstance* mvkInstance,
|
|||||||
// If it's a view (NSView/UIView), extract the layer, otherwise assume it's already a CAMetalLayer.
|
// 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 ([obj isKindOfClass: [PLATFORM_VIEW_CLASS class]]) {
|
||||||
if ( !NSThread.isMainThread ) {
|
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;
|
obj = ((PLATFORM_VIEW_CLASS*)obj).layer;
|
||||||
}
|
}
|
||||||
@ -72,7 +62,9 @@ MVKSurface::MVKSurface(MVKInstance* mvkInstance,
|
|||||||
} forObject: _mtlCAMetalLayer.delegate atKeyPath: @"layer"];
|
} forObject: _mtlCAMetalLayer.delegate atKeyPath: @"layer"];
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
_mtlCAMetalLayer = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,13 @@ class MVKWatermark;
|
|||||||
#pragma mark MVKSwapchain
|
#pragma mark MVKSwapchain
|
||||||
|
|
||||||
/** Represents a Vulkan swapchain. */
|
/** Represents a Vulkan swapchain. */
|
||||||
class MVKSwapchain : public MVKBaseDeviceObject {
|
class MVKSwapchain : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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. */
|
/** Returns the number of images in this swapchain. */
|
||||||
uint32_t getImageCount();
|
uint32_t getImageCount();
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "MVKWatermark.h"
|
#include "MVKWatermark.h"
|
||||||
#include "MVKWatermarkTextureContent.h"
|
#include "MVKWatermarkTextureContent.h"
|
||||||
#include "MVKWatermarkShaderSource.h"
|
#include "MVKWatermarkShaderSource.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "mvk_datatypes.hpp"
|
||||||
#include "MVKLogging.h"
|
#include "MVKLogging.h"
|
||||||
#import "CAMetalLayer+MoltenVK.h"
|
#import "CAMetalLayer+MoltenVK.h"
|
||||||
#import "MVKBlockObserver.h"
|
#import "MVKBlockObserver.h"
|
||||||
@ -177,7 +177,7 @@ id<CAMetalDrawable> MVKSwapchain::getNextCAMetalDrawable() {
|
|||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKSwapchain::MVKSwapchain(MVKDevice* device,
|
MVKSwapchain::MVKSwapchain(MVKDevice* device,
|
||||||
const VkSwapchainCreateInfoKHR* pCreateInfo) : MVKBaseDeviceObject(device), _surfaceLost(false) {
|
const VkSwapchainCreateInfoKHR* pCreateInfo) : MVKVulkanAPIDeviceObject(device), _surfaceLost(false) {
|
||||||
_currentAcquisitionID = 0;
|
_currentAcquisitionID = 0;
|
||||||
|
|
||||||
// If applicable, release any surfaces (not currently being displayed) from the old swapchain.
|
// If applicable, release any surfaces (not currently being displayed) from the old swapchain.
|
||||||
|
@ -43,6 +43,9 @@ class MVKSemaphoreImpl : public MVKBaseObject {
|
|||||||
|
|
||||||
public:
|
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.
|
* Adds a reservation to this semaphore, incrementing the reservation count.
|
||||||
* Subsequent calls to a wait() function will block until a corresponding call
|
* Subsequent calls to a wait() function will block until a corresponding call
|
||||||
@ -100,10 +103,13 @@ private:
|
|||||||
#pragma mark MVKSemaphore
|
#pragma mark MVKSemaphore
|
||||||
|
|
||||||
/** Represents a Vulkan semaphore. */
|
/** Represents a Vulkan semaphore. */
|
||||||
class MVKSemaphore : public MVKRefCountedDeviceObject {
|
class MVKSemaphore : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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
|
* Blocks processing on the current thread until this semaphore is
|
||||||
* signaled, or until the specified timeout in nanoseconds expires.
|
* signaled, or until the specified timeout in nanoseconds expires.
|
||||||
@ -121,7 +127,7 @@ public:
|
|||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKSemaphore(MVKDevice* device, const VkSemaphoreCreateInfo* pCreateInfo)
|
MVKSemaphore(MVKDevice* device, const VkSemaphoreCreateInfo* pCreateInfo)
|
||||||
: MVKRefCountedDeviceObject(device), _blocker(false, 1) {}
|
: MVKVulkanAPIDeviceObject(device), _blocker(false, 1) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MVKSemaphoreImpl _blocker;
|
MVKSemaphoreImpl _blocker;
|
||||||
@ -132,10 +138,13 @@ protected:
|
|||||||
#pragma mark MVKFence
|
#pragma mark MVKFence
|
||||||
|
|
||||||
/** Represents a Vulkan fence. */
|
/** Represents a Vulkan fence. */
|
||||||
class MVKFence : public MVKRefCountedDeviceObject {
|
class MVKFence : public MVKVulkanAPIDeviceObject {
|
||||||
|
|
||||||
public:
|
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
|
* 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,
|
* internal list of fence sitters that will be notified when this fence is signaled,
|
||||||
@ -166,7 +175,7 @@ public:
|
|||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKFence(MVKDevice* device, const VkFenceCreateInfo* pCreateInfo) :
|
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:
|
protected:
|
||||||
void notifySitters();
|
void notifySitters();
|
||||||
@ -185,6 +194,9 @@ class MVKFenceSitter : public MVKBaseObject {
|
|||||||
|
|
||||||
public:
|
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
|
* 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
|
* current thread until any or all of the fences that this instance is waiting for are
|
||||||
@ -222,7 +234,8 @@ VkResult mvkResetFences(uint32_t fenceCount, const VkFence* pFences);
|
|||||||
* Blocks the current thread until any or all of the specified
|
* Blocks the current thread until any or all of the specified
|
||||||
* fences have been signaled, or the specified timeout occurs.
|
* fences have been signaled, or the specified timeout occurs.
|
||||||
*/
|
*/
|
||||||
VkResult mvkWaitForFences(uint32_t fenceCount,
|
VkResult mvkWaitForFences(MVKDevice* device,
|
||||||
|
uint32_t fenceCount,
|
||||||
const VkFence* pFences,
|
const VkFence* pFences,
|
||||||
VkBool32 waitAll,
|
VkBool32 waitAll,
|
||||||
uint64_t timeout = UINT64_MAX);
|
uint64_t timeout = UINT64_MAX);
|
||||||
@ -237,17 +250,20 @@ VkResult mvkWaitForFences(uint32_t fenceCount,
|
|||||||
*
|
*
|
||||||
* Instances of this class are one-shot, and can only be used for a single compilation.
|
* 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:
|
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. */
|
/** If this object is waiting for compilation to complete, deletion will be deferred until then. */
|
||||||
void destroy() override;
|
void destroy() override;
|
||||||
|
|
||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKMetalCompiler(MVKDevice* device) : MVKBaseDeviceObject(device) {}
|
MVKMetalCompiler(MVKVulkanAPIDeviceObject* owner) : _owner(owner) {}
|
||||||
|
|
||||||
~MVKMetalCompiler() override;
|
~MVKMetalCompiler() override;
|
||||||
|
|
||||||
@ -257,6 +273,7 @@ protected:
|
|||||||
bool endCompile(NSError* compileError);
|
bool endCompile(NSError* compileError);
|
||||||
bool markDestroyed();
|
bool markDestroyed();
|
||||||
|
|
||||||
|
MVKVulkanAPIDeviceObject* _owner;
|
||||||
NSError* _compileError = nil;
|
NSError* _compileError = nil;
|
||||||
uint64_t _startTime = 0;
|
uint64_t _startTime = 0;
|
||||||
bool _isCompileDone = false;
|
bool _isCompileDone = false;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "MVKSync.h"
|
#include "MVKSync.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
|
#include "MVKLogging.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -70,7 +71,7 @@ bool MVKSemaphoreImpl::wait(uint64_t timeout, bool reserveAgain) {
|
|||||||
|
|
||||||
bool MVKSemaphore::wait(uint64_t timeout) {
|
bool MVKSemaphore::wait(uint64_t timeout) {
|
||||||
bool isDone = _blocker.wait(timeout, true);
|
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;
|
return isDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +139,8 @@ VkResult mvkResetFences(uint32_t fenceCount, const VkFence* pFences) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a blocking fence sitter, add it to each fence, wait, then remove it.
|
// 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,
|
const VkFence* pFences,
|
||||||
VkBool32 waitAll,
|
VkBool32 waitAll,
|
||||||
uint64_t timeout) {
|
uint64_t timeout) {
|
||||||
@ -153,7 +155,7 @@ VkResult mvkWaitForFences(uint32_t fenceCount,
|
|||||||
if ( !fenceSitter.wait(timeout) ) {
|
if ( !fenceSitter.wait(timeout) ) {
|
||||||
rslt = VK_TIMEOUT;
|
rslt = VK_TIMEOUT;
|
||||||
if (timeout > 0) {
|
if (timeout > 0) {
|
||||||
mvkNotifyErrorWithText(rslt, "Vulkan fence timeout after %llu nanoseconds.", timeout);
|
device->reportError(rslt, "Vulkan fence timeout after %llu nanoseconds.", timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,12 +177,14 @@ VkResult mvkWaitForFences(uint32_t fenceCount,
|
|||||||
// over a second to return when a compiler failure occurs!
|
// over a second to return when a compiler failure occurs!
|
||||||
void MVKMetalCompiler::compile(unique_lock<mutex>& lock, dispatch_block_t block) {
|
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());
|
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);
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
|
||||||
|
|
||||||
// Limit timeout to avoid overflow since wait_for() uses wait_until()
|
// 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; });
|
_blocker.wait_for(lock, nanoTimeout, [this]{ return _isCompileDone; });
|
||||||
|
|
||||||
if ( !_isCompileDone ) {
|
if ( !_isCompileDone ) {
|
||||||
@ -190,11 +194,11 @@ void MVKMetalCompiler::compile(unique_lock<mutex>& lock, dispatch_block_t block)
|
|||||||
|
|
||||||
if (_compileError) { handleError(); }
|
if (_compileError) { handleError(); }
|
||||||
|
|
||||||
_device->addActivityPerformance(*_pPerformanceTracker, _startTime);
|
mvkDev->addActivityPerformance(*_pPerformanceTracker, _startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MVKMetalCompiler::handleError() {
|
void MVKMetalCompiler::handleError() {
|
||||||
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED,
|
_owner->setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED,
|
||||||
"%s compile failed (Error code %li):\n%s.",
|
"%s compile failed (Error code %li):\n%s.",
|
||||||
_compilerType.c_str(), (long)_compileError.code,
|
_compilerType.c_str(), (long)_compileError.code,
|
||||||
_compileError.localizedDescription.UTF8String));
|
_compileError.localizedDescription.UTF8String));
|
||||||
@ -209,7 +213,7 @@ bool MVKMetalCompiler::endCompile(NSError* compileError) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MVKMetalCompiler::destroy() {
|
void MVKMetalCompiler::destroy() {
|
||||||
if (markDestroyed()) { MVKBaseDeviceObject::destroy(); }
|
if (markDestroyed()) { MVKBaseObject::destroy(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marks this object as destroyed, and returns whether the compilation is complete.
|
// Marks this object as destroyed, and returns whether the compilation is complete.
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "MVKExtensions.h"
|
#include "MVKExtensions.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "MVKOSExtensions.h"
|
#include "MVKOSExtensions.h"
|
||||||
|
#include "MVKEnvironment.h"
|
||||||
#include "vk_mvk_moltenvk.h"
|
#include "vk_mvk_moltenvk.h"
|
||||||
#include <vulkan/vulkan_ios.h>
|
#include <vulkan/vulkan_ios.h>
|
||||||
#include <vulkan/vulkan_macos.h>
|
#include <vulkan/vulkan_macos.h>
|
||||||
@ -26,6 +27,9 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark MVKExtension
|
||||||
|
|
||||||
// Returns a VkExtensionProperties struct populated with a name and version
|
// Returns a VkExtensionProperties struct populated with a name and version
|
||||||
static VkExtensionProperties mvkMakeExtProps(const char* extensionName, uint32_t specVersion) {
|
static VkExtensionProperties mvkMakeExtProps(const char* extensionName, uint32_t specVersion) {
|
||||||
VkExtensionProperties extProps;
|
VkExtensionProperties extProps;
|
||||||
@ -40,11 +44,62 @@ static VkExtensionProperties mvkMakeExtProps(const char* extensionName, uint32_t
|
|||||||
static VkExtensionProperties kVkExtProps_ ##EXT = mvkMakeExtProps(VK_ ##EXT ##_EXTENSION_NAME, VK_ ##EXT ##_SPEC_VERSION);
|
static VkExtensionProperties kVkExtProps_ ##EXT = mvkMakeExtProps(VK_ ##EXT ##_EXTENSION_NAME, VK_ ##EXT ##_SPEC_VERSION);
|
||||||
#include "MVKExtensions.def"
|
#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_LAST(var, EXT) vk_ ##var(&kVkExtProps_ ##EXT, enableForPlatform)
|
||||||
#define MVK_EXTENSION(var, EXT) MVK_EXTENSION_LAST(var, EXT),
|
#define MVK_EXTENSION(var, EXT) MVK_EXTENSION_LAST(var, EXT),
|
||||||
#include "MVKExtensions.def"
|
#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 {
|
bool MVKExtensionList::isEnabled(const char* extnName) const {
|
||||||
if ( !extnName ) { return false; }
|
if ( !extnName ) { return false; }
|
||||||
@ -77,7 +132,7 @@ VkResult MVKExtensionList::enable(uint32_t count, const char* const* names, MVKE
|
|||||||
for (uint32_t i = 0; i < count; i++) {
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
auto extnName = names[i];
|
auto extnName = names[i];
|
||||||
if (parent && !parent->isEnabled(extnName)) {
|
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 {
|
} else {
|
||||||
enable(extnName);
|
enable(extnName);
|
||||||
}
|
}
|
||||||
@ -102,29 +157,3 @@ string MVKExtensionList::enabledNamesString(const char* separator, bool prefixFi
|
|||||||
}
|
}
|
||||||
return logMsg;
|
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);
|
|
||||||
}
|
|
||||||
|
@ -52,6 +52,7 @@ MVK_EXTENSION(KHR_surface, KHR_SURFACE)
|
|||||||
MVK_EXTENSION(KHR_swapchain, KHR_SWAPCHAIN)
|
MVK_EXTENSION(KHR_swapchain, KHR_SWAPCHAIN)
|
||||||
MVK_EXTENSION(KHR_swapchain_mutable_format, KHR_SWAPCHAIN_MUTABLE_FORMAT)
|
MVK_EXTENSION(KHR_swapchain_mutable_format, KHR_SWAPCHAIN_MUTABLE_FORMAT)
|
||||||
MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS)
|
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_host_query_reset, EXT_HOST_QUERY_RESET)
|
||||||
MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET)
|
MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET)
|
||||||
MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER)
|
MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER)
|
||||||
|
@ -18,9 +18,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "mvk_vulkan.h"
|
#include "MVKBaseObject.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark MVKExtension
|
||||||
|
|
||||||
/** Describes a Vulkan extension and whether or not it is enabled or supported. */
|
/** Describes a Vulkan extension and whether or not it is enabled or supported. */
|
||||||
struct MVKExtension {
|
struct MVKExtension {
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
@ -29,13 +33,23 @@ struct MVKExtension {
|
|||||||
MVKExtension(VkExtensionProperties* pProperties, bool enableForPlatform = false);
|
MVKExtension(VkExtensionProperties* pProperties, bool enableForPlatform = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark MVKExtensionList
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fixed list of the Vulkan extensions known to MoltenVK, with
|
* A fixed list of the Vulkan extensions known to MoltenVK, with
|
||||||
* an indication of whether each extension is supported/enabled.
|
* an indication of whether each extension is supported/enabled.
|
||||||
*
|
*
|
||||||
* To add support for a Vulkan extension, add a variable to this list.
|
* 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 {
|
union {
|
||||||
struct {
|
struct {
|
||||||
#define MVK_EXTENSION(var, EXT) MVKExtension vk_ ##var;
|
#define MVK_EXTENSION(var, EXT) MVKExtension vk_ ##var;
|
||||||
@ -45,7 +59,10 @@ struct MVKExtensionList {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Returns the total number of extensions that are tracked by this object. */
|
/** 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. */
|
/** Returns whether the named extension is enabled. */
|
||||||
bool isEnabled(const char* extnName) const;
|
bool isEnabled(const char* extnName) const;
|
||||||
@ -68,6 +85,13 @@ struct MVKExtensionList {
|
|||||||
*/
|
*/
|
||||||
std::string enabledNamesString(const char* separator = " ", bool prefixFirstWithSeparator = false) const;
|
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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,10 +26,13 @@
|
|||||||
#pragma mark MVKLayer
|
#pragma mark MVKLayer
|
||||||
|
|
||||||
/** Represents a single Vulkan layer. */
|
/** Represents a single Vulkan layer. */
|
||||||
class MVKLayer : public MVKConfigurableObject {
|
class MVKLayer : public MVKBaseObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** Returns the Vulkan API opaque object controlling this object. */
|
||||||
|
MVKVulkanAPIObject* getVulkanAPIObject() override { return nullptr; };
|
||||||
|
|
||||||
/** Returns the name of this layer. */
|
/** Returns the name of this layer. */
|
||||||
const char* getName();
|
const char* getName();
|
||||||
|
|
||||||
@ -66,10 +69,13 @@ protected:
|
|||||||
#pragma mark MVKLayerManager
|
#pragma mark MVKLayerManager
|
||||||
|
|
||||||
/** Manages a set of Vulkan layers. */
|
/** Manages a set of Vulkan layers. */
|
||||||
class MVKLayerManager : public MVKConfigurableObject {
|
class MVKLayerManager : public MVKBaseObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** Returns the Vulkan API opaque object controlling this object. */
|
||||||
|
MVKVulkanAPIObject* getVulkanAPIObject() override { return nullptr; };
|
||||||
|
|
||||||
/** Returns the driver layer. */
|
/** Returns the driver layer. */
|
||||||
MVKLayer* getDriverLayer();
|
MVKLayer* getDriverLayer();
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ VkResult MVKLayer::getExtensionProperties(uint32_t* pCount, VkExtensionPropertie
|
|||||||
|
|
||||||
#pragma mark Object Creation
|
#pragma mark Object Creation
|
||||||
|
|
||||||
MVKLayer::MVKLayer() : _supportedExtensions(true) {
|
MVKLayer::MVKLayer() : _supportedExtensions(nullptr, true) {
|
||||||
|
|
||||||
// The core driver layer
|
// The core driver layer
|
||||||
memset(_layerProperties.layerName, 0, sizeof(_layerProperties.layerName));
|
memset(_layerProperties.layerName, 0, sizeof(_layerProperties.layerName));
|
||||||
@ -116,7 +116,7 @@ VkResult MVKLayerManager::getLayerProperties(uint32_t* pCount, VkLayerProperties
|
|||||||
|
|
||||||
// Populate the layers
|
// Populate the layers
|
||||||
MVKLayerManager::MVKLayerManager() {
|
MVKLayerManager::MVKLayerManager() {
|
||||||
_layers.push_back(MVKLayer());
|
_layers.emplace_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
static mutex _lock;
|
static mutex _lock;
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "MVKCommonEnvironment.h"
|
|
||||||
#include "CAMetalLayer+MoltenVK.h"
|
#include "CAMetalLayer+MoltenVK.h"
|
||||||
|
#include "MVKEnvironment.h"
|
||||||
|
|
||||||
@implementation CAMetalLayer (MoltenVK)
|
@implementation CAMetalLayer (MoltenVK)
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "MTLRenderPassDescriptor+MoltenVK.h"
|
#include "MTLRenderPassDescriptor+MoltenVK.h"
|
||||||
#include "MVKCommonEnvironment.h"
|
#include "MVKEnvironment.h"
|
||||||
|
|
||||||
@implementation MTLRenderPassDescriptor (MoltenVK)
|
@implementation MTLRenderPassDescriptor (MoltenVK)
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "MTLSamplerDescriptor+MoltenVK.h"
|
#include "MTLSamplerDescriptor+MoltenVK.h"
|
||||||
|
#include "MVKEnvironment.h"
|
||||||
|
|
||||||
@implementation MTLSamplerDescriptor (MoltenVK)
|
@implementation MTLSamplerDescriptor (MoltenVK)
|
||||||
|
|
||||||
|
@ -18,12 +18,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "MVKDevice.h"
|
#include "MVKQueue.h"
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
class MVKQueue;
|
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKGPUCaptureScope
|
#pragma mark MVKGPUCaptureScope
|
||||||
@ -34,10 +32,13 @@ class MVKQueue;
|
|||||||
* If the OS supports the MTLCaptureScope protocol, this class creates and wraps an MTLCaptureScope
|
* 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.
|
* instance for a MTLQueue, otherwise it interacts directly with the MTLQueue to define capture boundaries.
|
||||||
*/
|
*/
|
||||||
class MVKGPUCaptureScope : public MVKBaseDeviceObject {
|
class MVKGPUCaptureScope : public MVKBaseObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** Returns the Vulkan API opaque object controlling this object. */
|
||||||
|
MVKVulkanAPIObject* getVulkanAPIObject() override { return _queue->getVulkanAPIObject(); };
|
||||||
|
|
||||||
/** Marks the beginning boundary of a capture scope. */
|
/** Marks the beginning boundary of a capture scope. */
|
||||||
void beginScope();
|
void beginScope();
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ public:
|
|||||||
~MVKGPUCaptureScope() override;
|
~MVKGPUCaptureScope() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
MVKQueue* _queue;
|
||||||
id<MTLCaptureScope> _mtlCaptureScope = nil;
|
id<MTLCaptureScope> _mtlCaptureScope = nil;
|
||||||
id<MTLCommandQueue> _mtlQueue = nil;
|
id<MTLCommandQueue> _mtlQueue = nil;
|
||||||
bool _isFirstBoundary = true;
|
bool _isFirstBoundary = true;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "MVKGPUCapture.h"
|
#include "MVKGPUCapture.h"
|
||||||
#include "MVKQueue.h"
|
#include "MVKQueue.h"
|
||||||
#include "MVKOSExtensions.h"
|
#include "MVKOSExtensions.h"
|
||||||
|
#include "MVKEnvironment.h"
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
@ -55,11 +56,11 @@ void MVKGPUCaptureScope::makeDefault() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKGPUCaptureScope::MVKGPUCaptureScope(MVKQueue* mvkQueue, const char* purpose) : MVKBaseDeviceObject(mvkQueue->getDevice()) {
|
MVKGPUCaptureScope::MVKGPUCaptureScope(MVKQueue* mvkQueue, const char* purpose) : _queue(mvkQueue) {
|
||||||
_mtlQueue = [mvkQueue->getMTLCommandQueue() retain]; // retained
|
_mtlQueue = [_queue->getMTLCommandQueue() retain]; // retained
|
||||||
if (mvkOSVersion() >= kMinOSVersionMTLCaptureScope) {
|
if (mvkOSVersion() >= kMinOSVersionMTLCaptureScope) {
|
||||||
_mtlCaptureScope = [[MTLCaptureManager sharedCaptureManager] newCaptureScopeWithCommandQueue: _mtlQueue]; // retained
|
_mtlCaptureScope = [[MTLCaptureManager sharedCaptureManager] newCaptureScopeWithCommandQueue: _mtlQueue]; // retained
|
||||||
_mtlCaptureScope.label = @((mvkQueue->getName() + "-" + purpose).c_str());
|
_mtlCaptureScope.label = @((_queue->getName() + "-" + purpose).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,12 +17,57 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MVKBaseObject.h"
|
#include "MVKBaseObject.h"
|
||||||
|
#include "MVKInstance.h"
|
||||||
|
#include "MVKFoundation.h"
|
||||||
|
#include "MVKOSExtensions.h"
|
||||||
|
#include "MVKLogging.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
|
|
||||||
using namespace std;
|
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 -
|
||||||
#pragma mark MVKBaseObject
|
#pragma mark MVKBaseObject
|
||||||
|
|
||||||
@ -33,3 +78,125 @@ string MVKBaseObject::getClassName() {
|
|||||||
free(demangled);
|
free(demangled);
|
||||||
return clzName;
|
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;
|
||||||
|
}
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
#include "mvk_vulkan.h"
|
#include "mvk_vulkan.h"
|
||||||
#include <vulkan/vk_icd.h>
|
#include <vulkan/vk_icd.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
class MVKInstance;
|
||||||
|
class MVKVulkanAPIObject;
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
@ -37,6 +41,59 @@ public:
|
|||||||
/** Returns the name of the class of which this object is an instance. */
|
/** Returns the name of the class of which this object is an instance. */
|
||||||
std::string getClassName();
|
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. */
|
/** Destroys this object. Default behaviour simply deletes it. Subclasses may override to delay deletion. */
|
||||||
virtual void destroy() { delete this; }
|
virtual void destroy() { delete this; }
|
||||||
|
|
||||||
@ -72,14 +129,83 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#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 {
|
typedef struct {
|
||||||
VK_LOADER_DATA loaderData;
|
VK_LOADER_DATA loaderData;
|
||||||
MVKDispatchableObject* mvkObject;
|
MVKDispatchableVulkanAPIObject* mvkObject;
|
||||||
} MVKDispatchableObjectICDRef;
|
} MVKDispatchableObjectICDRef;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -88,13 +214,13 @@ public:
|
|||||||
* Returns a reference to this object suitable for use as a Vulkan API handle.
|
* Returns a reference to this object suitable for use as a Vulkan API handle.
|
||||||
* This is the compliment of the getDispatchableObject() method.
|
* 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.
|
* 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;
|
return vkHandle ? ((MVKDispatchableObjectICDRef*)vkHandle)->mvkObject : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,8 +20,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "MVKCommonEnvironment.h"
|
#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. */
|
/** 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), \
|
#define MVK_VULKAN_API_VERSION VK_MAKE_VERSION(VK_VERSION_MAJOR(VK_API_VERSION_1_0), \
|
||||||
VK_VERSION_MINOR(VK_API_VERSION_1_0), \
|
VK_VERSION_MINOR(VK_API_VERSION_1_0), \
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "MVKLogging.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define CASE_STRINGIFY(V) case V: return #V
|
#define CASE_STRINGIFY(V) case V: return #V
|
||||||
@ -75,23 +74,6 @@ const char* mvkVkComponentSwizzleName(VkComponentSwizzle swizzle) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 -
|
||||||
#pragma mark Alignment functions
|
#pragma mark Alignment functions
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "mvk_vulkan.h"
|
#include "mvk_vulkan.h"
|
||||||
#include "MVKLogging.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <simd/simd.h>
|
#include <simd/simd.h>
|
||||||
@ -137,13 +136,6 @@ static inline std::string mvkGetMoltenVKVersionString(uint32_t mvkVersion) {
|
|||||||
return verStr;
|
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 -
|
||||||
#pragma mark Alignment functions
|
#pragma mark Alignment functions
|
||||||
@ -203,7 +195,7 @@ static inline uint32_t mvkPowerOfTwoExponent(uintptr_t value) {
|
|||||||
static inline uintptr_t mvkAlignByteRef(uintptr_t byteRef, uintptr_t byteAlignment, bool alignDown = false) {
|
static inline uintptr_t mvkAlignByteRef(uintptr_t byteRef, uintptr_t byteAlignment, bool alignDown = false) {
|
||||||
if (byteAlignment == 0) { return byteRef; }
|
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 mask = byteAlignment - 1;
|
||||||
uintptr_t alignedRef = (byteRef + mask) & ~mask;
|
uintptr_t alignedRef = (byteRef + mask) & ~mask;
|
||||||
|
@ -58,6 +58,10 @@ class MVKWatermark : public MVKBaseObject {
|
|||||||
|
|
||||||
public:
|
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. */
|
/** Sets the clip-space position (0.0 - 1.0) of this watermark. */
|
||||||
void setPosition(MVKWatermarkPosition position);
|
void setPosition(MVKWatermarkPosition position);
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "MVKOSExtensions.h"
|
#include "MVKOSExtensions.h"
|
||||||
#include "MVKLogging.h"
|
#include "MVKLogging.h"
|
||||||
#include "MTLTextureDescriptor+MoltenVK.h"
|
#include "MTLTextureDescriptor+MoltenVK.h"
|
||||||
|
#include "MVKEnvironment.h"
|
||||||
|
|
||||||
|
|
||||||
/** The structure to hold shader uniforms. */
|
/** The structure to hold shader uniforms. */
|
||||||
|
78
MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp
Normal file
78
MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp
Normal file
@ -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
|
@ -17,10 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MVKEnvironment.h"
|
#include "MVKEnvironment.h"
|
||||||
#include "mvk_datatypes.h"
|
#include "mvk_datatypes.hpp"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "MVKOSExtensions.h"
|
#include "MVKOSExtensions.h"
|
||||||
#include "MVKLogging.h"
|
#include "MVKBaseObject.h"
|
||||||
#include <MoltenVKSPIRVToMSLConverter/SPIRVReflection.h>
|
#include <MoltenVKSPIRVToMSLConverter/SPIRVReflection.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -563,7 +563,12 @@ MVK_PUBLIC_SYMBOL MVKFormatType mvkFormatTypeFromMTLPixelFormat(MTLPixelFormat m
|
|||||||
return formatDescForMTLPixelFormat(mtlFormat).formatType;
|
return formatDescForMTLPixelFormat(mtlFormat).formatType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef mvkMTLPixelFormatFromVkFormat
|
||||||
MVK_PUBLIC_SYMBOL MTLPixelFormat mvkMTLPixelFormatFromVkFormat(VkFormat vkFormat) {
|
MVK_PUBLIC_SYMBOL MTLPixelFormat mvkMTLPixelFormatFromVkFormat(VkFormat vkFormat) {
|
||||||
|
return mvkMTLPixelFormatFromVkFormatInObj(vkFormat, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLPixelFormat mvkMTLPixelFormatFromVkFormatInObj(VkFormat vkFormat, MVKBaseObject* mvkObj) {
|
||||||
MTLPixelFormat mtlPixFmt = MTLPixelFormatInvalid;
|
MTLPixelFormat mtlPixFmt = MTLPixelFormatInvalid;
|
||||||
|
|
||||||
const MVKFormatDesc& fmtDesc = formatDescForVkFormat(vkFormat);
|
const MVKFormatDesc& fmtDesc = formatDescForVkFormat(vkFormat);
|
||||||
@ -585,7 +590,7 @@ MVK_PUBLIC_SYMBOL MTLPixelFormat mvkMTLPixelFormatFromVkFormat(VkFormat vkFormat
|
|||||||
errMsg += (fmtDescSubs.vkName) ? fmtDescSubs.vkName : to_string(fmtDescSubs.vk);
|
errMsg += (fmtDescSubs.vkName) ? fmtDescSubs.vkName : to_string(fmtDescSubs.vk);
|
||||||
errMsg += " instead.";
|
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;
|
return mtlPixFmt;
|
||||||
@ -660,7 +665,12 @@ MVK_PUBLIC_SYMBOL const char* mvkMTLPixelFormatName(MTLPixelFormat mtlFormat) {
|
|||||||
return formatDescForMTLPixelFormat(mtlFormat).mtlName;
|
return formatDescForMTLPixelFormat(mtlFormat).mtlName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef mvkMTLVertexFormatFromVkFormat
|
||||||
MVK_PUBLIC_SYMBOL MTLVertexFormat mvkMTLVertexFormatFromVkFormat(VkFormat vkFormat) {
|
MVK_PUBLIC_SYMBOL MTLVertexFormat mvkMTLVertexFormatFromVkFormat(VkFormat vkFormat) {
|
||||||
|
return mvkMTLVertexFormatFromVkFormatInObj(vkFormat, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLVertexFormat mvkMTLVertexFormatFromVkFormatInObj(VkFormat vkFormat, MVKBaseObject* mvkObj) {
|
||||||
MTLVertexFormat mtlVtxFmt = MTLVertexFormatInvalid;
|
MTLVertexFormat mtlVtxFmt = MTLVertexFormatInvalid;
|
||||||
|
|
||||||
const MVKFormatDesc& fmtDesc = formatDescForVkFormat(vkFormat);
|
const MVKFormatDesc& fmtDesc = formatDescForVkFormat(vkFormat);
|
||||||
@ -682,7 +692,7 @@ MVK_PUBLIC_SYMBOL MTLVertexFormat mvkMTLVertexFormatFromVkFormat(VkFormat vkForm
|
|||||||
errMsg += (fmtDescSubs.vkName) ? fmtDescSubs.vkName : to_string(fmtDescSubs.vk);
|
errMsg += (fmtDescSubs.vkName) ? fmtDescSubs.vkName : to_string(fmtDescSubs.vk);
|
||||||
errMsg += " instead.";
|
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;
|
return mtlVtxFmt;
|
||||||
@ -1046,7 +1056,12 @@ MVK_PUBLIC_SYMBOL MTLVertexStepFunction mvkMTLVertexStepFunctionFromVkVertexInpu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef mvkMTLPrimitiveTypeFromVkPrimitiveTopology
|
||||||
MVK_PUBLIC_SYMBOL MTLPrimitiveType mvkMTLPrimitiveTypeFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology) {
|
MVK_PUBLIC_SYMBOL MTLPrimitiveType mvkMTLPrimitiveTypeFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology) {
|
||||||
|
return mvkMTLPrimitiveTypeFromVkPrimitiveTopologyInObj(vkTopology, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLPrimitiveType mvkMTLPrimitiveTypeFromVkPrimitiveTopologyInObj(VkPrimitiveTopology vkTopology, MVKBaseObject* mvkObj) {
|
||||||
switch (vkTopology) {
|
switch (vkTopology) {
|
||||||
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
|
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
|
||||||
return MTLPrimitiveTypePoint;
|
return MTLPrimitiveTypePoint;
|
||||||
@ -1070,12 +1085,17 @@ MVK_PUBLIC_SYMBOL MTLPrimitiveType mvkMTLPrimitiveTypeFromVkPrimitiveTopology(Vk
|
|||||||
|
|
||||||
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
|
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
|
||||||
default:
|
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;
|
return MTLPrimitiveTypePoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology
|
||||||
MVK_PUBLIC_SYMBOL MTLPrimitiveTopologyClass mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology) {
|
MVK_PUBLIC_SYMBOL MTLPrimitiveTopologyClass mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology) {
|
||||||
|
return mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopologyInObj(vkTopology, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLPrimitiveTopologyClass mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopologyInObj(VkPrimitiveTopology vkTopology, MVKBaseObject* mvkObj) {
|
||||||
switch (vkTopology) {
|
switch (vkTopology) {
|
||||||
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
|
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
|
||||||
return MTLPrimitiveTopologyClassPoint;
|
return MTLPrimitiveTopologyClassPoint;
|
||||||
@ -1095,12 +1115,17 @@ MVK_PUBLIC_SYMBOL MTLPrimitiveTopologyClass mvkMTLPrimitiveTopologyClassFromVkPr
|
|||||||
return MTLPrimitiveTopologyClassTriangle;
|
return MTLPrimitiveTopologyClassTriangle;
|
||||||
|
|
||||||
default:
|
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;
|
return MTLPrimitiveTopologyClassUnspecified;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef mvkMTLTriangleFillModeFromVkPolygonMode
|
||||||
MVK_PUBLIC_SYMBOL MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonMode(VkPolygonMode vkFillMode) {
|
MVK_PUBLIC_SYMBOL MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonMode(VkPolygonMode vkFillMode) {
|
||||||
|
return mvkMTLTriangleFillModeFromVkPolygonModeInObj(vkFillMode, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonModeInObj(VkPolygonMode vkFillMode, MVKBaseObject* mvkObj) {
|
||||||
switch (vkFillMode) {
|
switch (vkFillMode) {
|
||||||
case VK_POLYGON_MODE_FILL:
|
case VK_POLYGON_MODE_FILL:
|
||||||
case VK_POLYGON_MODE_POINT:
|
case VK_POLYGON_MODE_POINT:
|
||||||
@ -1110,30 +1135,40 @@ MVK_PUBLIC_SYMBOL MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonMode(Vk
|
|||||||
return MTLTriangleFillModeLines;
|
return MTLTriangleFillModeLines;
|
||||||
|
|
||||||
default:
|
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;
|
return MTLTriangleFillModeFill;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef mvkMTLLoadActionFromVkAttachmentLoadOp
|
||||||
MVK_PUBLIC_SYMBOL MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOp(VkAttachmentLoadOp vkLoadOp) {
|
MVK_PUBLIC_SYMBOL MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOp(VkAttachmentLoadOp vkLoadOp) {
|
||||||
|
return mvkMTLLoadActionFromVkAttachmentLoadOpInObj(vkLoadOp, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOpInObj(VkAttachmentLoadOp vkLoadOp, MVKBaseObject* mvkObj) {
|
||||||
switch (vkLoadOp) {
|
switch (vkLoadOp) {
|
||||||
case VK_ATTACHMENT_LOAD_OP_LOAD: return MTLLoadActionLoad;
|
case VK_ATTACHMENT_LOAD_OP_LOAD: return MTLLoadActionLoad;
|
||||||
case VK_ATTACHMENT_LOAD_OP_CLEAR: return MTLLoadActionClear;
|
case VK_ATTACHMENT_LOAD_OP_CLEAR: return MTLLoadActionClear;
|
||||||
case VK_ATTACHMENT_LOAD_OP_DONT_CARE: return MTLLoadActionDontCare;
|
case VK_ATTACHMENT_LOAD_OP_DONT_CARE: return MTLLoadActionDontCare;
|
||||||
|
|
||||||
default:
|
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;
|
return MTLLoadActionLoad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef mvkMTLStoreActionFromVkAttachmentStoreOp
|
||||||
MVK_PUBLIC_SYMBOL MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOp(VkAttachmentStoreOp vkStoreOp, bool hasResolveAttachment) {
|
MVK_PUBLIC_SYMBOL MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOp(VkAttachmentStoreOp vkStoreOp, bool hasResolveAttachment) {
|
||||||
|
return mvkMTLStoreActionFromVkAttachmentStoreOpInObj(vkStoreOp, hasResolveAttachment, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOpInObj(VkAttachmentStoreOp vkStoreOp, bool hasResolveAttachment, MVKBaseObject* mvkObj) {
|
||||||
switch (vkStoreOp) {
|
switch (vkStoreOp) {
|
||||||
case VK_ATTACHMENT_STORE_OP_STORE: return hasResolveAttachment ? MTLStoreActionStoreAndMultisampleResolve : MTLStoreActionStore;
|
case VK_ATTACHMENT_STORE_OP_STORE: return hasResolveAttachment ? MTLStoreActionStoreAndMultisampleResolve : MTLStoreActionStore;
|
||||||
case VK_ATTACHMENT_STORE_OP_DONT_CARE: return hasResolveAttachment ? MTLStoreActionMultisampleResolve : MTLStoreActionDontCare;
|
case VK_ATTACHMENT_STORE_OP_DONT_CARE: return hasResolveAttachment ? MTLStoreActionMultisampleResolve : MTLStoreActionDontCare;
|
||||||
|
|
||||||
default:
|
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;
|
return MTLStoreActionStore;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1218,7 +1253,12 @@ MVK_PUBLIC_SYMBOL size_t mvkMTLIndexTypeSizeInBytes(MTLIndexType mtlIdxType) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef mvkShaderStageFromVkShaderStageFlagBits
|
||||||
MVK_PUBLIC_SYMBOL MVKShaderStage mvkShaderStageFromVkShaderStageFlagBits(VkShaderStageFlagBits vkStage) {
|
MVK_PUBLIC_SYMBOL MVKShaderStage mvkShaderStageFromVkShaderStageFlagBits(VkShaderStageFlagBits vkStage) {
|
||||||
|
return mvkShaderStageFromVkShaderStageFlagBitsInObj(vkStage, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MVKShaderStage mvkShaderStageFromVkShaderStageFlagBitsInObj(VkShaderStageFlagBits vkStage, MVKBaseObject* mvkObj) {
|
||||||
switch (vkStage) {
|
switch (vkStage) {
|
||||||
case VK_SHADER_STAGE_VERTEX_BIT: return kMVKShaderStageVertex;
|
case VK_SHADER_STAGE_VERTEX_BIT: return kMVKShaderStageVertex;
|
||||||
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return kMVKShaderStageTessCtl;
|
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return kMVKShaderStageTessCtl;
|
||||||
@ -1227,7 +1267,7 @@ MVK_PUBLIC_SYMBOL MVKShaderStage mvkShaderStageFromVkShaderStageFlagBits(VkShade
|
|||||||
case VK_SHADER_STAGE_FRAGMENT_BIT: return kMVKShaderStageFragment;
|
case VK_SHADER_STAGE_FRAGMENT_BIT: return kMVKShaderStageFragment;
|
||||||
case VK_SHADER_STAGE_COMPUTE_BIT: return kMVKShaderStageCompute;
|
case VK_SHADER_STAGE_COMPUTE_BIT: return kMVKShaderStageCompute;
|
||||||
default:
|
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;
|
return kMVKShaderStageMax;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1246,24 +1286,34 @@ MVK_PUBLIC_SYMBOL VkShaderStageFlagBits mvkVkShaderStageFlagBitsFromMVKShaderSta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef mvkMTLWindingFromSpvExecutionMode
|
||||||
MVK_PUBLIC_SYMBOL MTLWinding mvkMTLWindingFromSpvExecutionMode(uint32_t spvMode) {
|
MVK_PUBLIC_SYMBOL MTLWinding mvkMTLWindingFromSpvExecutionMode(uint32_t spvMode) {
|
||||||
|
return mvkMTLWindingFromSpvExecutionModeInObj(spvMode, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLWinding mvkMTLWindingFromSpvExecutionModeInObj(uint32_t spvMode, MVKBaseObject* mvkObj) {
|
||||||
switch (spvMode) {
|
switch (spvMode) {
|
||||||
// These are reversed due to the vertex flip.
|
// These are reversed due to the vertex flip.
|
||||||
case spv::ExecutionModeVertexOrderCw: return MTLWindingCounterClockwise;
|
case spv::ExecutionModeVertexOrderCw: return MTLWindingCounterClockwise;
|
||||||
case spv::ExecutionModeVertexOrderCcw: return MTLWindingClockwise;
|
case spv::ExecutionModeVertexOrderCcw: return MTLWindingClockwise;
|
||||||
default:
|
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;
|
return MTLWindingCounterClockwise;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef mvkMTLTessellationPartitionModeFromSpvExecutionMode
|
||||||
MVK_PUBLIC_SYMBOL MTLTessellationPartitionMode mvkMTLTessellationPartitionModeFromSpvExecutionMode(uint32_t spvMode) {
|
MVK_PUBLIC_SYMBOL MTLTessellationPartitionMode mvkMTLTessellationPartitionModeFromSpvExecutionMode(uint32_t spvMode) {
|
||||||
|
return mvkMTLTessellationPartitionModeFromSpvExecutionModeInObj(spvMode, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLTessellationPartitionMode mvkMTLTessellationPartitionModeFromSpvExecutionModeInObj(uint32_t spvMode, MVKBaseObject* mvkObj) {
|
||||||
switch (spvMode) {
|
switch (spvMode) {
|
||||||
case spv::ExecutionModeSpacingEqual: return MTLTessellationPartitionModeInteger;
|
case spv::ExecutionModeSpacingEqual: return MTLTessellationPartitionModeInteger;
|
||||||
case spv::ExecutionModeSpacingFractionalEven: return MTLTessellationPartitionModeFractionalEven;
|
case spv::ExecutionModeSpacingFractionalEven: return MTLTessellationPartitionModeFractionalEven;
|
||||||
case spv::ExecutionModeSpacingFractionalOdd: return MTLTessellationPartitionModeFractionalOdd;
|
case spv::ExecutionModeSpacingFractionalOdd: return MTLTessellationPartitionModeFractionalOdd;
|
||||||
default:
|
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;
|
return MTLTessellationPartitionModePow2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,16 +38,12 @@
|
|||||||
#include "MVKQueue.h"
|
#include "MVKQueue.h"
|
||||||
#include "MVKQueryPool.h"
|
#include "MVKQueryPool.h"
|
||||||
#include "MVKSwapchain.h"
|
#include "MVKSwapchain.h"
|
||||||
|
#include "MVKSurface.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "MVKLogging.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;
|
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(
|
MVK_PUBLIC_SYMBOL VkResult vkCreateInstance(
|
||||||
const VkInstanceCreateInfo* pCreateInfo,
|
const VkInstanceCreateInfo* pCreateInfo,
|
||||||
@ -204,7 +200,7 @@ MVK_PUBLIC_SYMBOL VkResult vkEnumerateDeviceExtensionProperties(
|
|||||||
|
|
||||||
MVKTraceVulkanCall();
|
MVKTraceVulkanCall();
|
||||||
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
|
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(
|
MVK_PUBLIC_SYMBOL VkResult vkEnumerateInstanceLayerProperties(
|
||||||
@ -222,7 +218,7 @@ MVK_PUBLIC_SYMBOL VkResult vkEnumerateDeviceLayerProperties(
|
|||||||
|
|
||||||
MVKTraceVulkanCall();
|
MVKTraceVulkanCall();
|
||||||
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
|
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
|
||||||
return mvkPD->getLayerManager()->getLayerProperties(pCount, pProperties);
|
return mvkPD->getInstance()->getLayerManager()->getLayerProperties(pCount, pProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
MVK_PUBLIC_SYMBOL void vkGetDeviceQueue(
|
MVK_PUBLIC_SYMBOL void vkGetDeviceQueue(
|
||||||
@ -441,7 +437,8 @@ MVK_PUBLIC_SYMBOL VkResult vkQueueBindSparse(
|
|||||||
VkFence fence) {
|
VkFence fence) {
|
||||||
|
|
||||||
MVKTraceVulkanCall();
|
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(
|
MVK_PUBLIC_SYMBOL VkResult vkCreateFence(
|
||||||
@ -494,7 +491,8 @@ MVK_PUBLIC_SYMBOL VkResult vkWaitForFences(
|
|||||||
uint64_t timeout) {
|
uint64_t timeout) {
|
||||||
|
|
||||||
MVKTraceVulkanCall();
|
MVKTraceVulkanCall();
|
||||||
return mvkWaitForFences(fenceCount, pFences, waitAll, timeout);
|
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
|
||||||
|
return mvkWaitForFences(mvkDev, fenceCount, pFences, waitAll, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
MVK_PUBLIC_SYMBOL VkResult vkCreateSemaphore(
|
MVK_PUBLIC_SYMBOL VkResult vkCreateSemaphore(
|
||||||
@ -528,7 +526,9 @@ MVK_PUBLIC_SYMBOL VkResult vkCreateEvent(
|
|||||||
VkEvent* pEvent) {
|
VkEvent* pEvent) {
|
||||||
|
|
||||||
MVKTraceVulkanCall();
|
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(
|
MVK_PUBLIC_SYMBOL void vkDestroyEvent(
|
||||||
@ -538,7 +538,8 @@ MVK_PUBLIC_SYMBOL void vkDestroyEvent(
|
|||||||
|
|
||||||
MVKTraceVulkanCall();
|
MVKTraceVulkanCall();
|
||||||
if ( !event ) { return; }
|
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(
|
MVK_PUBLIC_SYMBOL VkResult vkGetEventStatus(
|
||||||
@ -546,7 +547,8 @@ MVK_PUBLIC_SYMBOL VkResult vkGetEventStatus(
|
|||||||
VkEvent event) {
|
VkEvent event) {
|
||||||
|
|
||||||
MVKTraceVulkanCall();
|
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(
|
MVK_PUBLIC_SYMBOL VkResult vkSetEvent(
|
||||||
@ -554,7 +556,8 @@ MVK_PUBLIC_SYMBOL VkResult vkSetEvent(
|
|||||||
VkEvent event) {
|
VkEvent event) {
|
||||||
|
|
||||||
MVKTraceVulkanCall();
|
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(
|
MVK_PUBLIC_SYMBOL VkResult vkResetEvent(
|
||||||
@ -562,7 +565,8 @@ MVK_PUBLIC_SYMBOL VkResult vkResetEvent(
|
|||||||
VkEvent event) {
|
VkEvent event) {
|
||||||
|
|
||||||
MVKTraceVulkanCall();
|
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(
|
MVK_PUBLIC_SYMBOL VkResult vkCreateQueryPool(
|
||||||
@ -1468,7 +1472,8 @@ MVK_PUBLIC_SYMBOL void vkCmdSetEvent(
|
|||||||
VkPipelineStageFlags stageMask) {
|
VkPipelineStageFlags stageMask) {
|
||||||
|
|
||||||
MVKTraceVulkanCall();
|
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(
|
MVK_PUBLIC_SYMBOL void vkCmdResetEvent(
|
||||||
@ -1477,7 +1482,8 @@ MVK_PUBLIC_SYMBOL void vkCmdResetEvent(
|
|||||||
VkPipelineStageFlags stageMask) {
|
VkPipelineStageFlags stageMask) {
|
||||||
|
|
||||||
MVKTraceVulkanCall();
|
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(
|
MVK_PUBLIC_SYMBOL void vkCmdWaitEvents(
|
||||||
@ -1494,7 +1500,8 @@ MVK_PUBLIC_SYMBOL void vkCmdWaitEvents(
|
|||||||
const VkImageMemoryBarrier* pImageMemoryBarriers) {
|
const VkImageMemoryBarrier* pImageMemoryBarriers) {
|
||||||
|
|
||||||
MVKTraceVulkanCall();
|
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(
|
MVK_PUBLIC_SYMBOL void vkCmdPipelineBarrier(
|
||||||
@ -2083,6 +2090,49 @@ MVK_PUBLIC_SYMBOL void vkResetQueryPoolEXT(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#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 -
|
||||||
#pragma mark iOS & macOS surface extensions
|
#pragma mark iOS & macOS surface extensions
|
||||||
|
|
||||||
|
@ -57,15 +57,10 @@
|
|||||||
A9C70F65221B321700FBA31A /* SPIRVSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9C70F5E221B321700FBA31A /* SPIRVSupport.cpp */; };
|
A9C70F65221B321700FBA31A /* SPIRVSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9C70F5E221B321700FBA31A /* SPIRVSupport.cpp */; };
|
||||||
A9C70F66221B321700FBA31A /* 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 */; };
|
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 */; };
|
A9F042B01FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */; };
|
||||||
A9F042B11FB4D060009FCCB8 /* 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 */; };
|
A9F042B21FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */; };
|
||||||
A9F042B31FB4D060009FCCB8 /* 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 */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -120,9 +115,7 @@
|
|||||||
A9B51BDC225E98BB00AC74D2 /* MVKOSExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKOSExtensions.h; sourceTree = "<group>"; };
|
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; };
|
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; };
|
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>"; };
|
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 */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -244,8 +237,6 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */,
|
A9F042AA1FB4D060009FCCB8 /* MVKCommonEnvironment.h */,
|
||||||
A9E337B7220129ED00363D2A /* MVKLogging.cpp */,
|
|
||||||
A9F042AB1FB4D060009FCCB8 /* MVKLogging.h */,
|
|
||||||
A9B51BDC225E98BB00AC74D2 /* MVKOSExtensions.h */,
|
A9B51BDC225E98BB00AC74D2 /* MVKOSExtensions.h */,
|
||||||
A9B51BDB225E98BB00AC74D2 /* MVKOSExtensions.mm */,
|
A9B51BDB225E98BB00AC74D2 /* MVKOSExtensions.mm */,
|
||||||
A98149651FB6A98A005F00B4 /* MVKStrings.h */,
|
A98149651FB6A98A005F00B4 /* MVKStrings.h */,
|
||||||
@ -275,7 +266,6 @@
|
|||||||
isa = PBXHeadersBuildPhase;
|
isa = PBXHeadersBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
A9F042B41FB4D060009FCCB8 /* MVKLogging.h in Headers */,
|
|
||||||
A9C70F5F221B321700FBA31A /* SPIRVSupport.h in Headers */,
|
A9C70F5F221B321700FBA31A /* SPIRVSupport.h in Headers */,
|
||||||
A90941A51C581F840094110D /* GLSLConversion.h in Headers */,
|
A90941A51C581F840094110D /* GLSLConversion.h in Headers */,
|
||||||
A90940A91C5808BB0094110D /* GLSLToSPIRVConverter.h in Headers */,
|
A90940A91C5808BB0094110D /* GLSLToSPIRVConverter.h in Headers */,
|
||||||
@ -288,7 +278,6 @@
|
|||||||
isa = PBXHeadersBuildPhase;
|
isa = PBXHeadersBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
A9F042B51FB4D060009FCCB8 /* MVKLogging.h in Headers */,
|
|
||||||
A9C70F60221B321700FBA31A /* SPIRVSupport.h in Headers */,
|
A9C70F60221B321700FBA31A /* SPIRVSupport.h in Headers */,
|
||||||
A90941A61C581F840094110D /* GLSLConversion.h in Headers */,
|
A90941A61C581F840094110D /* GLSLConversion.h in Headers */,
|
||||||
A90940AA1C5808BB0094110D /* GLSLToSPIRVConverter.h in Headers */,
|
A90940AA1C5808BB0094110D /* GLSLToSPIRVConverter.h in Headers */,
|
||||||
@ -305,7 +294,6 @@
|
|||||||
A98149681FB6A98A005F00B4 /* MVKStrings.h in Headers */,
|
A98149681FB6A98A005F00B4 /* MVKStrings.h in Headers */,
|
||||||
A9C70F61221B321700FBA31A /* SPIRVSupport.h in Headers */,
|
A9C70F61221B321700FBA31A /* SPIRVSupport.h in Headers */,
|
||||||
A928C9191D0488DC00071B88 /* SPIRVConversion.h in Headers */,
|
A928C9191D0488DC00071B88 /* SPIRVConversion.h in Headers */,
|
||||||
A9F042B61FB4D060009FCCB8 /* MVKLogging.h in Headers */,
|
|
||||||
A909408C1C58013E0094110D /* SPIRVToMSLConverter.h in Headers */,
|
A909408C1C58013E0094110D /* SPIRVToMSLConverter.h in Headers */,
|
||||||
A9F042B21FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */,
|
A9F042B21FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */,
|
||||||
);
|
);
|
||||||
@ -320,7 +308,6 @@
|
|||||||
A9C70F62221B321700FBA31A /* SPIRVSupport.h in Headers */,
|
A9C70F62221B321700FBA31A /* SPIRVSupport.h in Headers */,
|
||||||
A928C91A1D0488DC00071B88 /* SPIRVConversion.h in Headers */,
|
A928C91A1D0488DC00071B88 /* SPIRVConversion.h in Headers */,
|
||||||
A909408D1C58013E0094110D /* SPIRVToMSLConverter.h in Headers */,
|
A909408D1C58013E0094110D /* SPIRVToMSLConverter.h in Headers */,
|
||||||
A9F042B71FB4D060009FCCB8 /* MVKLogging.h in Headers */,
|
|
||||||
A9F042B31FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */,
|
A9F042B31FB4D060009FCCB8 /* MVKCommonEnvironment.h in Headers */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@ -625,7 +612,6 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
A9E337B8220129ED00363D2A /* MVKLogging.cpp in Sources */,
|
|
||||||
A97CC7411C7527F3004A5C7E /* MoltenVKShaderConverterTool.cpp in Sources */,
|
A97CC7411C7527F3004A5C7E /* MoltenVKShaderConverterTool.cpp in Sources */,
|
||||||
A9C70F63221B321700FBA31A /* SPIRVSupport.cpp in Sources */,
|
A9C70F63221B321700FBA31A /* SPIRVSupport.cpp in Sources */,
|
||||||
A95096BF2003D32400F10950 /* OSSupport.mm in Sources */,
|
A95096BF2003D32400F10950 /* OSSupport.mm in Sources */,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user