Merge pull request #1408 from billhollings/handle-bad-api-pointers
Properly ignore non-null pipeline creation pointers that should be ignored.
This commit is contained in:
commit
3236796839
@ -398,6 +398,9 @@ protected:
|
|||||||
bool _needsFragmentBufferSizeBuffer = false;
|
bool _needsFragmentBufferSizeBuffer = false;
|
||||||
bool _needsFragmentDynamicOffsetBuffer = false;
|
bool _needsFragmentDynamicOffsetBuffer = false;
|
||||||
bool _needsFragmentViewRangeBuffer = false;
|
bool _needsFragmentViewRangeBuffer = false;
|
||||||
|
bool _isRasterizing = false;
|
||||||
|
bool _isRasterizingColor = false;
|
||||||
|
bool _isRasterizingDepthStencil = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -365,6 +365,13 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
|
|||||||
const VkGraphicsPipelineCreateInfo* pCreateInfo) :
|
const VkGraphicsPipelineCreateInfo* pCreateInfo) :
|
||||||
MVKPipeline(device, pipelineCache, (MVKPipelineLayout*)pCreateInfo->layout, parent) {
|
MVKPipeline(device, pipelineCache, (MVKPipelineLayout*)pCreateInfo->layout, parent) {
|
||||||
|
|
||||||
|
// Determine rasterization early, as various other structs are validated and interpreted in this context.
|
||||||
|
MVKRenderPass* mvkRendPass = (MVKRenderPass*)pCreateInfo->renderPass;
|
||||||
|
MVKRenderSubpass* mvkRenderSubpass = mvkRendPass->getSubpass(pCreateInfo->subpass);
|
||||||
|
_isRasterizing = !isRasterizationDisabled(pCreateInfo);
|
||||||
|
_isRasterizingColor = _isRasterizing && mvkRenderSubpass->hasColorAttachments();
|
||||||
|
_isRasterizingDepthStencil = _isRasterizing && mvkRenderSubpass->hasDepthStencilAttachment();
|
||||||
|
|
||||||
// Get the tessellation shaders, if present. Do this now, because we need to extract
|
// Get the tessellation shaders, if present. Do this now, because we need to extract
|
||||||
// reflection data from them that informs everything else.
|
// reflection data from them that informs everything else.
|
||||||
for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
|
for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
|
||||||
@ -405,8 +412,8 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blending
|
// Blending - must ignore allowed bad pColorBlendState pointer if rasterization disabled or no color attachments
|
||||||
if (pCreateInfo->pColorBlendState) {
|
if (_isRasterizingColor && pCreateInfo->pColorBlendState) {
|
||||||
memcpy(&_blendConstants, &pCreateInfo->pColorBlendState->blendConstants, sizeof(_blendConstants));
|
memcpy(&_blendConstants, &pCreateInfo->pColorBlendState->blendConstants, sizeof(_blendConstants));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,9 +428,9 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tessellation
|
// Tessellation - must ignore allowed bad pTessellationState pointer if not tess pipeline
|
||||||
_outputControlPointCount = reflectData.numControlPoints;
|
_outputControlPointCount = reflectData.numControlPoints;
|
||||||
mvkSetOrClear(&_tessInfo, pCreateInfo->pTessellationState);
|
mvkSetOrClear(&_tessInfo, (_pTessCtlSS && _pTessEvalSS) ? pCreateInfo->pTessellationState : nullptr);
|
||||||
|
|
||||||
// Rasterization
|
// Rasterization
|
||||||
_mtlCullMode = MTLCullModeNone;
|
_mtlCullMode = MTLCullModeNone;
|
||||||
@ -448,10 +455,11 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
|
|||||||
initMTLRenderPipelineState(pCreateInfo, reflectData);
|
initMTLRenderPipelineState(pCreateInfo, reflectData);
|
||||||
|
|
||||||
// Depth stencil content - clearing will disable depth and stencil testing
|
// Depth stencil content - clearing will disable depth and stencil testing
|
||||||
mvkSetOrClear(&_depthStencilInfo, pCreateInfo->pDepthStencilState);
|
// Must ignore allowed bad pDepthStencilState pointer if rasterization disabled or no depth attachment
|
||||||
|
mvkSetOrClear(&_depthStencilInfo, _isRasterizingDepthStencil ? pCreateInfo->pDepthStencilState : nullptr);
|
||||||
|
|
||||||
// Viewports and scissors
|
// Viewports and scissors - must ignore allowed bad pViewportState pointer if rasterization is disabled
|
||||||
auto pVPState = pCreateInfo->pViewportState;
|
auto pVPState = _isRasterizing ? pCreateInfo->pViewportState : nullptr;
|
||||||
if (pVPState) {
|
if (pVPState) {
|
||||||
uint32_t vpCnt = pVPState->viewportCount;
|
uint32_t vpCnt = pVPState->viewportCount;
|
||||||
_viewports.reserve(vpCnt);
|
_viewports.reserve(vpCnt);
|
||||||
@ -920,7 +928,7 @@ bool MVKGraphicsPipeline::addVertexShaderToPipeline(MTLRenderPipelineDescriptor*
|
|||||||
shaderConfig.options.mslOptions.dynamic_offsets_buffer_index = _dynamicOffsetBufferIndex.stages[kMVKShaderStageVertex];
|
shaderConfig.options.mslOptions.dynamic_offsets_buffer_index = _dynamicOffsetBufferIndex.stages[kMVKShaderStageVertex];
|
||||||
shaderConfig.options.mslOptions.view_mask_buffer_index = _viewRangeBufferIndex.stages[kMVKShaderStageVertex];
|
shaderConfig.options.mslOptions.view_mask_buffer_index = _viewRangeBufferIndex.stages[kMVKShaderStageVertex];
|
||||||
shaderConfig.options.mslOptions.capture_output_to_buffer = false;
|
shaderConfig.options.mslOptions.capture_output_to_buffer = false;
|
||||||
shaderConfig.options.mslOptions.disable_rasterization = isRasterizationDisabled(pCreateInfo);
|
shaderConfig.options.mslOptions.disable_rasterization = !_isRasterizing;
|
||||||
addVertexInputToShaderConversionConfig(shaderConfig, pCreateInfo);
|
addVertexInputToShaderConversionConfig(shaderConfig, pCreateInfo);
|
||||||
|
|
||||||
MVKMTLFunction func = ((MVKShaderModule*)_pVertexSS->module)->getMTLFunction(&shaderConfig, _pVertexSS->pSpecializationInfo, _pipelineCache);
|
MVKMTLFunction func = ((MVKShaderModule*)_pVertexSS->module)->getMTLFunction(&shaderConfig, _pVertexSS->pSpecializationInfo, _pipelineCache);
|
||||||
@ -1108,7 +1116,7 @@ bool MVKGraphicsPipeline::addTessEvalShaderToPipeline(MTLRenderPipelineDescripto
|
|||||||
shaderConfig.options.mslOptions.buffer_size_buffer_index = _bufferSizeBufferIndex.stages[kMVKShaderStageTessEval];
|
shaderConfig.options.mslOptions.buffer_size_buffer_index = _bufferSizeBufferIndex.stages[kMVKShaderStageTessEval];
|
||||||
shaderConfig.options.mslOptions.dynamic_offsets_buffer_index = _dynamicOffsetBufferIndex.stages[kMVKShaderStageTessEval];
|
shaderConfig.options.mslOptions.dynamic_offsets_buffer_index = _dynamicOffsetBufferIndex.stages[kMVKShaderStageTessEval];
|
||||||
shaderConfig.options.mslOptions.capture_output_to_buffer = false;
|
shaderConfig.options.mslOptions.capture_output_to_buffer = false;
|
||||||
shaderConfig.options.mslOptions.disable_rasterization = isRasterizationDisabled(pCreateInfo);
|
shaderConfig.options.mslOptions.disable_rasterization = !_isRasterizing;
|
||||||
addPrevStageOutputToShaderConversionConfig(shaderConfig, tcOutputs);
|
addPrevStageOutputToShaderConversionConfig(shaderConfig, tcOutputs);
|
||||||
|
|
||||||
MVKMTLFunction func = ((MVKShaderModule*)_pTessEvalSS->module)->getMTLFunction(&shaderConfig, _pTessEvalSS->pSpecializationInfo, _pipelineCache);
|
MVKMTLFunction func = ((MVKShaderModule*)_pTessEvalSS->module)->getMTLFunction(&shaderConfig, _pTessEvalSS->pSpecializationInfo, _pipelineCache);
|
||||||
@ -1157,7 +1165,7 @@ bool MVKGraphicsPipeline::addFragmentShaderToPipeline(MTLRenderPipelineDescripto
|
|||||||
shaderConfig.options.entryPointName = _pFragmentSS->pName;
|
shaderConfig.options.entryPointName = _pFragmentSS->pName;
|
||||||
shaderConfig.options.mslOptions.capture_output_to_buffer = false;
|
shaderConfig.options.mslOptions.capture_output_to_buffer = false;
|
||||||
shaderConfig.options.mslOptions.fixed_subgroup_size = mvkIsAnyFlagEnabled(_pFragmentSS->flags, VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT) ? 0 : _device->_pMetalFeatures->maxSubgroupSize;
|
shaderConfig.options.mslOptions.fixed_subgroup_size = mvkIsAnyFlagEnabled(_pFragmentSS->flags, VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT) ? 0 : _device->_pMetalFeatures->maxSubgroupSize;
|
||||||
if (pCreateInfo->pMultisampleState) {
|
if (_isRasterizing && pCreateInfo->pMultisampleState) { // Must ignore allowed bad pMultisampleState pointer if rasterization disabled
|
||||||
if (pCreateInfo->pMultisampleState->pSampleMask && pCreateInfo->pMultisampleState->pSampleMask[0] != 0xffffffff) {
|
if (pCreateInfo->pMultisampleState->pSampleMask && pCreateInfo->pMultisampleState->pSampleMask[0] != 0xffffffff) {
|
||||||
shaderConfig.options.mslOptions.additional_fixed_sample_mask = pCreateInfo->pMultisampleState->pSampleMask[0];
|
shaderConfig.options.mslOptions.additional_fixed_sample_mask = pCreateInfo->pMultisampleState->pSampleMask[0];
|
||||||
}
|
}
|
||||||
@ -1444,9 +1452,9 @@ void MVKGraphicsPipeline::addFragmentOutputToPipeline(MTLRenderPipelineDescripto
|
|||||||
: mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(pCreateInfo->pInputAssemblyState->topology);
|
: mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(pCreateInfo->pInputAssemblyState->topology);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color attachments
|
// Color attachments - must ignore bad pColorBlendState pointer if rasterization is disabled or subpass has no color attachments
|
||||||
uint32_t caCnt = 0;
|
uint32_t caCnt = 0;
|
||||||
if (pCreateInfo->pColorBlendState) {
|
if (_isRasterizingColor && pCreateInfo->pColorBlendState) {
|
||||||
for (uint32_t caIdx = 0; caIdx < pCreateInfo->pColorBlendState->attachmentCount; caIdx++) {
|
for (uint32_t caIdx = 0; caIdx < pCreateInfo->pColorBlendState->attachmentCount; caIdx++) {
|
||||||
const VkPipelineColorBlendAttachmentState* pCA = &pCreateInfo->pColorBlendState->pAttachments[caIdx];
|
const VkPipelineColorBlendAttachmentState* pCA = &pCreateInfo->pColorBlendState->pAttachments[caIdx];
|
||||||
|
|
||||||
@ -1493,8 +1501,8 @@ void MVKGraphicsPipeline::addFragmentOutputToPipeline(MTLRenderPipelineDescripto
|
|||||||
colorDesc.writeMask = MTLColorWriteMaskNone;
|
colorDesc.writeMask = MTLColorWriteMaskNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multisampling
|
// Multisampling - must ignore allowed bad pMultisampleState pointer if rasterization disabled
|
||||||
if (pCreateInfo->pMultisampleState) {
|
if (_isRasterizing && pCreateInfo->pMultisampleState) {
|
||||||
plDesc.sampleCount = mvkSampleCountFromVkSampleCountFlagBits(pCreateInfo->pMultisampleState->rasterizationSamples);
|
plDesc.sampleCount = mvkSampleCountFromVkSampleCountFlagBits(pCreateInfo->pMultisampleState->rasterizationSamples);
|
||||||
mvkRenderSubpass->setDefaultSampleCount(pCreateInfo->pMultisampleState->rasterizationSamples);
|
mvkRenderSubpass->setDefaultSampleCount(pCreateInfo->pMultisampleState->rasterizationSamples);
|
||||||
plDesc.alphaToCoverageEnabled = pCreateInfo->pMultisampleState->alphaToCoverageEnable;
|
plDesc.alphaToCoverageEnabled = pCreateInfo->pMultisampleState->alphaToCoverageEnable;
|
||||||
@ -1507,8 +1515,9 @@ void MVKGraphicsPipeline::initShaderConversionConfig(SPIRVToMSLConversionConfigu
|
|||||||
const VkGraphicsPipelineCreateInfo* pCreateInfo,
|
const VkGraphicsPipelineCreateInfo* pCreateInfo,
|
||||||
const SPIRVTessReflectionData& reflectData) {
|
const SPIRVTessReflectionData& reflectData) {
|
||||||
|
|
||||||
|
// Tessellation - must ignore allowed bad pTessellationState pointer if not tess pipeline
|
||||||
VkPipelineTessellationDomainOriginStateCreateInfo* pTessDomainOriginState = nullptr;
|
VkPipelineTessellationDomainOriginStateCreateInfo* pTessDomainOriginState = nullptr;
|
||||||
if (pCreateInfo->pTessellationState) {
|
if (isTessellationPipeline() && pCreateInfo->pTessellationState) {
|
||||||
for (const auto* next = (VkBaseInStructure*)pCreateInfo->pTessellationState->pNext; next; next = next->pNext) {
|
for (const auto* next = (VkBaseInStructure*)pCreateInfo->pTessellationState->pNext; next; next = next->pNext) {
|
||||||
switch (next->sType) {
|
switch (next->sType) {
|
||||||
case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO:
|
case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO:
|
||||||
@ -1550,9 +1559,10 @@ void MVKGraphicsPipeline::initShaderConversionConfig(SPIRVToMSLConversionConfigu
|
|||||||
// fragment shader outputs a color value without a corresponding color attachment.
|
// fragment shader outputs a color value without a corresponding color attachment.
|
||||||
// However, if alpha-to-coverage is enabled, we must enable the fragment shader first color output,
|
// However, if alpha-to-coverage is enabled, we must enable the fragment shader first color output,
|
||||||
// even without a color attachment present or in use, so that coverage can be calculated.
|
// even without a color attachment present or in use, so that coverage can be calculated.
|
||||||
bool hasA2C = pCreateInfo->pMultisampleState && pCreateInfo->pMultisampleState->alphaToCoverageEnable;
|
// Must ignore allowed bad pMultisampleState pointer if rasterization disabled
|
||||||
|
bool hasA2C = _isRasterizing && pCreateInfo->pMultisampleState && pCreateInfo->pMultisampleState->alphaToCoverageEnable;
|
||||||
shaderConfig.options.mslOptions.enable_frag_output_mask = hasA2C ? 1 : 0;
|
shaderConfig.options.mslOptions.enable_frag_output_mask = hasA2C ? 1 : 0;
|
||||||
if (pCreateInfo->pColorBlendState) {
|
if (_isRasterizingColor && pCreateInfo->pColorBlendState) {
|
||||||
for (uint32_t caIdx = 0; caIdx < pCreateInfo->pColorBlendState->attachmentCount; caIdx++) {
|
for (uint32_t caIdx = 0; caIdx < pCreateInfo->pColorBlendState->attachmentCount; caIdx++) {
|
||||||
if (mvkRenderSubpass->isColorAttachmentUsed(caIdx)) {
|
if (mvkRenderSubpass->isColorAttachmentUsed(caIdx)) {
|
||||||
mvkEnableFlags(shaderConfig.options.mslOptions.enable_frag_output_mask, 1 << caIdx);
|
mvkEnableFlags(shaderConfig.options.mslOptions.enable_frag_output_mask, 1 << caIdx);
|
||||||
|
@ -47,13 +47,19 @@ public:
|
|||||||
MVKVulkanAPIObject* getVulkanAPIObject() override;
|
MVKVulkanAPIObject* getVulkanAPIObject() override;
|
||||||
|
|
||||||
/** Returns the parent render pass of this subpass. */
|
/** Returns the parent render pass of this subpass. */
|
||||||
inline MVKRenderPass* getRenderPass() { return _renderPass; }
|
MVKRenderPass* getRenderPass() { return _renderPass; }
|
||||||
|
|
||||||
/** Returns the index of this subpass in its parent render pass. */
|
/** Returns the index of this subpass in its parent render pass. */
|
||||||
inline uint32_t getSubpassIndex() { return _subpassIndex; }
|
uint32_t getSubpassIndex() { return _subpassIndex; }
|
||||||
|
|
||||||
|
/** Returns whether this subpass has any color attachments. */
|
||||||
|
bool hasColorAttachments();
|
||||||
|
|
||||||
|
/** Returns whether this subpass has a depth/stencil attachment. */
|
||||||
|
bool hasDepthStencilAttachment() { return _depthStencilAttachment.attachment != VK_ATTACHMENT_UNUSED; }
|
||||||
|
|
||||||
/** Returns the number of color attachments, which may be zero for depth-only rendering. */
|
/** Returns the number of color attachments, which may be zero for depth-only rendering. */
|
||||||
inline uint32_t getColorAttachmentCount() { return uint32_t(_colorAttachments.size()); }
|
uint32_t getColorAttachmentCount() { return uint32_t(_colorAttachments.size()); }
|
||||||
|
|
||||||
/** Returns the format of the color attachment at the specified index. */
|
/** Returns the format of the color attachment at the specified index. */
|
||||||
VkFormat getColorAttachmentFormat(uint32_t colorAttIdx);
|
VkFormat getColorAttachmentFormat(uint32_t colorAttIdx);
|
||||||
@ -74,7 +80,7 @@ public:
|
|||||||
bool isMultiview() const { return _viewMask != 0; }
|
bool isMultiview() const { return _viewMask != 0; }
|
||||||
|
|
||||||
/** Returns the total number of views to be rendered. */
|
/** Returns the total number of views to be rendered. */
|
||||||
inline uint32_t getViewCount() const { return __builtin_popcount(_viewMask); }
|
uint32_t getViewCount() const { return __builtin_popcount(_viewMask); }
|
||||||
|
|
||||||
/** Returns the number of Metal render passes needed to render all views. */
|
/** Returns the number of Metal render passes needed to render all views. */
|
||||||
uint32_t getMultiviewMetalPassCount() const;
|
uint32_t getMultiviewMetalPassCount() const;
|
||||||
|
@ -35,6 +35,13 @@ using namespace std;
|
|||||||
|
|
||||||
MVKVulkanAPIObject* MVKRenderSubpass::getVulkanAPIObject() { return _renderPass->getVulkanAPIObject(); };
|
MVKVulkanAPIObject* MVKRenderSubpass::getVulkanAPIObject() { return _renderPass->getVulkanAPIObject(); };
|
||||||
|
|
||||||
|
bool MVKRenderSubpass::hasColorAttachments() {
|
||||||
|
for (auto& ca : _colorAttachments) {
|
||||||
|
if (ca.attachment != VK_ATTACHMENT_UNUSED) { return true; }
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
VkFormat MVKRenderSubpass::getColorAttachmentFormat(uint32_t colorAttIdx) {
|
VkFormat MVKRenderSubpass::getColorAttachmentFormat(uint32_t colorAttIdx) {
|
||||||
if (colorAttIdx < _colorAttachments.size()) {
|
if (colorAttIdx < _colorAttachments.size()) {
|
||||||
uint32_t rpAttIdx = _colorAttachments[colorAttIdx].attachment;
|
uint32_t rpAttIdx = _colorAttachments[colorAttIdx].attachment;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user