Log error and assertion if ImageView swizzling is disabled but needed.

MVKConfiguration::fullTextureSwizzle renamed to fullImageViewSwizzle.
Env var MVK_CONFIG_FULL_TEXTURE_SWIZZLE renamed to MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE.
Refactor MVKResourcesCommandEncoderState swizzle updates.
Add mvkPackSwizzle(), mvkUnpackSwizzle() & mvkVkComponentSwizzleName() and remove from MVKImage.
Refactor mvkVkResultName() to use literal strings.
This commit is contained in:
Bill Hollings 2019-01-14 17:36:39 -05:00
parent 0f9aabfc7b
commit a7ab108166
12 changed files with 165 additions and 118 deletions

View File

@ -16,10 +16,10 @@ For best results, use a Markdown reader.*
MoltenVK 1.0.31
---------------
Released 2018/01/12
Released 2018/01/15
- Support runtime config via runtime environment variables
- Add full texture swizzling to config, and disable it by default.
- Add full ImageView swizzling to config, and disable it by default.
- Add GPU switching to config, and enable it by default.
- Add queue family specialization to config, and disable it by default.
- Enable synchronous queue submits as config default.

View File

@ -375,15 +375,17 @@ typedef struct {
VkBool32 switchSystemGPU;
/**
* If enabled, arbitrary per-texture swizzles are supported, as defined in
* VkImageViewCreateInfo::components when creating a VkImageView.
* If enabled, arbitrary ImageView component swizzles are supported, as defined
* in VkImageViewCreateInfo::components when creating a VkImageView.
*
* If disabled, a very limited set of per-texture swizzles are supported
* If disabled, a very limited set of ImageView component swizzles are supported
* via format substitutions.
*
* Metal does not natively support per-texture swizzling. If this parameter is enabled,
* per-texture swizzling is performed in shader code during textures sampling and reading,
* regardless of whether a swizzle has been specified, which may result in reduced performance.
* Metal does not natively support per-texture swizzling. If this parameter is enabled
* when a pipeline is compiled, ImageView swizzling is automatically performed in the
* converted Metal shader code during all texture sampling and reading operations,
* regardless of whether a swizzle has been specified for the ImageView associated
* with the Metal texture. This may result in reduced performance.
*
* The value of this parameter may be changed at any time during application runtime,
* and the changed value will immediately effect subsequent MoltenVK behaviour.
@ -391,7 +393,7 @@ typedef struct {
* and disabled when compiling others. Existing pipelines are not automatically
* re-compiled when this parameter is changed.
*
* If this parameter is disabled, the following limited set of per-texture swizzles
* If this parameter is disabled, the following limited set of ImageView swizzles
* are supported by MoltenVK, via automatic format substitution:
*
* Texture format Swizzle
@ -406,11 +408,11 @@ typedef struct {
* VK_FORMAT_D24_UNORM_S8_UINT RED, ANY, ANY, ANY (stencil only)
*
* The initial value or this parameter is set by the
* MVK_CONFIG_FULL_TEXTURE_SWIZZLE
* MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE
* runtime environment variable or MoltenVK compile-time build setting.
* If neither is set, the value of this parameter defaults to false.
*/
VkBool32 fullTextureSwizzle;
VkBool32 fullImageViewSwizzle;
} MVKConfiguration;

View File

@ -351,7 +351,7 @@ void MVKCommandEncoder::clearRenderArea() {
}
void MVKCommandEncoder::finalizeDispatchState() {
_computePipelineState.encode();
_computePipelineState.encode(); // Must do first..it sets others
_computeResourcesState.encode();
_computePushConstants.encode();
}

View File

@ -374,6 +374,13 @@ protected:
bindings.push_back(db);
}
// For texture bindings, we also keep track of whether any bindings need a texture swizzle
void bind(const MVKMTLTextureBinding& tb, MVKVector<MVKMTLTextureBinding>& texBindings,
bool& bindingsDirtyFlag, bool& needsSwizzleFlag) {
bind(tb, texBindings, bindingsDirtyFlag);
if (tb.swizzle != 0) { needsSwizzleFlag = true; }
}
// Template function that executes a lambda expression on each dirty element of
// a vector of bindings, and marks the bindings and the vector as no longer dirty.
template<class T>
@ -391,11 +398,6 @@ protected:
}
}
// Updates the swizzle for an image in the given vector.
void updateSwizzle(MVKVector<uint32_t> &constants, uint32_t index, uint32_t swizzle) {
if (index >= constants.size()) { constants.resize(index + 1); }
constants[index] = swizzle;
}
};
@ -466,6 +468,9 @@ protected:
bool _areFragmentTextureBindingsDirty = false;
bool _areVertexSamplerStateBindingsDirty = false;
bool _areFragmentSamplerStateBindingsDirty = false;
bool _needsVertexSwizzle = false;
bool _needsFragmentSwizzle = false;
};
@ -508,6 +513,8 @@ protected:
bool _areBufferBindingsDirty = false;
bool _areTextureBindingsDirty = false;
bool _areSamplerStateBindingsDirty = false;
bool _needsSwizzle = false;
};

View File

@ -398,6 +398,31 @@ void MVKBlendColorCommandEncoderState::resetImpl() {
}
#pragma mark -
#pragma mark MVKResourcesCommandEncoderState
// Updates the swizzle for an image in the given vector.
static void updateSwizzle(MVKVector<uint32_t> &constants, uint32_t index, uint32_t swizzle) {
if (index >= constants.size()) { constants.resize(index + 1); }
constants[index] = swizzle;
}
// If a swizzle is needed for this stage, iterates all the bindings and logs errors for those that need texture swizzling.
static void assertMissingSwizzles(bool needsSwizzle, const char* stageName, MVKVector<MVKMTLTextureBinding>& texBindings) {
if (needsSwizzle) {
for (MVKMTLTextureBinding& tb : texBindings) {
VkComponentMapping vkcm = mvkUnpackSwizzle(tb.swizzle);
MVKLogError("Pipeline does not support component swizzle (%s, %s, %s, %s) required by a VkImageView used in the %s shader."
" Full VkImageView component swizzling will be supported by a pipeline if the MVKConfiguration::fullImageViewSwizzle"
" config parameter or MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE environment variable was enabled when the pipeline is compiled.",
mvkVkComponentSwizzleName(vkcm.r), mvkVkComponentSwizzleName(vkcm.g),
mvkVkComponentSwizzleName(vkcm.b), mvkVkComponentSwizzleName(vkcm.a), stageName);
MVKAssert(false, "See previous logged error.");
}
}
}
#pragma mark -
#pragma mark MVKGraphicsResourcesCommandEncoderState
@ -410,11 +435,11 @@ void MVKGraphicsResourcesCommandEncoderState::bindFragmentBuffer(const MVKMTLBuf
}
void MVKGraphicsResourcesCommandEncoderState::bindVertexTexture(const MVKMTLTextureBinding& binding) {
bind(binding, _vertexTextureBindings, _areVertexTextureBindingsDirty);
bind(binding, _vertexTextureBindings, _areVertexTextureBindingsDirty, _needsVertexSwizzle);
}
void MVKGraphicsResourcesCommandEncoderState::bindFragmentTexture(const MVKMTLTextureBinding& binding) {
bind(binding, _fragmentTextureBindings, _areFragmentTextureBindingsDirty);
bind(binding, _fragmentTextureBindings, _areFragmentTextureBindingsDirty, _needsFragmentSwizzle);
}
void MVKGraphicsResourcesCommandEncoderState::bindVertexSamplerState(const MVKMTLSamplerStateBinding& binding) {
@ -447,20 +472,6 @@ void MVKGraphicsResourcesCommandEncoderState::markDirty() {
void MVKGraphicsResourcesCommandEncoderState::encodeImpl() {
if (_vertexAuxBufferBinding.isDirty) {
for (auto& b : _vertexTextureBindings) {
if (b.isDirty)
updateSwizzle(_vertexSwizzleConstants, b.index, b.swizzle);
}
}
if (_fragmentAuxBufferBinding.isDirty) {
for (auto& b : _fragmentTextureBindings) {
if (b.isDirty)
updateSwizzle(_fragmentSwizzleConstants, b.index, b.swizzle);
}
}
encodeBinding<MVKMTLBufferBinding>(_vertexBufferBindings, _areVertexBufferBindingsDirty,
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: b.mtlBuffer
@ -476,17 +487,33 @@ void MVKGraphicsResourcesCommandEncoderState::encodeImpl() {
});
if (_vertexAuxBufferBinding.isDirty) {
for (auto& b : _vertexTextureBindings) {
if (b.isDirty) { updateSwizzle(_vertexSwizzleConstants, b.index, b.swizzle); }
}
_cmdEncoder->setVertexBytes(_cmdEncoder->_mtlRenderEncoder,
_vertexSwizzleConstants.data(),
_vertexSwizzleConstants.size() * sizeof(uint32_t),
_vertexAuxBufferBinding.index);
} else {
assertMissingSwizzles(_needsVertexSwizzle, "vertex", _vertexTextureBindings);
}
if (_fragmentAuxBufferBinding.isDirty) {
for (auto& b : _fragmentTextureBindings) {
if (b.isDirty) { updateSwizzle(_fragmentSwizzleConstants, b.index, b.swizzle); }
}
_cmdEncoder->setFragmentBytes(_cmdEncoder->_mtlRenderEncoder,
_fragmentSwizzleConstants.data(),
_fragmentSwizzleConstants.size() * sizeof(uint32_t),
_fragmentAuxBufferBinding.index);
} else {
assertMissingSwizzles(_needsFragmentSwizzle, "fragment", _fragmentTextureBindings);
}
encodeBinding<MVKMTLTextureBinding>(_vertexTextureBindings, _areVertexTextureBindingsDirty,
@ -532,6 +559,9 @@ void MVKGraphicsResourcesCommandEncoderState::resetImpl() {
_areFragmentSamplerStateBindingsDirty = false;
_vertexAuxBufferBinding.isDirty = false;
_fragmentAuxBufferBinding.isDirty = false;
_needsVertexSwizzle = false;
_needsFragmentSwizzle = false;
}
@ -543,7 +573,7 @@ void MVKComputeResourcesCommandEncoderState::bindBuffer(const MVKMTLBufferBindin
}
void MVKComputeResourcesCommandEncoderState::bindTexture(const MVKMTLTextureBinding& binding) {
bind(binding, _textureBindings, _areTextureBindingsDirty);
bind(binding, _textureBindings, _areTextureBindingsDirty, _needsSwizzle);
}
void MVKComputeResourcesCommandEncoderState::bindSamplerState(const MVKMTLSamplerStateBinding& binding) {
@ -566,13 +596,6 @@ void MVKComputeResourcesCommandEncoderState::markDirty() {
void MVKComputeResourcesCommandEncoderState::encodeImpl() {
if (_auxBufferBinding.isDirty) {
for (auto& b : _textureBindings) {
if (b.isDirty)
updateSwizzle(_swizzleConstants, b.index, b.swizzle);
}
}
encodeBinding<MVKMTLBufferBinding>(_bufferBindings, _areBufferBindingsDirty,
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
[cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch) setBuffer: b.mtlBuffer
@ -581,10 +604,18 @@ void MVKComputeResourcesCommandEncoderState::encodeImpl() {
});
if (_auxBufferBinding.isDirty) {
for (auto& b : _textureBindings) {
if (b.isDirty) { updateSwizzle(_swizzleConstants, b.index, b.swizzle); }
}
_cmdEncoder->setComputeBytes(_cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch),
_swizzleConstants.data(),
_swizzleConstants.size() * sizeof(uint32_t),
_auxBufferBinding.index);
} else {
assertMissingSwizzles(_needsSwizzle, "compute", _textureBindings);
}
encodeBinding<MVKMTLTextureBinding>(_textureBindings, _areTextureBindingsDirty,
@ -610,6 +641,8 @@ void MVKComputeResourcesCommandEncoderState::resetImpl() {
_areTextureBindingsDirty = false;
_areSamplerStateBindingsDirty = false;
_auxBufferBinding.isDirty = false;
_needsSwizzle = false;
}

View File

@ -289,8 +289,6 @@ protected:
void initMTLTextureViewSupport();
MTLPixelFormat getSwizzledMTLPixelFormat(VkFormat format, VkComponentMapping components, bool& useSwizzle);
bool matchesSwizzle(VkComponentMapping components, VkComponentMapping pattern);
const char* getSwizzleName(VkComponentSwizzle swizzle);
uint32_t packSwizzle(VkComponentMapping components);
void validateImageViewConfig(const VkImageViewCreateInfo* pCreateInfo);
MVKImage* _image;

View File

@ -798,7 +798,7 @@ MVKImageView::MVKImageView(MVKDevice* device, const VkImageViewCreateInfo* pCrea
_mtlPixelFormat = getSwizzledMTLPixelFormat(pCreateInfo->format, pCreateInfo->components, useSwizzle);
_mtlTextureType = mvkMTLTextureTypeFromVkImageViewType(pCreateInfo->viewType, (_image->getSampleCount() != VK_SAMPLE_COUNT_1_BIT));
initMTLTextureViewSupport();
_packedSwizzle = useSwizzle ? packSwizzle(pCreateInfo->components) : 0;
_packedSwizzle = useSwizzle ? mvkPackSwizzle(pCreateInfo->components) : 0;
}
// Validate whether the image view configuration can be supported
@ -896,19 +896,6 @@ MTLPixelFormat MVKImageView::getSwizzledMTLPixelFormat(VkFormat format, VkCompon
return mtlPF;
}
const char* MVKImageView::getSwizzleName(VkComponentSwizzle swizzle) {
switch (swizzle) {
case VK_COMPONENT_SWIZZLE_IDENTITY: return "VK_COMPONENT_SWIZZLE_IDENTITY";
case VK_COMPONENT_SWIZZLE_ZERO: return "VK_COMPONENT_SWIZZLE_ZERO";
case VK_COMPONENT_SWIZZLE_ONE: return "VK_COMPONENT_SWIZZLE_ONE";
case VK_COMPONENT_SWIZZLE_R: return "VK_COMPONENT_SWIZZLE_R";
case VK_COMPONENT_SWIZZLE_G: return "VK_COMPONENT_SWIZZLE_G";
case VK_COMPONENT_SWIZZLE_B: return "VK_COMPONENT_SWIZZLE_B";
case VK_COMPONENT_SWIZZLE_A: return "VK_COMPONENT_SWIZZLE_A";
default: return "VK_COMPONENT_SWIZZLE_UNKNOWN";
}
}
// Returns whether the swizzle components of the internal VkComponentMapping matches the
// swizzle pattern, by comparing corresponding elements of the two structures. The pattern
// supports wildcards, in that any element of pattern can be set to VK_COMPONENT_SWIZZLE_MAX_ENUM
@ -926,12 +913,6 @@ bool MVKImageView::matchesSwizzle(VkComponentMapping components, VkComponentMapp
return true;
}
// Packs a VkComponentMapping structure into a single 32-bit word.
uint32_t MVKImageView::packSwizzle(VkComponentMapping components) {
return ((components.r & 0xFF) << 0) | ((components.g & 0xFF) << 8) |
((components.b & 0xFF) << 16) | ((components.a & 0xFF) << 24);
}
// Determine whether this image view should use a Metal texture view,
// and set the _useMTLTextureView variable appropriately.
void MVKImageView::initMTLTextureViewSupport() {

View File

@ -366,7 +366,7 @@ void MVKInstance::initConfig() {
MVK_SET_FROM_ENV_OR_BUILD_BOOL( _mvkConfig.displayWatermark, MVK_CONFIG_DISPLAY_WATERMARK);
MVK_SET_FROM_ENV_OR_BUILD_BOOL( _mvkConfig.specializedQueueFamilies, MVK_CONFIG_SPECIALIZED_QUEUE_FAMILIES);
MVK_SET_FROM_ENV_OR_BUILD_BOOL( _mvkConfig.switchSystemGPU, MVK_CONFIG_SWITCH_SYSTEM_GPU);
MVK_SET_FROM_ENV_OR_BUILD_BOOL( _mvkConfig.fullTextureSwizzle, MVK_CONFIG_FULL_TEXTURE_SWIZZLE);
MVK_SET_FROM_ENV_OR_BUILD_BOOL( _mvkConfig.fullImageViewSwizzle, MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE);
}
VkResult MVKInstance::verifyLayers(uint32_t count, const char* const* names) {

View File

@ -324,7 +324,7 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor
shaderContext.options.entryPointName = pSS->pName;
id<MTLFunction> mtlFunction = ((MVKShaderModule*)pSS->module)->getMTLFunction(&shaderContext, pSS->pSpecializationInfo, _pipelineCache).mtlFunction;
if ( !mtlFunction ) {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader function could not be compiled into pipeline. See previous error."));
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader function could not be compiled into pipeline. See previous logged error."));
return nil;
}
plDesc.vertexFunction = mtlFunction;
@ -347,7 +347,7 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor
shaderContext.options.entryPointName = pSS->pName;
id<MTLFunction> mtlFunction = ((MVKShaderModule*)pSS->module)->getMTLFunction(&shaderContext, pSS->pSpecializationInfo, _pipelineCache).mtlFunction;
if ( !mtlFunction ) {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Fragment shader function could not be compiled into pipeline. See previous error."));
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Fragment shader function could not be compiled into pipeline. See previous logged error."));
}
plDesc.fragmentFunction = mtlFunction;
_needsFragmentAuxBuffer = shaderContext.options.needsAuxBuffer;
@ -484,7 +484,7 @@ void MVKGraphicsPipeline::initMVKShaderConverterContext(SPIRVToMSLConverterConte
shaderContext.options.isRenderingPoints = isRenderingPoints(pCreateInfo);
shaderContext.options.isRasterizationDisabled = (pCreateInfo->pRasterizationState && (pCreateInfo->pRasterizationState->rasterizerDiscardEnable));
shaderContext.options.shouldFlipVertexY = _device->_pMVKConfig->shaderConversionFlipVertexY;
shaderContext.options.shouldSwizzleTextureSamples = _device->_pMVKConfig->fullTextureSwizzle;
shaderContext.options.shouldSwizzleTextureSamples = _device->_pMVKConfig->fullImageViewSwizzle;
// Set the shader context vertex attribute information
shaderContext.vertexAttributes.clear();
@ -581,7 +581,7 @@ MVKComputePipeline::MVKComputePipeline(MVKDevice* device,
setConfigurationResult(plc->getConfigurationResult());
plc->destroy();
} else {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Compute shader function could not be compiled into pipeline. See previous error."));
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Compute shader function could not be compiled into pipeline. See previous logged error."));
}
if (_needsAuxBuffer && _auxBufferIndex.compute == ~0u) {
@ -599,7 +599,7 @@ MVKMTLFunction MVKComputePipeline::getMTLFunction(const VkComputePipelineCreateI
shaderContext.options.entryPointName = pCreateInfo->stage.pName;
shaderContext.options.entryPointStage = spv::ExecutionModelGLCompute;
shaderContext.options.mslVersion = _device->_pMetalFeatures->mslVersion;
shaderContext.options.shouldSwizzleTextureSamples = _device->_pMVKConfig->fullTextureSwizzle;
shaderContext.options.shouldSwizzleTextureSamples = _device->_pMVKConfig->fullImageViewSwizzle;
MVKPipelineLayout* layout = (MVKPipelineLayout*)pCreateInfo->layout;
layout->populateShaderConverterContext(shaderContext);

View File

@ -107,9 +107,9 @@
# define MVK_CONFIG_SWITCH_SYSTEM_GPU 1
#endif
/** Support full per-texture swizzles. Disabled by default. */
#ifndef MVK_CONFIG_FULL_TEXTURE_SWIZZLE
# define MVK_CONFIG_FULL_TEXTURE_SWIZZLE 0
/** Support full ImageView swizzles. Disabled by default. */
#ifndef MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE
# define MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE 0
#endif

View File

@ -19,45 +19,59 @@
#include "MVKFoundation.h"
#include "MVKLogging.h"
#define CASE_RESULT(R) case R: return strcpy(name, #R);
char* mvkResultName(VkResult vkResult, char* name) {
#define CASE_STRINGIFY(V) case V: return #V
const char* mvkVkResultName(VkResult vkResult) {
switch (vkResult) {
CASE_RESULT(VK_SUCCESS)
CASE_RESULT(VK_NOT_READY)
CASE_RESULT(VK_TIMEOUT)
CASE_RESULT(VK_EVENT_SET)
CASE_RESULT(VK_EVENT_RESET)
CASE_RESULT(VK_INCOMPLETE)
CASE_RESULT(VK_ERROR_OUT_OF_HOST_MEMORY)
CASE_RESULT(VK_ERROR_OUT_OF_DEVICE_MEMORY)
CASE_RESULT(VK_ERROR_INITIALIZATION_FAILED)
CASE_RESULT(VK_ERROR_DEVICE_LOST)
CASE_RESULT(VK_ERROR_MEMORY_MAP_FAILED)
CASE_RESULT(VK_ERROR_LAYER_NOT_PRESENT)
CASE_RESULT(VK_ERROR_EXTENSION_NOT_PRESENT)
CASE_RESULT(VK_ERROR_FEATURE_NOT_PRESENT)
CASE_RESULT(VK_ERROR_INCOMPATIBLE_DRIVER)
CASE_RESULT(VK_ERROR_TOO_MANY_OBJECTS)
CASE_RESULT(VK_ERROR_FORMAT_NOT_SUPPORTED)
CASE_RESULT(VK_ERROR_FRAGMENTED_POOL)
CASE_STRINGIFY(VK_SUCCESS);
CASE_STRINGIFY(VK_NOT_READY);
CASE_STRINGIFY(VK_TIMEOUT);
CASE_STRINGIFY(VK_EVENT_SET);
CASE_STRINGIFY(VK_EVENT_RESET);
CASE_STRINGIFY(VK_INCOMPLETE);
CASE_RESULT(VK_ERROR_SURFACE_LOST_KHR)
CASE_RESULT(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR)
CASE_RESULT(VK_SUBOPTIMAL_KHR)
CASE_RESULT(VK_ERROR_OUT_OF_DATE_KHR)
CASE_RESULT(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR)
CASE_STRINGIFY(VK_ERROR_OUT_OF_HOST_MEMORY);
CASE_STRINGIFY(VK_ERROR_OUT_OF_DEVICE_MEMORY);
CASE_STRINGIFY(VK_ERROR_INITIALIZATION_FAILED);
CASE_STRINGIFY(VK_ERROR_DEVICE_LOST);
CASE_STRINGIFY(VK_ERROR_MEMORY_MAP_FAILED);
CASE_STRINGIFY(VK_ERROR_LAYER_NOT_PRESENT);
CASE_STRINGIFY(VK_ERROR_EXTENSION_NOT_PRESENT);
CASE_STRINGIFY(VK_ERROR_FEATURE_NOT_PRESENT);
CASE_STRINGIFY(VK_ERROR_INCOMPATIBLE_DRIVER);
CASE_STRINGIFY(VK_ERROR_TOO_MANY_OBJECTS);
CASE_STRINGIFY(VK_ERROR_FORMAT_NOT_SUPPORTED);
CASE_STRINGIFY(VK_ERROR_FRAGMENTED_POOL);
CASE_RESULT(VK_ERROR_VALIDATION_FAILED_EXT)
CASE_RESULT(VK_ERROR_INVALID_SHADER_NV)
CASE_STRINGIFY(VK_ERROR_SURFACE_LOST_KHR);
CASE_STRINGIFY(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
CASE_STRINGIFY(VK_SUBOPTIMAL_KHR);
CASE_STRINGIFY(VK_ERROR_OUT_OF_DATE_KHR);
CASE_STRINGIFY(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
CASE_RESULT(VK_ERROR_OUT_OF_POOL_MEMORY)
CASE_RESULT(VK_ERROR_INVALID_EXTERNAL_HANDLE)
CASE_STRINGIFY(VK_ERROR_VALIDATION_FAILED_EXT);
CASE_STRINGIFY(VK_ERROR_INVALID_SHADER_NV);
default:
sprintf(name, "UNKNOWN_VkResult(%d)", vkResult);
return name;
CASE_STRINGIFY(VK_ERROR_OUT_OF_POOL_MEMORY);
CASE_STRINGIFY(VK_ERROR_INVALID_EXTERNAL_HANDLE);
default: return "VK_UNKNOWN_VK_Result";
}
}
const char* mvkVkComponentSwizzleName(VkComponentSwizzle swizzle) {
switch (swizzle) {
CASE_STRINGIFY(VK_COMPONENT_SWIZZLE_IDENTITY);
CASE_STRINGIFY(VK_COMPONENT_SWIZZLE_ZERO);
CASE_STRINGIFY(VK_COMPONENT_SWIZZLE_ONE);
CASE_STRINGIFY(VK_COMPONENT_SWIZZLE_R);
CASE_STRINGIFY(VK_COMPONENT_SWIZZLE_G);
CASE_STRINGIFY(VK_COMPONENT_SWIZZLE_B);
CASE_STRINGIFY(VK_COMPONENT_SWIZZLE_A);
default: return "VK_UNKNOWN_VKComponentSwizzle";
}
}
@ -65,10 +79,8 @@ VkResult mvkNotifyErrorWithText(VkResult vkErr, const char* errFmt, ...) {
va_list args;
va_start(args, errFmt);
char vkRsltName[MVKResultNameMaxLen];
mvkResultName(vkErr, vkRsltName);
// 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);

View File

@ -100,13 +100,11 @@ typedef enum {
kMVKCommandUseDispatch, /**< vkCmdDispatch. */
} MVKCommandUse;
/**
* Copies the name of the specified VkResult code to the specified string.
*
* Returns a pointer to that string.
*/
#define MVKResultNameMaxLen 64
char* mvkResultName(VkResult vkResult, char* name);
/** Returns the name of the result value. */
const char* mvkVkResultName(VkResult vkResult);
/** Returns the name of the component swizzle. */
const char* mvkVkComponentSwizzleName(VkComponentSwizzle swizzle);
/**
* Notifies the app of an error code and error message, via the following methods:
@ -260,6 +258,22 @@ static inline VkOffset3D mvkVkOffset3DDifference(VkOffset3D minuend, VkOffset3D
return rslt;
}
/** Packs the four swizzle components into a single 32-bit word. */
static inline uint32_t mvkPackSwizzle(VkComponentMapping components) {
return ((components.r & 0xFF) << 0) | ((components.g & 0xFF) << 8) |
((components.b & 0xFF) << 16) | ((components.a & 0xFF) << 24);
}
/** Unpacks a single 32-bit word containing four swizzle components. */
static inline VkComponentMapping mvkUnpackSwizzle(uint32_t packed) {
VkComponentMapping components;
components.r = (VkComponentSwizzle)((packed >> 0) & 0xFF);
components.g = (VkComponentSwizzle)((packed >> 8) & 0xFF);
components.b = (VkComponentSwizzle)((packed >> 16) & 0xFF);
components.a = (VkComponentSwizzle)((packed >> 24) & 0xFF);
return components;
}
#pragma mark -
#pragma mark Template functions