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 MoltenVK 1.0.31
--------------- ---------------
Released 2018/01/12 Released 2018/01/15
- Support runtime config via runtime environment variables - 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 GPU switching to config, and enable it by default.
- Add queue family specialization to config, and disable it by default. - Add queue family specialization to config, and disable it by default.
- Enable synchronous queue submits as config default. - Enable synchronous queue submits as config default.

View File

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

View File

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

View File

@ -374,6 +374,13 @@ protected:
bindings.push_back(db); 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 // 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. // a vector of bindings, and marks the bindings and the vector as no longer dirty.
template<class T> 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 _areFragmentTextureBindingsDirty = false;
bool _areVertexSamplerStateBindingsDirty = false; bool _areVertexSamplerStateBindingsDirty = false;
bool _areFragmentSamplerStateBindingsDirty = false; bool _areFragmentSamplerStateBindingsDirty = false;
bool _needsVertexSwizzle = false;
bool _needsFragmentSwizzle = false;
}; };
@ -508,6 +513,8 @@ protected:
bool _areBufferBindingsDirty = false; bool _areBufferBindingsDirty = false;
bool _areTextureBindingsDirty = false; bool _areTextureBindingsDirty = false;
bool _areSamplerStateBindingsDirty = 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 -
#pragma mark MVKGraphicsResourcesCommandEncoderState #pragma mark MVKGraphicsResourcesCommandEncoderState
@ -410,11 +435,11 @@ void MVKGraphicsResourcesCommandEncoderState::bindFragmentBuffer(const MVKMTLBuf
} }
void MVKGraphicsResourcesCommandEncoderState::bindVertexTexture(const MVKMTLTextureBinding& binding) { void MVKGraphicsResourcesCommandEncoderState::bindVertexTexture(const MVKMTLTextureBinding& binding) {
bind(binding, _vertexTextureBindings, _areVertexTextureBindingsDirty); bind(binding, _vertexTextureBindings, _areVertexTextureBindingsDirty, _needsVertexSwizzle);
} }
void MVKGraphicsResourcesCommandEncoderState::bindFragmentTexture(const MVKMTLTextureBinding& binding) { void MVKGraphicsResourcesCommandEncoderState::bindFragmentTexture(const MVKMTLTextureBinding& binding) {
bind(binding, _fragmentTextureBindings, _areFragmentTextureBindingsDirty); bind(binding, _fragmentTextureBindings, _areFragmentTextureBindingsDirty, _needsFragmentSwizzle);
} }
void MVKGraphicsResourcesCommandEncoderState::bindVertexSamplerState(const MVKMTLSamplerStateBinding& binding) { void MVKGraphicsResourcesCommandEncoderState::bindVertexSamplerState(const MVKMTLSamplerStateBinding& binding) {
@ -447,20 +472,6 @@ void MVKGraphicsResourcesCommandEncoderState::markDirty() {
void MVKGraphicsResourcesCommandEncoderState::encodeImpl() { 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, encodeBinding<MVKMTLBufferBinding>(_vertexBufferBindings, _areVertexBufferBindingsDirty,
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void { [](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: b.mtlBuffer [cmdEncoder->_mtlRenderEncoder setVertexBuffer: b.mtlBuffer
@ -476,17 +487,33 @@ void MVKGraphicsResourcesCommandEncoderState::encodeImpl() {
}); });
if (_vertexAuxBufferBinding.isDirty) { if (_vertexAuxBufferBinding.isDirty) {
_cmdEncoder->setVertexBytes(_cmdEncoder->_mtlRenderEncoder,
for (auto& b : _vertexTextureBindings) {
if (b.isDirty) { updateSwizzle(_vertexSwizzleConstants, b.index, b.swizzle); }
}
_cmdEncoder->setVertexBytes(_cmdEncoder->_mtlRenderEncoder,
_vertexSwizzleConstants.data(), _vertexSwizzleConstants.data(),
_vertexSwizzleConstants.size() * sizeof(uint32_t), _vertexSwizzleConstants.size() * sizeof(uint32_t),
_vertexAuxBufferBinding.index); _vertexAuxBufferBinding.index);
}
} else {
assertMissingSwizzles(_needsVertexSwizzle, "vertex", _vertexTextureBindings);
}
if (_fragmentAuxBufferBinding.isDirty) { if (_fragmentAuxBufferBinding.isDirty) {
_cmdEncoder->setFragmentBytes(_cmdEncoder->_mtlRenderEncoder,
for (auto& b : _fragmentTextureBindings) {
if (b.isDirty) { updateSwizzle(_fragmentSwizzleConstants, b.index, b.swizzle); }
}
_cmdEncoder->setFragmentBytes(_cmdEncoder->_mtlRenderEncoder,
_fragmentSwizzleConstants.data(), _fragmentSwizzleConstants.data(),
_fragmentSwizzleConstants.size() * sizeof(uint32_t), _fragmentSwizzleConstants.size() * sizeof(uint32_t),
_fragmentAuxBufferBinding.index); _fragmentAuxBufferBinding.index);
} else {
assertMissingSwizzles(_needsFragmentSwizzle, "fragment", _fragmentTextureBindings);
} }
encodeBinding<MVKMTLTextureBinding>(_vertexTextureBindings, _areVertexTextureBindingsDirty, encodeBinding<MVKMTLTextureBinding>(_vertexTextureBindings, _areVertexTextureBindingsDirty,
@ -532,6 +559,9 @@ void MVKGraphicsResourcesCommandEncoderState::resetImpl() {
_areFragmentSamplerStateBindingsDirty = false; _areFragmentSamplerStateBindingsDirty = false;
_vertexAuxBufferBinding.isDirty = false; _vertexAuxBufferBinding.isDirty = false;
_fragmentAuxBufferBinding.isDirty = false; _fragmentAuxBufferBinding.isDirty = false;
_needsVertexSwizzle = false;
_needsFragmentSwizzle = false;
} }
@ -543,7 +573,7 @@ void MVKComputeResourcesCommandEncoderState::bindBuffer(const MVKMTLBufferBindin
} }
void MVKComputeResourcesCommandEncoderState::bindTexture(const MVKMTLTextureBinding& binding) { void MVKComputeResourcesCommandEncoderState::bindTexture(const MVKMTLTextureBinding& binding) {
bind(binding, _textureBindings, _areTextureBindingsDirty); bind(binding, _textureBindings, _areTextureBindingsDirty, _needsSwizzle);
} }
void MVKComputeResourcesCommandEncoderState::bindSamplerState(const MVKMTLSamplerStateBinding& binding) { void MVKComputeResourcesCommandEncoderState::bindSamplerState(const MVKMTLSamplerStateBinding& binding) {
@ -566,13 +596,6 @@ void MVKComputeResourcesCommandEncoderState::markDirty() {
void MVKComputeResourcesCommandEncoderState::encodeImpl() { void MVKComputeResourcesCommandEncoderState::encodeImpl() {
if (_auxBufferBinding.isDirty) {
for (auto& b : _textureBindings) {
if (b.isDirty)
updateSwizzle(_swizzleConstants, b.index, b.swizzle);
}
}
encodeBinding<MVKMTLBufferBinding>(_bufferBindings, _areBufferBindingsDirty, encodeBinding<MVKMTLBufferBinding>(_bufferBindings, _areBufferBindingsDirty,
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void { [](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
[cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch) setBuffer: b.mtlBuffer [cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch) setBuffer: b.mtlBuffer
@ -581,10 +604,18 @@ void MVKComputeResourcesCommandEncoderState::encodeImpl() {
}); });
if (_auxBufferBinding.isDirty) { if (_auxBufferBinding.isDirty) {
_cmdEncoder->setComputeBytes(_cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch),
for (auto& b : _textureBindings) {
if (b.isDirty) { updateSwizzle(_swizzleConstants, b.index, b.swizzle); }
}
_cmdEncoder->setComputeBytes(_cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch),
_swizzleConstants.data(), _swizzleConstants.data(),
_swizzleConstants.size() * sizeof(uint32_t), _swizzleConstants.size() * sizeof(uint32_t),
_auxBufferBinding.index); _auxBufferBinding.index);
} else {
assertMissingSwizzles(_needsSwizzle, "compute", _textureBindings);
} }
encodeBinding<MVKMTLTextureBinding>(_textureBindings, _areTextureBindingsDirty, encodeBinding<MVKMTLTextureBinding>(_textureBindings, _areTextureBindingsDirty,
@ -610,6 +641,8 @@ void MVKComputeResourcesCommandEncoderState::resetImpl() {
_areTextureBindingsDirty = false; _areTextureBindingsDirty = false;
_areSamplerStateBindingsDirty = false; _areSamplerStateBindingsDirty = false;
_auxBufferBinding.isDirty = false; _auxBufferBinding.isDirty = false;
_needsSwizzle = false;
} }

View File

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

View File

@ -798,7 +798,7 @@ MVKImageView::MVKImageView(MVKDevice* device, const VkImageViewCreateInfo* pCrea
_mtlPixelFormat = getSwizzledMTLPixelFormat(pCreateInfo->format, pCreateInfo->components, useSwizzle); _mtlPixelFormat = getSwizzledMTLPixelFormat(pCreateInfo->format, pCreateInfo->components, useSwizzle);
_mtlTextureType = mvkMTLTextureTypeFromVkImageViewType(pCreateInfo->viewType, (_image->getSampleCount() != VK_SAMPLE_COUNT_1_BIT)); _mtlTextureType = mvkMTLTextureTypeFromVkImageViewType(pCreateInfo->viewType, (_image->getSampleCount() != VK_SAMPLE_COUNT_1_BIT));
initMTLTextureViewSupport(); initMTLTextureViewSupport();
_packedSwizzle = useSwizzle ? packSwizzle(pCreateInfo->components) : 0; _packedSwizzle = useSwizzle ? mvkPackSwizzle(pCreateInfo->components) : 0;
} }
// Validate whether the image view configuration can be supported // Validate whether the image view configuration can be supported
@ -896,19 +896,6 @@ MTLPixelFormat MVKImageView::getSwizzledMTLPixelFormat(VkFormat format, VkCompon
return mtlPF; 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 // Returns whether the swizzle components of the internal VkComponentMapping matches the
// swizzle pattern, by comparing corresponding elements of the two structures. The pattern // 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 // 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; 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, // Determine whether this image view should use a Metal texture view,
// and set the _useMTLTextureView variable appropriately. // and set the _useMTLTextureView variable appropriately.
void MVKImageView::initMTLTextureViewSupport() { 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.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.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.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) { VkResult MVKInstance::verifyLayers(uint32_t count, const char* const* names) {

View File

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

View File

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

View File

@ -19,45 +19,59 @@
#include "MVKFoundation.h" #include "MVKFoundation.h"
#include "MVKLogging.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) { 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_STRINGIFY(VK_SUCCESS);
CASE_RESULT(VK_ERROR_OUT_OF_DEVICE_MEMORY) CASE_STRINGIFY(VK_NOT_READY);
CASE_RESULT(VK_ERROR_INITIALIZATION_FAILED) CASE_STRINGIFY(VK_TIMEOUT);
CASE_RESULT(VK_ERROR_DEVICE_LOST) CASE_STRINGIFY(VK_EVENT_SET);
CASE_RESULT(VK_ERROR_MEMORY_MAP_FAILED) CASE_STRINGIFY(VK_EVENT_RESET);
CASE_RESULT(VK_ERROR_LAYER_NOT_PRESENT) CASE_STRINGIFY(VK_INCOMPLETE);
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_RESULT(VK_ERROR_SURFACE_LOST_KHR) CASE_STRINGIFY(VK_ERROR_OUT_OF_HOST_MEMORY);
CASE_RESULT(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR) CASE_STRINGIFY(VK_ERROR_OUT_OF_DEVICE_MEMORY);
CASE_RESULT(VK_SUBOPTIMAL_KHR) CASE_STRINGIFY(VK_ERROR_INITIALIZATION_FAILED);
CASE_RESULT(VK_ERROR_OUT_OF_DATE_KHR) CASE_STRINGIFY(VK_ERROR_DEVICE_LOST);
CASE_RESULT(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR) 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_STRINGIFY(VK_ERROR_SURFACE_LOST_KHR);
CASE_RESULT(VK_ERROR_INVALID_SHADER_NV) 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_STRINGIFY(VK_ERROR_VALIDATION_FAILED_EXT);
CASE_RESULT(VK_ERROR_INVALID_EXTERNAL_HANDLE) CASE_STRINGIFY(VK_ERROR_INVALID_SHADER_NV);
default: CASE_STRINGIFY(VK_ERROR_OUT_OF_POOL_MEMORY);
sprintf(name, "UNKNOWN_VkResult(%d)", vkResult); CASE_STRINGIFY(VK_ERROR_INVALID_EXTERNAL_HANDLE);
return name;
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_list args;
va_start(args, errFmt); va_start(args, errFmt);
char vkRsltName[MVKResultNameMaxLen];
mvkResultName(vkErr, vkRsltName);
// Prepend the error code to the format string // Prepend the error code to the format string
const char* vkRsltName = mvkVkResultName(vkErr);
char fmtStr[strlen(vkRsltName) + strlen(errFmt) + 4]; char fmtStr[strlen(vkRsltName) + strlen(errFmt) + 4];
sprintf(fmtStr, "%s: %s", vkRsltName, errFmt); sprintf(fmtStr, "%s: %s", vkRsltName, errFmt);

View File

@ -100,13 +100,11 @@ typedef enum {
kMVKCommandUseDispatch, /**< vkCmdDispatch. */ kMVKCommandUseDispatch, /**< vkCmdDispatch. */
} MVKCommandUse; } MVKCommandUse;
/** /** Returns the name of the result value. */
* Copies the name of the specified VkResult code to the specified string. const char* mvkVkResultName(VkResult vkResult);
*
* Returns a pointer to that string. /** Returns the name of the component swizzle. */
*/ const char* mvkVkComponentSwizzleName(VkComponentSwizzle swizzle);
#define MVKResultNameMaxLen 64
char* mvkResultName(VkResult vkResult, char* name);
/** /**
* Notifies the app of an error code and error message, via the following methods: * 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; 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 -
#pragma mark Template functions #pragma mark Template functions