From a7ab1081663f018c175a20bfd8c8a8df4dad4ef3 Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Mon, 14 Jan 2019 17:36:39 -0500 Subject: [PATCH] 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. --- Docs/Whats_New.md | 4 +- MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h | 20 +++-- .../MoltenVK/Commands/MVKCommandBuffer.mm | 2 +- .../Commands/MVKCommandEncoderState.h | 17 ++-- .../Commands/MVKCommandEncoderState.mm | 89 +++++++++++++------ MoltenVK/MoltenVK/GPUObjects/MVKImage.h | 2 - MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 21 +---- MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm | 2 +- MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm | 10 +-- MoltenVK/MoltenVK/Utility/MVKEnvironment.h | 6 +- MoltenVK/MoltenVK/Utility/MVKFoundation.cpp | 82 +++++++++-------- MoltenVK/MoltenVK/Utility/MVKFoundation.h | 28 ++++-- 12 files changed, 165 insertions(+), 118 deletions(-) diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index c049180c..c2fbfaf1 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -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. diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h index a5b20dff..5a3eb175 100644 --- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h +++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h @@ -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; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm index 64d6d16f..a93f150c 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandBuffer.mm @@ -351,7 +351,7 @@ void MVKCommandEncoder::clearRenderArea() { } void MVKCommandEncoder::finalizeDispatchState() { - _computePipelineState.encode(); + _computePipelineState.encode(); // Must do first..it sets others _computeResourcesState.encode(); _computePushConstants.encode(); } diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h index ef02488c..f52bcabe 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h @@ -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& 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 @@ -391,11 +398,6 @@ protected: } } - // Updates the swizzle for an image in the given vector. - void updateSwizzle(MVKVector &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; }; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm index e51c4e33..d7eea3bd 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm @@ -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 &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& 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(_vertexBufferBindings, _areVertexBufferBindingsDirty, [](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void { [cmdEncoder->_mtlRenderEncoder setVertexBuffer: b.mtlBuffer @@ -476,17 +487,33 @@ void MVKGraphicsResourcesCommandEncoderState::encodeImpl() { }); 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.size() * sizeof(uint32_t), _vertexAuxBufferBinding.index); - } + + } else { + assertMissingSwizzles(_needsVertexSwizzle, "vertex", _vertexTextureBindings); + } 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.size() * sizeof(uint32_t), _fragmentAuxBufferBinding.index); + + } else { + assertMissingSwizzles(_needsFragmentSwizzle, "fragment", _fragmentTextureBindings); } encodeBinding(_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(_bufferBindings, _areBufferBindingsDirty, [](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void { [cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch) setBuffer: b.mtlBuffer @@ -581,10 +604,18 @@ void MVKComputeResourcesCommandEncoderState::encodeImpl() { }); 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.size() * sizeof(uint32_t), _auxBufferBinding.index); + + } else { + assertMissingSwizzles(_needsSwizzle, "compute", _textureBindings); } encodeBinding(_textureBindings, _areTextureBindingsDirty, @@ -610,6 +641,8 @@ void MVKComputeResourcesCommandEncoderState::resetImpl() { _areTextureBindingsDirty = false; _areSamplerStateBindingsDirty = false; _auxBufferBinding.isDirty = false; + + _needsSwizzle = false; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h index 2909ff00..71a01468 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h @@ -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; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index d0847506..faa31cbd 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -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() { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm index 9c7bb9e3..d2cb6ceb 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm @@ -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) { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm index e095c9fd..9bb5a360 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -324,7 +324,7 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor shaderContext.options.entryPointName = pSS->pName; id 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 = ((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); diff --git a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h index eec11061..c7d1e3ee 100644 --- a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h +++ b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h @@ -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 diff --git a/MoltenVK/MoltenVK/Utility/MVKFoundation.cpp b/MoltenVK/MoltenVK/Utility/MVKFoundation.cpp index 04ffbd7f..276df6f9 100644 --- a/MoltenVK/MoltenVK/Utility/MVKFoundation.cpp +++ b/MoltenVK/MoltenVK/Utility/MVKFoundation.cpp @@ -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); diff --git a/MoltenVK/MoltenVK/Utility/MVKFoundation.h b/MoltenVK/MoltenVK/Utility/MVKFoundation.h index c931c12d..7ef4ba77 100644 --- a/MoltenVK/MoltenVK/Utility/MVKFoundation.h +++ b/MoltenVK/MoltenVK/Utility/MVKFoundation.h @@ -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