Merge pull request #660 from billhollings/master

Move push constant binding to vkCmdBindPipeline() from vkCmdBindDescriptorSet().
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
index 033f613..35d6a02 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
@@ -44,7 +44,10 @@
 MVKPipeline* MVKPipelineCommandEncoderState::getPipeline() { return _pipeline; }
 
 void MVKPipelineCommandEncoderState::encodeImpl(uint32_t stage) {
-    if (_pipeline) { _pipeline->encode(_cmdEncoder, stage); }
+    if (_pipeline) {
+		_pipeline->encode(_cmdEncoder, stage);
+		_pipeline->bindPushConstants(_cmdEncoder);
+	}
 }
 
 void MVKPipelineCommandEncoderState::resetImpl() {
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
index a6ecc88..7b56702 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.h
@@ -58,9 +58,6 @@
                             uint32_t firstSet,
                             MVKVector<uint32_t>& dynamicOffsets);
 
-	/** Populates the specified shader converter context. */
-	void populateShaderConverterContext(SPIRVToMSLConversionConfiguration& context);
-
 	/** Updates a descriptor set in a command encoder. */
 	void pushDescriptorSet(MVKCommandEncoder* cmdEncoder,
 						   MVKVector<VkWriteDescriptorSet>& descriptorWrites,
@@ -72,6 +69,9 @@
 						   uint32_t set,
 						   const void* pData);
 
+	/** Populates the specified shader converter context. */
+	void populateShaderConverterContext(SPIRVToMSLConversionConfiguration& context);
+
 	/** Returns the current swizzle buffer bindings. */
 	const MVKShaderImplicitRezBinding& getSwizzleBufferIndex() { return _swizzleBufferIndex; }
 
@@ -96,6 +96,9 @@
 	/** Returns the number of buffers in this layout. This is used to calculate the size of the buffer size buffer. */
 	uint32_t getBufferCount() { return _pushConstantsMTLResourceIndexes.getMaxBufferIndex(); }
 
+	/** Returns the push constant binding info. */
+	const MVKShaderResourceBinding& getPushConstantBindings() { return _pushConstantsMTLResourceIndexes; }
+
 	/** Constructs an instance for the specified device. */
 	MVKPipelineLayout(MVKDevice* device, const VkPipelineLayoutCreateInfo* pCreateInfo);
 
@@ -144,6 +147,9 @@
 	/** Binds this pipeline to the specified command encoder. */
 	virtual void encode(MVKCommandEncoder* cmdEncoder, uint32_t stage = 0) = 0;
 
+	/** Binds the push constants to a command encoder. */
+	void bindPushConstants(MVKCommandEncoder* cmdEncoder);
+
 	/** Returns the current swizzle buffer bindings. */
 	const MVKShaderImplicitRezBinding& getSwizzleBufferIndex() { return _swizzleBufferIndex; }
 
@@ -157,9 +163,7 @@
 	bool hasValidMTLPipelineStates() { return _hasValidMTLPipelineStates; }
 
 	/** Constructs an instance for the device. layout, and parent (which may be NULL). */
-	MVKPipeline(MVKDevice* device, MVKPipelineCache* pipelineCache, MVKPipeline* parent) : MVKVulkanAPIDeviceObject(device),
-																						   _pipelineCache(pipelineCache),
-	   																					   _fullImageViewSwizzle(device->_pMVKConfig->fullImageViewSwizzle)	{}
+	MVKPipeline(MVKDevice* device, MVKPipelineCache* pipelineCache, MVKPipelineLayout* layout, MVKPipeline* parent);
 
 protected:
 	void propogateDebugName() override {}
@@ -167,6 +171,7 @@
 	MVKPipelineCache* _pipelineCache;
 	MVKShaderImplicitRezBinding _swizzleBufferIndex;
 	MVKShaderImplicitRezBinding _bufferSizeBufferIndex;
+	MVKShaderResourceBinding _pushConstantsMTLResourceIndexes;
 	bool _fullImageViewSwizzle;
 	bool _hasValidMTLPipelineStates = true;
 
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
index d3978df..abbdc49 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
@@ -53,11 +53,6 @@
 							  dynamicOffsets, &pDynamicOffsetIndex);
 		setConfigurationResult(dsl.getConfigurationResult());
 	}
-	if (cmdEncoder) {
-		for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
-			cmdEncoder->getPushConstants(mvkVkShaderStageFlagBitsFromMVKShaderStage(MVKShaderStage(i)))->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.stages[i].bufferIndex);
-		}
-	}
 }
 
 // A null cmdEncoder can be passed to perform a validation pass
@@ -68,12 +63,6 @@
 	auto& dsl = _descriptorSetLayouts[set];
 	dsl.pushDescriptorSet(cmdEncoder, descriptorWrites, _dslMTLResourceIndexOffsets[set]);
 	setConfigurationResult(dsl.getConfigurationResult());
-
-	if (cmdEncoder) {
-		for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
-			cmdEncoder->getPushConstants(mvkVkShaderStageFlagBitsFromMVKShaderStage(MVKShaderStage(i)))->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.stages[i].bufferIndex);
-		}
-	}
 }
 
 // A null cmdEncoder can be passed to perform a validation pass
@@ -85,12 +74,6 @@
 	auto& dsl = _descriptorSetLayouts[set];
 	dsl.pushDescriptorSet(cmdEncoder, descUpdateTemplate, pData, _dslMTLResourceIndexOffsets[set]);
 	setConfigurationResult(dsl.getConfigurationResult());
-
-	if (cmdEncoder) {
-		for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
-			cmdEncoder->getPushConstants(mvkVkShaderStageFlagBitsFromMVKShaderStage(MVKShaderStage(i)))->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.stages[i].bufferIndex);
-		}
-	}
 }
 
 void MVKPipelineLayout::populateShaderConverterContext(SPIRVToMSLConversionConfiguration& context) {
@@ -169,6 +152,24 @@
 
 
 #pragma mark -
+#pragma mark MVKPipeline
+
+void MVKPipeline::bindPushConstants(MVKCommandEncoder* cmdEncoder) {
+	if (cmdEncoder) {
+		for (uint32_t i = kMVKShaderStageVertex; i < kMVKShaderStageMax; i++) {
+			cmdEncoder->getPushConstants(mvkVkShaderStageFlagBitsFromMVKShaderStage(MVKShaderStage(i)))->setMTLBufferIndex(_pushConstantsMTLResourceIndexes.stages[i].bufferIndex);
+		}
+	}
+}
+
+MVKPipeline::MVKPipeline(MVKDevice* device, MVKPipelineCache* pipelineCache, MVKPipelineLayout* layout, MVKPipeline* parent) :
+	MVKVulkanAPIDeviceObject(device),
+	_pipelineCache(pipelineCache),
+	_pushConstantsMTLResourceIndexes(layout->getPushConstantBindings()),
+	_fullImageViewSwizzle(device->_pMVKConfig->fullImageViewSwizzle) {}
+
+
+#pragma mark -
 #pragma mark MVKGraphicsPipeline
 
 void MVKGraphicsPipeline::getStages(MVKVector<uint32_t>& stages) {
@@ -285,7 +286,8 @@
 MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
 										 MVKPipelineCache* pipelineCache,
 										 MVKPipeline* parent,
-										 const VkGraphicsPipelineCreateInfo* pCreateInfo) : MVKPipeline(device, pipelineCache, parent) {
+										 const VkGraphicsPipelineCreateInfo* pCreateInfo) :
+	MVKPipeline(device, pipelineCache, (MVKPipelineLayout*)pCreateInfo->layout, parent) {
 
 	// Get the tessellation shaders, if present. Do this now, because we need to extract
 	// reflection data from them that informs everything else.
@@ -1275,7 +1277,9 @@
 MVKComputePipeline::MVKComputePipeline(MVKDevice* device,
 									   MVKPipelineCache* pipelineCache,
 									   MVKPipeline* parent,
-									   const VkComputePipelineCreateInfo* pCreateInfo) : MVKPipeline(device, pipelineCache, parent) {
+									   const VkComputePipelineCreateInfo* pCreateInfo) :
+	MVKPipeline(device, pipelineCache, (MVKPipelineLayout*)pCreateInfo->layout, parent) {
+
 	MVKMTLFunction shaderFunc = getMTLFunction(pCreateInfo);
 	_mtlThreadgroupSize = shaderFunc.threadGroupSize;
 	_mtlPipelineState = nil;