Merge pull request #313 from billhollings/master

Support polygonMode VK_POLYGON_MODE_POINT.
This commit is contained in:
Bill Hollings 2018-10-25 16:57:49 -04:00 committed by GitHub
commit aba70b867b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 95 additions and 77 deletions

View File

@ -12,11 +12,22 @@ Copyright (c) 2014-2018 [The Brenwill Workshop Ltd.](http://www.brenwill.com)
For best results, use a Markdown reader.*
MoltenVK 1.0.24
MoltenVK 1.0.25
---------------
Released TBD
- Update shader caching for compatibility with texture swizzling.
- Support polygonMode VK_POLYGON_MODE_POINT.
- vkCreateInstance returns VK_ERROR_INCOMPATIBLE_DRIVER if Metal not available.
MoltenVK 1.0.24
---------------
Released 2018/10/16
- Support arbitrary swizzles of image data.
- Include struct size parameter in VK_MVK_moltenvk extension functions that pass structs that
might change size across extension versions.
- Remove vkGetMoltenVKDeviceConfigurationMVK() & vkSetMoltenVKDeviceConfigurationMVK() functions.

View File

@ -332,12 +332,11 @@ MTLVertexStepFunction mvkMTLVertexStepFunctionFromVkVertexInputRate(VkVertexInpu
/** Returns the Metal MTLPrimitiveType corresponding to the specified Vulkan VkPrimitiveTopology. */
MTLPrimitiveType mvkMTLPrimitiveTypeFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology);
/**
* Returns the Metal MTLPrimitiveTopologyClass corresponding to the specified Vulkan VkPrimitiveTopology.
*
* The value is treated as an NSUInteger to support OS versions on which the enum is unavailable.
*/
NSUInteger mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology);
/** Returns the Metal MTLPrimitiveTopologyClass corresponding to the specified Vulkan VkPrimitiveTopology. */
MTLPrimitiveTopologyClass mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology);
/** Returns the Metal MTLTriangleFillMode corresponding to the specified Vulkan VkPolygonMode, */
MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonMode(VkPolygonMode vkFillMode);
/** Returns the Metal MTLLoadAction corresponding to the specified Vulkan VkAttachmentLoadOp. */
MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOp(VkAttachmentLoadOp vkLoadOp);
@ -363,9 +362,6 @@ MTLCullMode mvkMTLCullModeFromVkCullModeFlags(VkCullModeFlags vkCull);
/** Returns the Metal MTLWinding corresponding to the specified Vulkan VkFrontFace, */
MTLWinding mvkMTLWindingFromVkFrontFace(VkFrontFace vkWinding);
/** Returns the Metal MTLTriangleFillMode corresponding to the specified Vulkan VkPolygonMode, */
MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonMode(VkPolygonMode vkFillMode);
/** Returns the Metal MTLIndexType corresponding to the specified Vulkan VkIndexType, */
MTLIndexType mvkMTLIndexTypeFromVkIndexType(VkIndexType vkIdxType);

View File

@ -218,7 +218,7 @@ class MVKDepthStencilCommandEncoderState : public MVKCommandEncoderState {
public:
/** Sets the depth stencil state during pipeline binding. */
void setDepthStencilState(VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo);
void setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo);
/**
* Sets the stencil compare mask value of the indicated faces
@ -240,7 +240,7 @@ protected:
void encodeImpl() override;
void resetImpl() override;
void setStencilState(MVKMTLStencilDescriptorData& stencilInfo,
VkStencilOpState& vkStencil,
const VkStencilOpState& vkStencil,
bool enabled);
MVKMTLDepthStencilDescriptorData _depthStencilData;
@ -256,7 +256,7 @@ class MVKStencilReferenceValueCommandEncoderState : public MVKCommandEncoderStat
public:
/** Sets the stencil references during pipeline binding. */
void setReferenceValues(VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo);
void setReferenceValues(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo);
/** Sets the stencil state from explicit dynamic command. */
void setReferenceValues(VkStencilFaceFlags faceMask, uint32_t stencilReference);
@ -283,7 +283,7 @@ class MVKDepthBiasCommandEncoderState : public MVKCommandEncoderState {
public:
/** Sets the depth bias during pipeline binding. */
void setDepthBias(VkPipelineRasterizationStateCreateInfo vkRasterInfo);
void setDepthBias(const VkPipelineRasterizationStateCreateInfo& vkRasterInfo);
/** Sets the depth bias dynamically. */
void setDepthBias(float depthBiasConstantFactor,

View File

@ -186,7 +186,7 @@ void MVKPushConstantsCommandEncoderState::resetImpl() {
#pragma mark -
#pragma mark MVKDepthStencilCommandEncoderState
void MVKDepthStencilCommandEncoderState:: setDepthStencilState(VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo) {
void MVKDepthStencilCommandEncoderState:: setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo) {
if (vkDepthStencilInfo.depthTestEnable) {
_depthStencilData.depthCompareFunction = mvkMTLCompareFunctionFromVkCompareOp(vkDepthStencilInfo.depthCompareOp);
@ -203,7 +203,7 @@ void MVKDepthStencilCommandEncoderState:: setDepthStencilState(VkPipelineDepthSt
}
void MVKDepthStencilCommandEncoderState::setStencilState(MVKMTLStencilDescriptorData& stencilInfo,
VkStencilOpState& vkStencil,
const VkStencilOpState& vkStencil,
bool enabled) {
if ( !enabled ) {
stencilInfo = kMVKMTLStencilDescriptorDataDefault;
@ -282,7 +282,7 @@ void MVKDepthStencilCommandEncoderState::resetImpl() {
#pragma mark -
#pragma mark MVKStencilReferenceValueCommandEncoderState
void MVKStencilReferenceValueCommandEncoderState:: setReferenceValues(VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo) {
void MVKStencilReferenceValueCommandEncoderState:: setReferenceValues(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo) {
// If ref values are to be set dynamically, don't set them here.
if (_cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE)) { return; }
@ -323,7 +323,7 @@ void MVKStencilReferenceValueCommandEncoderState::resetImpl() {
#pragma mark -
#pragma mark MVKDepthBiasCommandEncoderState
void MVKDepthBiasCommandEncoderState::setDepthBias(VkPipelineRasterizationStateCreateInfo vkRasterInfo) {
void MVKDepthBiasCommandEncoderState::setDepthBias(const VkPipelineRasterizationStateCreateInfo& vkRasterInfo) {
_isEnabled = vkRasterInfo.depthBiasEnable;

View File

@ -90,7 +90,7 @@ id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdClearMTLRenderPipeli
plDesc.vertexFunction = getFunctionNamed("vtxCmdClearAttachments");
plDesc.fragmentFunction = getClearFragFunction(attKey);
plDesc.sampleCount = attKey.mtlSampleCount;
plDesc.inputPrimitiveTopologyMVK = mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
plDesc.inputPrimitiveTopologyMVK = MTLPrimitiveTopologyClassTriangle;
for (uint32_t caIdx = 0; caIdx < kMVKAttachmentFormatDepthStencilIndex; caIdx++) {
MTLRenderPipelineColorAttachmentDescriptor* colorDesc = plDesc.colorAttachments[caIdx];

View File

@ -69,9 +69,11 @@ void MVKInstance::destroySurface(MVKSurface* mvkSrfc,
// sorted according to power, with higher power GPU's at the front of the array.
// This ensures that a lazy app that simply grabs the first GPU will get a high-power one by default.
// If the MVK_FORCE_LOW_POWER_GPU is defined, the returned array will only include low-power devices.
// If Metal is not supported, ensure we return an empty array.
static NSArray<id<MTLDevice>>* getAvailableMTLDevices() {
#if MVK_MACOS
NSArray* mtlDevs = [MTLCopyAllDevices() autorelease];
if ( !mtlDevs ) { return @[]; }
#ifdef MVK_FORCE_LOW_POWER_GPU
NSMutableArray* lpDevs = [[NSMutableArray new] autorelease];
@ -101,8 +103,9 @@ static NSArray<id<MTLDevice>>* getAvailableMTLDevices() {
#endif
#if MVK_IOS
return [NSArray arrayWithObject: MTLCreateSystemDefaultDevice()];
#endif
id<MTLDevice> mtlDev = MTLCreateSystemDefaultDevice();
return mtlDev ? [NSArray arrayWithObject: mtlDev] : @[];
#endif // MVK_IOS
}
MVKInstance::MVKInstance(const VkInstanceCreateInfo* pCreateInfo) {
@ -131,6 +134,9 @@ MVKInstance::MVKInstance(const VkInstanceCreateInfo* pCreateInfo) {
for (id<MTLDevice> mtlDev in mtlDevices) {
_physicalDevices.push_back(new MVKPhysicalDevice(this, mtlDev));
}
if (_physicalDevices.empty()) {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INCOMPATIBLE_DRIVER, "Vulkan is not supported on this device. MoltenVK requires Metal, which is not available on this device."));
}
}
#define ADD_PROC_ADDR(entrypoint) _procAddrMap[""#entrypoint] = (PFN_vkVoidFunction)&entrypoint;

View File

@ -152,6 +152,7 @@ protected:
void initMVKShaderConverterContext(SPIRVToMSLConverterContext& _shaderContext,
const VkGraphicsPipelineCreateInfo* pCreateInfo);
MTLRenderPipelineDescriptor* getMTLRenderPipelineDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo);
bool isRenderingPoints(const VkGraphicsPipelineCreateInfo* pCreateInfo);
VkPipelineRasterizationStateCreateInfo _rasterInfo;
VkPipelineDepthStencilStateCreateInfo _depthStencilInfo;

View File

@ -204,7 +204,7 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
MVKPipeline* parent,
const VkGraphicsPipelineCreateInfo* pCreateInfo) : MVKPipeline(device, pipelineCache, parent) {
// Track dynamic state in _dynamicStateEnabled array
// Track dynamic state in _dynamicStateEnabled array
memset(&_dynamicStateEnabled, false, sizeof(_dynamicStateEnabled)); // start with all dynamic state disabled
const VkPipelineDynamicStateCreateInfo* pDS = pCreateInfo->pDynamicState;
if (pDS) {
@ -214,31 +214,34 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
}
}
if (pCreateInfo->pColorBlendState) {
memcpy(&_blendConstants, &pCreateInfo->pColorBlendState->blendConstants, sizeof(_blendConstants));
}
// Blending
if (pCreateInfo->pColorBlendState) {
memcpy(&_blendConstants, &pCreateInfo->pColorBlendState->blendConstants, sizeof(_blendConstants));
}
if (pCreateInfo->pInputAssemblyState) {
_mtlPrimitiveType = mvkMTLPrimitiveTypeFromVkPrimitiveTopology(pCreateInfo->pInputAssemblyState->topology);
}
// Topology
_mtlPrimitiveType = MTLPrimitiveTypePoint;
if (pCreateInfo->pInputAssemblyState && !isRenderingPoints(pCreateInfo)) {
_mtlPrimitiveType = mvkMTLPrimitiveTypeFromVkPrimitiveTopology(pCreateInfo->pInputAssemblyState->topology);
}
// Add raster content - must occur before initMTLRenderPipelineState() for rasterizerDiscardEnable
// Rasterization
_mtlCullMode = MTLCullModeNone;
_mtlFrontWinding = MTLWindingCounterClockwise;
_mtlFillMode = MTLTriangleFillModeFill;
_mtlDepthClipMode = MTLDepthClipModeClip;
_mtlDepthClipMode = MTLDepthClipModeClip;
bool hasRasterInfo = mvkSetOrClear(&_rasterInfo, pCreateInfo->pRasterizationState);
if (hasRasterInfo) {
_mtlCullMode = mvkMTLCullModeFromVkCullModeFlags(_rasterInfo.cullMode);
_mtlFrontWinding = mvkMTLWindingFromVkFrontFace(_rasterInfo.frontFace);
_mtlFillMode = mvkMTLTriangleFillModeFromVkPolygonMode(_rasterInfo.polygonMode);
if (_rasterInfo.depthClampEnable) {
if (_rasterInfo.depthClampEnable) {
if (_device->_pFeatures->depthClamp) {
_mtlDepthClipMode = MTLDepthClipModeClamp;
} else {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "This device does not support depth clamping."));
}
}
_mtlDepthClipMode = MTLDepthClipModeClamp;
} else {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "This device does not support depth clamping."));
}
}
}
// Render pipeline state
@ -247,7 +250,7 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
// Depth stencil content
_hasDepthStencilInfo = mvkSetOrClear(&_depthStencilInfo, pCreateInfo->pDepthStencilState);
// Add viewports and scissors
// Viewports and scissors
if (pCreateInfo->pViewportState) {
_mtlViewports.reserve(pCreateInfo->pViewportState->viewportCount);
for (uint32_t i = 0; i < pCreateInfo->pViewportState->viewportCount; i++) {
@ -270,7 +273,7 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
}
}
/** Constructs the underlying Metal render pipeline. */
// Constructs the underlying Metal render pipeline.
void MVKGraphicsPipeline::initMTLRenderPipelineState(const VkGraphicsPipelineCreateInfo* pCreateInfo) {
_mtlPipelineState = nil;
MTLRenderPipelineDescriptor* plDesc = getMTLRenderPipelineDescriptor(pCreateInfo);
@ -450,14 +453,16 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor
plDesc.alphaToOneEnabled = pCreateInfo->pMultisampleState->alphaToOneEnable;
}
if (pCreateInfo->pInputAssemblyState) {
plDesc.inputPrimitiveTopologyMVK = mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(pCreateInfo->pInputAssemblyState->topology);
}
if (pCreateInfo->pInputAssemblyState) {
plDesc.inputPrimitiveTopologyMVK = isRenderingPoints(pCreateInfo)
? MTLPrimitiveTopologyClassPoint
: mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(pCreateInfo->pInputAssemblyState->topology);
}
return plDesc;
}
/** Initializes the context used to prepare the MSL library used by this pipeline. */
// Initializes the context used to prepare the MSL library used by this pipeline.
void MVKGraphicsPipeline::initMVKShaderConverterContext(SPIRVToMSLConverterContext& shaderContext,
const VkGraphicsPipelineCreateInfo* pCreateInfo) {
@ -467,7 +472,7 @@ void MVKGraphicsPipeline::initMVKShaderConverterContext(SPIRVToMSLConverterConte
MVKPipelineLayout* layout = (MVKPipelineLayout*)pCreateInfo->layout;
layout->populateShaderConverterContext(shaderContext);
shaderContext.options.isRenderingPoints = (pCreateInfo->pInputAssemblyState && (pCreateInfo->pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST));
shaderContext.options.isRenderingPoints = isRenderingPoints(pCreateInfo);
shaderContext.options.isRasterizationDisabled = (pCreateInfo->pRasterizationState && (pCreateInfo->pRasterizationState->rasterizerDiscardEnable));
shaderContext.options.shouldFlipVertexY = _device->_pMVKConfig->shaderConversionFlipVertexY;
@ -498,6 +503,12 @@ void MVKGraphicsPipeline::initMVKShaderConverterContext(SPIRVToMSLConverterConte
}
}
// We render points if either the topology or polygon fill mode dictate it
bool MVKGraphicsPipeline::isRenderingPoints(const VkGraphicsPipelineCreateInfo* pCreateInfo) {
return ((pCreateInfo->pInputAssemblyState && (pCreateInfo->pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)) ||
(pCreateInfo->pRasterizationState && (pCreateInfo->pRasterizationState->polygonMode == VK_POLYGON_MODE_POINT)));
}
MVKGraphicsPipeline::~MVKGraphicsPipeline() {
[_mtlPipelineState release];
}
@ -569,7 +580,7 @@ MVKComputePipeline::~MVKComputePipeline() {
#pragma mark -
#pragma mark MVKPipelineCache
/** Return a shader library from the specified shader context sourced from the specified shader module. */
// Return a shader library from the specified shader context sourced from the specified shader module.
MVKShaderLibrary* MVKPipelineCache::getShaderLibrary(SPIRVToMSLConverterContext* pContext, MVKShaderModule* shaderModule) {
lock_guard<mutex> lock(_shaderCacheLock);

View File

@ -30,9 +30,7 @@
* This property allows support under all OS versions. Delegates to the inputPrimitiveTopology
* property if it is available. otherwise, returns MTLPrimitiveTopologyClassUnspecified when
* read and does nothing when set.
*
* The value is treated as an NSUInteger to support OS versions on which the enum is unavailable.
*/
@property(nonatomic, readwrite) NSUInteger inputPrimitiveTopologyMVK;
@property(nonatomic, readwrite) MTLPrimitiveTopologyClass inputPrimitiveTopologyMVK;
@end

View File

@ -22,23 +22,13 @@
@implementation MTLRenderPipelineDescriptor (MoltenVK)
-(NSUInteger) inputPrimitiveTopologyMVK {
#if MVK_MACOS
return self.inputPrimitiveTopology;
#endif
#if MVK_IOS
return 0;
#endif
-(MTLPrimitiveTopologyClass) inputPrimitiveTopologyMVK {
if ( [self respondsToSelector: @selector(inputPrimitiveTopology)] ) { return self.inputPrimitiveTopology; }
return MTLPrimitiveTopologyClassUnspecified;
}
-(void) setInputPrimitiveTopologyMVK: (NSUInteger) topology {
#if MVK_MACOS
self.inputPrimitiveTopology = topology;
#endif
-(void) setInputPrimitiveTopologyMVK: (MTLPrimitiveTopologyClass) topology {
if ([self respondsToSelector: @selector(setInputPrimitiveTopology:)]) { self.inputPrimitiveTopology = topology; }
}
@end

View File

@ -978,8 +978,7 @@ MVK_PUBLIC_SYMBOL MTLPrimitiveType mvkMTLPrimitiveTypeFromVkPrimitiveTopology(Vk
}
}
MVK_PUBLIC_SYMBOL NSUInteger mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology) {
#if MVK_MACOS
MVK_PUBLIC_SYMBOL MTLPrimitiveTopologyClass mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology) {
switch (vkTopology) {
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
return MTLPrimitiveTopologyClassPoint;
@ -1002,10 +1001,21 @@ MVK_PUBLIC_SYMBOL NSUInteger mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology
mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "VkPrimitiveTopology value %d is not supported for render pipelines.", vkTopology);
return MTLPrimitiveTopologyClassUnspecified;
}
#endif
#if MVK_IOS
return 0;
#endif
}
MVK_PUBLIC_SYMBOL MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonMode(VkPolygonMode vkFillMode) {
switch (vkFillMode) {
case VK_POLYGON_MODE_FILL:
case VK_POLYGON_MODE_POINT:
return MTLTriangleFillModeFill;
case VK_POLYGON_MODE_LINE:
return MTLTriangleFillModeLines;
default:
mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "VkPolygonMode value %d is not supported for render pipelines.", vkFillMode);
return MTLTriangleFillModeFill;
}
}
MVK_PUBLIC_SYMBOL MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOp(VkAttachmentLoadOp vkLoadOp) {
@ -1096,15 +1106,6 @@ MVK_PUBLIC_SYMBOL MTLWinding mvkMTLWindingFromVkFrontFace(VkFrontFace vkWinding)
}
}
MVK_PUBLIC_SYMBOL MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonMode(VkPolygonMode vkFillMode) {
switch (vkFillMode) {
case VK_POLYGON_MODE_FILL: return MTLTriangleFillModeFill;
case VK_POLYGON_MODE_LINE: return MTLTriangleFillModeLines;
case VK_POLYGON_MODE_POINT: return MTLTriangleFillModeLines;
default: return MTLTriangleFillModeLines;
}
}
MVK_PUBLIC_SYMBOL MTLIndexType mvkMTLIndexTypeFromVkIndexType(VkIndexType vkIdxType) {
switch (vkIdxType) {
case VK_INDEX_TYPE_UINT32: return MTLIndexTypeUInt32;

View File

@ -95,6 +95,10 @@
argument = "path-to-SPIR-V-shader-file"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "-so"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "-mo"
isEnabled = "YES">