Fix occasional missing Metal buffer binding when only offset changes.

This fixes an earlier regression, where when only the offset changes in
a buffer descriptor, the binding is not marked dirty if the same Metal
binding index is used by a push constant in between descriptor bindings.

- MVKPushConstantsCommandEncoderState::markDirty() call resource encoder
  state markPushConstantBinding() to find and mark dirty descriptor that
  uses same Metal index as a push constant binding.
- Add MVKResourcesCommandEncoderState::markMetalBufferIndexDirty() to
  find and mark dirty a descriptor buffer binding that uses
- MVKResourcesCommandEncoderState::bind() use range-based-for-loop
  for consistency (unrelated).
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index 9b6287a..ef50c13 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -811,6 +811,7 @@
 - Fix memory estimates for iOS 13+.
 - Broaden conditions for host read sync for image memory barriers on macOS.
 - Fix issue of reseting `CAMetalDrawable` and `MTLTexture` of peer swapchain images.
+- Fix occasional missing Metal buffer binding when only offset changes.
 - Fix the `make install` build command to overwrite the existing framework in the system
   framework library, and update `README.md` to clarify the instructions for using `make install`. 
 - Update the `README.md` and `MoltenVK_Runtime_UserGuide.md` documents to clarify that 
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
index 0def2be..f682927 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
@@ -200,8 +200,9 @@
     /** Sets the index of the Metal buffer used to hold the push constants. */
     void setMTLBufferIndex(uint32_t mtlBufferIndex, bool pipelineStageUsesPushConstants);
 
-    /** Constructs this instance for the specified command encoder. */
-    MVKPushConstantsCommandEncoderState(MVKCommandEncoder* cmdEncoder,
+	void markDirty() override;
+
+	MVKPushConstantsCommandEncoderState(MVKCommandEncoder* cmdEncoder,
                                         VkShaderStageFlagBits shaderStage)
         : MVKCommandEncoderState(cmdEncoder), _shaderStage(shaderStage) {}
 
@@ -364,11 +365,12 @@
 												   MTLResourceUsage mtlUsage,
 												   MTLRenderStages mtlStages) = 0;
 
+	void markDirty() override;
+
     MVKResourcesCommandEncoderState(MVKCommandEncoder* cmdEncoder) :
 		MVKCommandEncoderState(cmdEncoder), _boundDescriptorSets{} {}
 
 protected:
-	void markDirty() override;
 
     // Template function that marks both the vector and all binding elements in the vector as dirty.
     template<class T>
@@ -377,6 +379,18 @@
         bindingsDirtyFlag = true;
     }
 
+	// Find and mark dirty the binding that uses the index.
+	template<class T>
+	void markIndexDirty(T& bindings, bool& bindingsDirtyFlag, uint32_t index) {
+		for (auto& b : bindings) {
+			if (b.index == index) {
+				b.markDirty();
+				bindingsDirtyFlag = true;
+				return;
+			}
+		}
+	}
+
     // Template function that updates an existing binding or adds a new binding to a vector
     // of bindings, and marks the binding, the vector, and this instance as dirty
     template<class T, class V>
@@ -387,9 +401,9 @@
         MVKCommandEncoderState::markDirty();
         bindingsDirtyFlag = true;
 
-        for (auto iter = bindings.begin(), end = bindings.end(); iter != end; ++iter) {
-            if (iter->index == b.index) {
-                iter->update(b);
+        for (auto& rb : bindings) {
+			if (rb.index == b.index) {
+                rb.update(b);
                 return;
             }
         }
@@ -533,6 +547,11 @@
 	/** Offset all buffers for vertex attribute bindings with zero divisors by the given number of strides. */
 	void offsetZeroDivisorVertexBuffers(MVKGraphicsStage stage, MVKGraphicsPipeline* pipeline, uint32_t firstInstance);
 
+	/** Marks the use of the MTLBuffer binding index by a push constant. */
+	void markPushConstantBinding(MVKShaderStage stage, uint32_t mtlBufferIndex);
+
+	void markDirty() override;
+
 #pragma mark Construction
     
     /** Constructs this instance for the specified command encoder. */
@@ -540,7 +559,6 @@
 
 protected:
     void encodeImpl(uint32_t stage) override;
-    void markDirty() override;
 	void bindMetalArgumentBuffer(MVKShaderStage stage, MVKMTLBufferBinding& buffBind) override;
 
     ResourceBindings<8> _shaderStageResourceBindings[4];
@@ -581,6 +599,9 @@
 										   MTLResourceUsage mtlUsage,
 										   MTLRenderStages mtlStages) override;
 
+	/** Marks the use of the MTLBuffer binding index by a push constant. */
+	void markPushConstantBinding(uint32_t mtlBufferIndex);
+
     void markDirty() override;
 
 #pragma mark Construction
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
index 1a36927..44440bc 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm
@@ -180,6 +180,27 @@
 	}
 }
 
+void MVKPushConstantsCommandEncoderState::markDirty() {
+	MVKCommandEncoderState::markDirty();
+	if (_pipelineStageUsesPushConstants) {
+		switch (_shaderStage) {
+			case VK_SHADER_STAGE_VERTEX_BIT:
+			case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
+			case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
+			case VK_SHADER_STAGE_FRAGMENT_BIT:
+				_cmdEncoder->_graphicsResourcesState.markPushConstantBinding(mvkShaderStageFromVkShaderStageFlagBits(_shaderStage),
+																			 _mtlBufferIndex);
+				break;
+			case VK_SHADER_STAGE_COMPUTE_BIT:
+				_cmdEncoder->_computeResourcesState.markPushConstantBinding(_mtlBufferIndex);
+				break;
+			default:
+				MVKAssert(false, "Unsupported shader stage: %d", _shaderStage);
+				break;
+		}
+	}
+}
+
 // At this point, I have been marked not-dirty, under the assumption that I will make changes to the encoder.
 // However, some of the paths below decide not to actually make any changes to the encoder. In that case,
 // I should remain dirty until I actually do make encoder changes.
@@ -982,6 +1003,11 @@
 	}
 }
 
+void MVKGraphicsResourcesCommandEncoderState::markPushConstantBinding(MVKShaderStage stage, uint32_t mtlBufferIndex) {
+	auto& stageRezBinds = _shaderStageResourceBindings[stage];
+	markIndexDirty(stageRezBinds.bufferBindings, stageRezBinds.areBufferBindingsDirty, mtlBufferIndex);
+}
+
 
 #pragma mark -
 #pragma mark MVKComputeResourcesCommandEncoderState
@@ -1115,6 +1141,10 @@
 	}
 }
 
+void MVKComputeResourcesCommandEncoderState::markPushConstantBinding(uint32_t mtlBufferIndex) {
+	markIndexDirty(_resourceBindings.bufferBindings, _resourceBindings.areBufferBindingsDirty, mtlBufferIndex);
+}
+
 
 #pragma mark -
 #pragma mark MVKOcclusionQueryCommandEncoderState