/*
 * MVKDescriptorSetLayout.mm
 *
 * Copyright (c) 2014-2018 The Brenwill Workshop Ltd. (http://www.brenwill.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "MVKDescriptorSet.h"
#include "MVKCommandBuffer.h"
#include "MVKBuffer.h"
#include "MVKFoundation.h"
#include "MVKLogging.h"
#include <stdlib.h>

using namespace std;


#pragma mark MVKShaderStageResourceBinding

MVK_PUBLIC_SYMBOL MVKShaderStageResourceBinding MVKShaderStageResourceBinding::operator+ (const MVKShaderStageResourceBinding& rhs) {
	MVKShaderStageResourceBinding rslt;
	rslt.bufferIndex = this->bufferIndex + rhs.bufferIndex;
	rslt.textureIndex = this->textureIndex + rhs.textureIndex;
	rslt.samplerIndex = this->samplerIndex + rhs.samplerIndex;
	return rslt;
}

MVK_PUBLIC_SYMBOL MVKShaderStageResourceBinding& MVKShaderStageResourceBinding::operator+= (const MVKShaderStageResourceBinding& rhs) {
	this->bufferIndex += rhs.bufferIndex;
	this->textureIndex += rhs.textureIndex;
	this->samplerIndex += rhs.samplerIndex;
	return *this;
}


#pragma mark MVKShaderResourceBinding

MVK_PUBLIC_SYMBOL MVKShaderResourceBinding MVKShaderResourceBinding::operator+ (const MVKShaderResourceBinding& rhs) {
	MVKShaderResourceBinding rslt;
	rslt.vertexStage = this->vertexStage + rhs.vertexStage;
	rslt.fragmentStage = this->fragmentStage + rhs.fragmentStage;
    rslt.computeStage = this->computeStage + rhs.computeStage;
	return rslt;
}

MVK_PUBLIC_SYMBOL MVKShaderResourceBinding& MVKShaderResourceBinding::operator+= (const MVKShaderResourceBinding& rhs) {
	this->vertexStage += rhs.vertexStage;
	this->fragmentStage += rhs.fragmentStage;
    this->computeStage += rhs.computeStage;
	return *this;
}


#pragma mark -
#pragma mark MVKDescriptorSetLayoutBinding

void MVKDescriptorSetLayoutBinding::bind(MVKCommandEncoder* cmdEncoder,
                                         MVKDescriptorBinding& descBinding,
                                         MVKShaderResourceBinding& dslMTLRezIdxOffsets,
                                         vector<uint32_t>& dynamicOffsets,
                                         uint32_t* pDynamicOffsetIndex) {
    MVKMTLBufferBinding bb;
    MVKMTLTextureBinding tb;
    MVKMTLSamplerStateBinding sb;
    NSUInteger bufferDynamicOffset = 0;

    // Establish the resource indices to use, by combining the offsets of the DSL and this DSL binding.
    MVKShaderResourceBinding mtlIdxs = _mtlResourceIndexOffsets + dslMTLRezIdxOffsets;

    for (uint32_t rezIdx = 0; rezIdx < _info.descriptorCount; rezIdx++) {
        switch (_info.descriptorType) {

            // After determining dynamic part of offset (zero otherwise), fall through to non-dynamic handling
            case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
            case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
                bufferDynamicOffset = dynamicOffsets[*pDynamicOffsetIndex];
                (*pDynamicOffsetIndex)++;           // Move on to next dynamic offset (and feedback to caller)
            case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
            case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: {
                bb.mtlBuffer = descBinding._mtlBuffers[rezIdx];
                bb.offset = descBinding._mtlBufferOffsets[rezIdx] + bufferDynamicOffset;
                if (_applyToVertexStage) {
                    bb.index = mtlIdxs.vertexStage.bufferIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindVertexBuffer(bb);
                }
                if (_applyToFragmentStage) {
                    bb.index = mtlIdxs.fragmentStage.bufferIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindFragmentBuffer(bb);
                }
                if (_applyToComputeStage) {
                    bb.index = mtlIdxs.computeStage.bufferIndex + rezIdx;
                    cmdEncoder->_computeResourcesState.bindBuffer(bb);
                }
                break;
            }

            case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
            case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
            case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
            case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
            case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
                tb.mtlTexture = descBinding._mtlTextures[rezIdx];
                if (_applyToVertexStage) {
                    tb.index = mtlIdxs.vertexStage.textureIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindVertexTexture(tb);
                }
                if (_applyToFragmentStage) {
                    tb.index = mtlIdxs.fragmentStage.textureIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindFragmentTexture(tb);
                }
                if (_applyToComputeStage) {
                    tb.index = mtlIdxs.computeStage.textureIndex + rezIdx;
                    cmdEncoder->_computeResourcesState.bindTexture(tb);
                }
                break;
            }

            case VK_DESCRIPTOR_TYPE_SAMPLER: {
                sb.mtlSamplerState = descBinding._mtlSamplers[rezIdx];
                if (_applyToVertexStage) {
                    sb.index = mtlIdxs.vertexStage.samplerIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindVertexSamplerState(sb);
                }
                if (_applyToFragmentStage) {
                    sb.index = mtlIdxs.fragmentStage.samplerIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindFragmentSamplerState(sb);
                }
                if (_applyToComputeStage) {
                    sb.index = mtlIdxs.computeStage.samplerIndex + rezIdx;
                    cmdEncoder->_computeResourcesState.bindSamplerState(sb);
                }
                break;
            }

            case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
                tb.mtlTexture = descBinding._mtlTextures[rezIdx];
                sb.mtlSamplerState = descBinding._mtlSamplers[rezIdx];
                if (_applyToVertexStage) {
                    tb.index = mtlIdxs.vertexStage.textureIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindVertexTexture(tb);
                    sb.index = mtlIdxs.vertexStage.samplerIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindVertexSamplerState(sb);
                }
                if (_applyToFragmentStage) {
                    tb.index = mtlIdxs.fragmentStage.textureIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindFragmentTexture(tb);
                    sb.index = mtlIdxs.fragmentStage.samplerIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindFragmentSamplerState(sb);
                }
                if (_applyToComputeStage) {
                    tb.index = mtlIdxs.computeStage.textureIndex + rezIdx;
                    cmdEncoder->_computeResourcesState.bindTexture(tb);
                    sb.index = mtlIdxs.computeStage.samplerIndex + rezIdx;
                    cmdEncoder->_computeResourcesState.bindSamplerState(sb);
                }
                break;
            }

            default:
                break;
        }
    }
}

void MVKDescriptorSetLayoutBinding::push(MVKCommandEncoder* cmdEncoder,
                                         uint32_t& dstArrayElement,
                                         uint32_t& descriptorCount,
                                         VkDescriptorType descriptorType,
                                         const VkDescriptorImageInfo*& pImageInfo,
                                         const VkDescriptorBufferInfo*& pBufferInfo,
                                         const VkBufferView*& pTexelBufferView,
                                         MVKShaderResourceBinding& dslMTLRezIdxOffsets) {
    MVKMTLBufferBinding bb;
    MVKMTLTextureBinding tb;
    MVKMTLSamplerStateBinding sb;

    if (dstArrayElement >= _info.descriptorCount) {
        dstArrayElement -= _info.descriptorCount;
        return;
    }

    if (descriptorType != _info.descriptorType) {
        dstArrayElement = 0;
        if (_info.descriptorCount > descriptorCount)
            descriptorCount = 0;
        else {
            descriptorCount -= _info.descriptorCount;
            pImageInfo += _info.descriptorCount;
            pBufferInfo += _info.descriptorCount;
            pTexelBufferView += _info.descriptorCount;
        }
        return;
    }

    // Establish the resource indices to use, by combining the offsets of the DSL and this DSL binding.
    MVKShaderResourceBinding mtlIdxs = _mtlResourceIndexOffsets + dslMTLRezIdxOffsets;

    for (uint32_t rezIdx = dstArrayElement;
         rezIdx < _info.descriptorCount && rezIdx - dstArrayElement < descriptorCount;
         rezIdx++) {
        switch (_info.descriptorType) {

            case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
            case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
            case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
            case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: {
                const VkDescriptorBufferInfo& bufferInfo = pBufferInfo[rezIdx - dstArrayElement];
                MVKBuffer* buffer = (MVKBuffer*)bufferInfo.buffer;
                bb.mtlBuffer = buffer->getMTLBuffer();
                bb.offset = bufferInfo.offset;
                if (_applyToVertexStage) {
                    bb.index = mtlIdxs.vertexStage.bufferIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindVertexBuffer(bb);
                }
                if (_applyToFragmentStage) {
                    bb.index = mtlIdxs.fragmentStage.bufferIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindFragmentBuffer(bb);
                }
                if (_applyToComputeStage) {
                    bb.index = mtlIdxs.computeStage.bufferIndex + rezIdx;
                    cmdEncoder->_computeResourcesState.bindBuffer(bb);
                }
                break;
            }

            case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
            case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
            case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
                const VkDescriptorImageInfo& imageInfo = pImageInfo[rezIdx - dstArrayElement];
                MVKImageView* imageView = (MVKImageView*)imageInfo.imageView;
                tb.mtlTexture = imageView->getMTLTexture();
                if (_applyToVertexStage) {
                    tb.index = mtlIdxs.vertexStage.textureIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindVertexTexture(tb);
                }
                if (_applyToFragmentStage) {
                    tb.index = mtlIdxs.fragmentStage.textureIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindFragmentTexture(tb);
                }
                if (_applyToComputeStage) {
                    tb.index = mtlIdxs.computeStage.textureIndex + rezIdx;
                    cmdEncoder->_computeResourcesState.bindTexture(tb);
                }
                break;
            }

            case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
            case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
                MVKBufferView* bufferView = (MVKBufferView*)pTexelBufferView[rezIdx - dstArrayElement];
                tb.mtlTexture = bufferView->getMTLTexture();
                if (_applyToVertexStage) {
                    tb.index = mtlIdxs.vertexStage.textureIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindVertexTexture(tb);
                }
                if (_applyToFragmentStage) {
                    tb.index = mtlIdxs.fragmentStage.textureIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindFragmentTexture(tb);
                }
                if (_applyToComputeStage) {
                    tb.index = mtlIdxs.computeStage.textureIndex + rezIdx;
                    cmdEncoder->_computeResourcesState.bindTexture(tb);
                }
                break;
            }

            case VK_DESCRIPTOR_TYPE_SAMPLER: {
                MVKSampler* sampler;
                if (_immutableSamplers.empty())
                    sampler = (MVKSampler*)pImageInfo[rezIdx - dstArrayElement].sampler;
                else
                    sampler = _immutableSamplers[rezIdx];
                sb.mtlSamplerState = sampler->getMTLSamplerState();
                if (_applyToVertexStage) {
                    sb.index = mtlIdxs.vertexStage.samplerIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindVertexSamplerState(sb);
                }
                if (_applyToFragmentStage) {
                    sb.index = mtlIdxs.fragmentStage.samplerIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindFragmentSamplerState(sb);
                }
                if (_applyToComputeStage) {
                    sb.index = mtlIdxs.computeStage.samplerIndex + rezIdx;
                    cmdEncoder->_computeResourcesState.bindSamplerState(sb);
                }
                break;
            }

            case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
                const VkDescriptorImageInfo& imageInfo = pImageInfo[rezIdx - dstArrayElement];
                MVKImageView* imageView = (MVKImageView*)imageInfo.imageView;
                MVKSampler* sampler = _immutableSamplers.empty() ? (MVKSampler*)imageInfo.sampler : _immutableSamplers[rezIdx];
                tb.mtlTexture = imageView->getMTLTexture();
                sb.mtlSamplerState = sampler->getMTLSamplerState();
                if (_applyToVertexStage) {
                    tb.index = mtlIdxs.vertexStage.textureIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindVertexTexture(tb);
                    sb.index = mtlIdxs.vertexStage.samplerIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindVertexSamplerState(sb);
                }
                if (_applyToFragmentStage) {
                    tb.index = mtlIdxs.fragmentStage.textureIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindFragmentTexture(tb);
                    sb.index = mtlIdxs.fragmentStage.samplerIndex + rezIdx;
                    cmdEncoder->_graphicsResourcesState.bindFragmentSamplerState(sb);
                }
                if (_applyToComputeStage) {
                    tb.index = mtlIdxs.computeStage.textureIndex + rezIdx;
                    cmdEncoder->_computeResourcesState.bindTexture(tb);
                    sb.index = mtlIdxs.computeStage.samplerIndex + rezIdx;
                    cmdEncoder->_computeResourcesState.bindSamplerState(sb);
                }
                break;
            }

            default:
                break;
        }
    }

    dstArrayElement = 0;
    if (_info.descriptorCount > descriptorCount)
        descriptorCount = 0;
    else {
        descriptorCount -= _info.descriptorCount;
        pImageInfo += _info.descriptorCount;
        pBufferInfo += _info.descriptorCount;
        pTexelBufferView += _info.descriptorCount;
    }
}

void MVKDescriptorSetLayoutBinding::populateShaderConverterContext(SPIRVToMSLConverterContext& context,
                                                                   MVKShaderResourceBinding& dslMTLRezIdxOffsets,
                                                                   uint32_t dslIndex) {

    // Establish the resource indices to use, by combining the offsets of the DSL and this DSL binding.
    MVKShaderResourceBinding mtlIdxs = _mtlResourceIndexOffsets + dslMTLRezIdxOffsets;

    if (_applyToVertexStage) {
        mvkPopulateShaderConverterContext(context,
                                          mtlIdxs.vertexStage,
                                          spv::ExecutionModelVertex,
                                          dslIndex,
                                          _info.binding);
    }

    if (_applyToFragmentStage) {
        mvkPopulateShaderConverterContext(context,
                                          mtlIdxs.fragmentStage,
                                          spv::ExecutionModelFragment,
                                          dslIndex,
                                          _info.binding);
    }

    if (_applyToComputeStage) {
        mvkPopulateShaderConverterContext(context,
                                          mtlIdxs.computeStage,
                                          spv::ExecutionModelGLCompute,
                                          dslIndex,
                                          _info.binding);
    }
}

MVKDescriptorSetLayoutBinding::MVKDescriptorSetLayoutBinding(MVKDescriptorSetLayout* layout,
                                                             const VkDescriptorSetLayoutBinding* pBinding) : MVKConfigurableObject() {

    //    MVKLogDebug("Creating MVKDescriptorSetLayoutBinding binding %d.", pBinding->binding);

    // Determine the shader stages used by this binding
    _applyToVertexStage = mvkAreFlagsEnabled(pBinding->stageFlags, VK_SHADER_STAGE_VERTEX_BIT);
    _applyToFragmentStage = mvkAreFlagsEnabled(pBinding->stageFlags, VK_SHADER_STAGE_FRAGMENT_BIT);
    _applyToComputeStage = mvkAreFlagsEnabled(pBinding->stageFlags, VK_SHADER_STAGE_COMPUTE_BIT);

    // If this binding is used by the vertex shader, set the Metal resource index
    if (_applyToVertexStage) {
        setConfigurationResult(initMetalResourceIndexOffsets(&_mtlResourceIndexOffsets.vertexStage,
                                                             &layout->_mtlResourceCounts.vertexStage, pBinding));
    }

    // If this binding is used by the fragment shader, set the Metal resource index
    if (_applyToFragmentStage) {
        setConfigurationResult(initMetalResourceIndexOffsets(&_mtlResourceIndexOffsets.fragmentStage,
                                                             &layout->_mtlResourceCounts.fragmentStage, pBinding));
    }

    // If this binding is used by a compute shader, set the Metal resource index
    if (_applyToComputeStage) {
        setConfigurationResult(initMetalResourceIndexOffsets(&_mtlResourceIndexOffsets.computeStage,
                                                             &layout->_mtlResourceCounts.computeStage, pBinding));
    }

    // If immutable samplers are defined, copy them in
    if ( pBinding->pImmutableSamplers &&
        (pBinding->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
         pBinding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ) {
            _immutableSamplers.reserve(pBinding->descriptorCount);
            for (uint32_t i = 0; i < pBinding->descriptorCount; i++) {
                _immutableSamplers.push_back((MVKSampler*)pBinding->pImmutableSamplers[i]);
            }
        }

    _info = *pBinding;
    _info.pImmutableSamplers = nullptr;     // Remove dangling pointer
}

/**
 * Sets the appropriate Metal resource indexes within this binding from the 
 * specified descriptor set binding counts, and updates those counts accordingly.
 */
VkResult MVKDescriptorSetLayoutBinding::initMetalResourceIndexOffsets(MVKShaderStageResourceBinding* pBindingIndexes,
                                                                      MVKShaderStageResourceBinding* pDescSetCounts,
                                                                      const VkDescriptorSetLayoutBinding* pBinding) {
    switch (pBinding->descriptorType) {
        case VK_DESCRIPTOR_TYPE_SAMPLER:
            pBindingIndexes->samplerIndex = pDescSetCounts->samplerIndex;
            pDescSetCounts->samplerIndex += pBinding->descriptorCount;
            break;

        case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
            pBindingIndexes->textureIndex = pDescSetCounts->textureIndex;
            pDescSetCounts->textureIndex += pBinding->descriptorCount;
            pBindingIndexes->samplerIndex = pDescSetCounts->samplerIndex;
            pDescSetCounts->samplerIndex += pBinding->descriptorCount;
            break;

        case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
        case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
        case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
        case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
        case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
            pBindingIndexes->textureIndex = pDescSetCounts->textureIndex;
            pDescSetCounts->textureIndex += pBinding->descriptorCount;
            break;

        case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
        case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
        case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
        case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
            pBindingIndexes->bufferIndex = pDescSetCounts->bufferIndex;
            pDescSetCounts->bufferIndex += pBinding->descriptorCount;
            break;

        default:
            break;
    }
    return VK_SUCCESS;
}


#pragma mark -
#pragma mark MVKDescriptorSetLayout

void MVKDescriptorSetLayout::bindDescriptorSet(MVKCommandEncoder* cmdEncoder,
                                               MVKDescriptorSet* descSet,
                                               MVKShaderResourceBinding& dslMTLRezIdxOffsets,
                                               vector<uint32_t>& dynamicOffsets,
                                               uint32_t* pDynamicOffsetIndex) {

    if (_isPushDescriptorLayout) return;
    uint32_t bindCnt = (uint32_t)_bindings.size();
    for (uint32_t bindIdx = 0; bindIdx < bindCnt; bindIdx++) {
        _bindings[bindIdx].bind(cmdEncoder, descSet->_bindings[bindIdx],
                                dslMTLRezIdxOffsets, dynamicOffsets,
                                pDynamicOffsetIndex);
    }
}

void MVKDescriptorSetLayout::pushDescriptorSet(MVKCommandEncoder* cmdEncoder,
                                               vector<VkWriteDescriptorSet>& descriptorWrites,
                                               MVKShaderResourceBinding& dslMTLRezIdxOffsets) {

    if (!_isPushDescriptorLayout) return;
    for (const VkWriteDescriptorSet& descWrite : descriptorWrites) {
        uint32_t bindIdx = descWrite.dstBinding;
        uint32_t dstArrayElement = descWrite.dstArrayElement;
        uint32_t descriptorCount = descWrite.descriptorCount;
        const VkDescriptorImageInfo* pImageInfo = descWrite.pImageInfo;
        const VkDescriptorBufferInfo* pBufferInfo = descWrite.pBufferInfo;
        const VkBufferView* pTexelBufferView = descWrite.pTexelBufferView;
        // Note: This will result in us walking off the end of the array
        // in case there are too many updates... but that's ill-defined anyway.
        for (; descriptorCount; bindIdx++) {
            _bindings[bindIdx].push(cmdEncoder, dstArrayElement, descriptorCount,
                                    descWrite.descriptorType, pImageInfo, pBufferInfo,
                                    pTexelBufferView, dslMTLRezIdxOffsets);
        }
    }
}

void MVKDescriptorSetLayout::populateShaderConverterContext(SPIRVToMSLConverterContext& context,
                                                            MVKShaderResourceBinding& dslMTLRezIdxOffsets,
															uint32_t dslIndex) {
	uint32_t bindCnt = (uint32_t)_bindings.size();
	for (uint32_t bindIdx = 0; bindIdx < bindCnt; bindIdx++) {
		_bindings[bindIdx].populateShaderConverterContext(context, dslMTLRezIdxOffsets, dslIndex);
	}
}

MVKDescriptorSetLayout::MVKDescriptorSetLayout(MVKDevice* device,
                                               const VkDescriptorSetLayoutCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
    _isPushDescriptorLayout = (pCreateInfo->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR) != 0;
    // Create the descriptor bindings
    _bindings.reserve(pCreateInfo->bindingCount);
    for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
        _bindings.emplace_back(this, &pCreateInfo->pBindings[i]);
        setConfigurationResult(_bindings.back().getConfigurationResult());
    }
}


#pragma mark -
#pragma mark MVKDescriptorBinding

uint32_t MVKDescriptorBinding::writeBindings(uint32_t srcStartIndex,
											 uint32_t dstStartIndex,
											 uint32_t count,
											 const VkDescriptorImageInfo* pImageInfo,
											 const VkDescriptorBufferInfo* pBufferInfo,
											 const VkBufferView* pTexelBufferView) {

	uint32_t dstCnt = MIN(count, _pBindingLayout->_info.descriptorCount - dstStartIndex);

	switch (_pBindingLayout->_info.descriptorType) {
		case VK_DESCRIPTOR_TYPE_SAMPLER:
			for (uint32_t i = 0; i < dstCnt; i++) {
				uint32_t dstIdx = dstStartIndex + i;
				const VkDescriptorImageInfo* pImgInfo = &pImageInfo[srcStartIndex + i];
				_imageBindings[dstIdx] = *pImgInfo;
				if (_hasDynamicSamplers) {
					_mtlSamplers[dstIdx] = ((MVKSampler*)pImgInfo->sampler)->getMTLSamplerState();
				}
			}
			break;

		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
			for (uint32_t i = 0; i < dstCnt; i++) {
				uint32_t dstIdx = dstStartIndex + i;
				const VkDescriptorImageInfo* pImgInfo = &pImageInfo[srcStartIndex + i];
				_imageBindings[dstIdx] = *pImgInfo;
				_mtlTextures[dstIdx] = ((MVKImageView*)pImgInfo->imageView)->getMTLTexture();
				if (_hasDynamicSamplers) {
					_mtlSamplers[dstIdx] = ((MVKSampler*)pImgInfo->sampler)->getMTLSamplerState();
				}
			}
			break;

		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
		case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
		case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
			for (uint32_t i = 0; i < dstCnt; i++) {
				uint32_t dstIdx = dstStartIndex + i;
				const VkDescriptorImageInfo* pImgInfo = &pImageInfo[srcStartIndex + i];
				_imageBindings[dstIdx] = *pImgInfo;
				_mtlTextures[dstIdx] = ((MVKImageView*)pImgInfo->imageView)->getMTLTexture();
			}
			break;

		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
			for (uint32_t i = 0; i < dstCnt; i++) {
				uint32_t dstIdx = dstStartIndex + i;
				const VkDescriptorBufferInfo* pBuffInfo = &pBufferInfo[srcStartIndex + i];
				_bufferBindings[dstIdx] = *pBuffInfo;
                MVKBuffer* mtlBuff = (MVKBuffer*)pBuffInfo->buffer;
				_mtlBuffers[dstIdx] = mtlBuff->getMTLBuffer();
				_mtlBufferOffsets[dstIdx] = mtlBuff->getMTLBufferOffset() + pBuffInfo->offset;
			}
			break;

        case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
        case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
            for (uint32_t i = 0; i < dstCnt; i++) {
                uint32_t dstIdx = dstStartIndex + i;
                const VkBufferView* pBuffView = &pTexelBufferView[srcStartIndex + i];
                _texelBufferBindings[dstIdx] = *pBuffView;
                _mtlTextures[dstIdx] = ((MVKBufferView*)*pBuffView)->getMTLTexture();
            }
			break;
		default:
			break;
	}

	return count - dstCnt;
}

uint32_t MVKDescriptorBinding::readBindings(uint32_t srcStartIndex,
											uint32_t dstStartIndex,
											uint32_t count,
											VkDescriptorImageInfo* pImageInfo,
											VkDescriptorBufferInfo* pBufferInfo,
											VkBufferView* pTexelBufferView) {

	uint32_t srcCnt = MIN(count, _pBindingLayout->_info.descriptorCount - srcStartIndex);

	switch (_pBindingLayout->_info.descriptorType) {
		case VK_DESCRIPTOR_TYPE_SAMPLER:
		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
		case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
		case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
			for (uint32_t i = 0; i < srcCnt; i++) {
				pImageInfo[dstStartIndex + i] = _imageBindings[srcStartIndex + i];
			}
			break;

		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
			for (uint32_t i = 0; i < srcCnt; i++) {
				pBufferInfo[dstStartIndex + i] = _bufferBindings[srcStartIndex + i];
			}
			break;

		case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
		case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
			for (uint32_t i = 0; i < srcCnt; i++) {
				pTexelBufferView[dstStartIndex + i] = _texelBufferBindings[srcStartIndex + i];
			}
			break;

		default:
			break;
	}

	return count - srcCnt;
}

bool MVKDescriptorBinding::hasBinding(uint32_t binding) {
    return _pBindingLayout->_info.binding == binding;
}

MVKDescriptorBinding::MVKDescriptorBinding(MVKDescriptorSetLayoutBinding* pBindingLayout) : MVKBaseObject() {

	uint32_t descCnt = pBindingLayout->_info.descriptorCount;

	// Create space for the binding and Metal resources and populate with NULL and zero values
	switch (pBindingLayout->_info.descriptorType) {
		case VK_DESCRIPTOR_TYPE_SAMPLER:
			_imageBindings.resize(descCnt, VkDescriptorImageInfo());
			initMTLSamplers(pBindingLayout);
			break;

		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
			_imageBindings.resize(descCnt, VkDescriptorImageInfo());
			_mtlTextures.resize(descCnt, VK_NULL_HANDLE);
			initMTLSamplers(pBindingLayout);
			break;

		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
		case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
		case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
			_imageBindings.resize(descCnt, VkDescriptorImageInfo());
			_mtlTextures.resize(descCnt, VK_NULL_HANDLE);
			break;

		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
			_bufferBindings.resize(descCnt, VkDescriptorBufferInfo());
			_mtlBuffers.resize(descCnt, VK_NULL_HANDLE);
			_mtlBufferOffsets.resize(descCnt, 0);
			break;

		case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
		case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
			_texelBufferBindings.resize(descCnt, VK_NULL_HANDLE);
            _mtlTextures.resize(descCnt, VK_NULL_HANDLE);
			break;

		default:
			break;
	}

    // Okay to hold layout as a pointer. From the Vulkan spec...
    // "VkDescriptorSetLayout objects may be accessed by commands that operate on descriptor
    //  sets allocated using that layout, and those descriptor sets must not be updated with
    //  vkUpdateDescriptorSets after the descriptor set layout has been destroyed.
    _pBindingLayout = pBindingLayout;
}

/**
 * If the descriptor set layout binding contains immutable samplers, immediately populate
 * the corresponding Metal sampler in this descriptor binding from it. Otherwise add a null
 * placeholder that will be populated dynamically at a later time.
 */
void MVKDescriptorBinding::initMTLSamplers(MVKDescriptorSetLayoutBinding* pBindingLayout) {
    uint32_t descCnt = pBindingLayout->_info.descriptorCount;
    auto imtblSamps = pBindingLayout->_immutableSamplers;
    _hasDynamicSamplers = imtblSamps.empty();

    _mtlSamplers.reserve(descCnt);
    for (uint32_t i = 0; i < descCnt; i++) {
        _mtlSamplers.push_back(_hasDynamicSamplers ? VK_NULL_HANDLE : imtblSamps[i]->getMTLSamplerState());
    }
}


#pragma mark -
#pragma mark MVKDescriptorSet

template<typename DescriptorAction>
void MVKDescriptorSet::writeDescriptorSets(const DescriptorAction* pDescriptorAction,
                                           const VkDescriptorImageInfo* pImageInfo,
                                           const VkDescriptorBufferInfo* pBufferInfo,
                                           const VkBufferView* pTexelBufferView) {
    uint32_t dstStartIdx = pDescriptorAction->dstArrayElement;
    uint32_t binding = pDescriptorAction->dstBinding;
    uint32_t origCnt = pDescriptorAction->descriptorCount;
    uint32_t remainCnt = origCnt;

//    MVKLogDebug("Writing descriptor sets with buffer info %p starting at binding point %d.", pBufferInfo, binding);

    MVKDescriptorBinding* mvkDescBind = getBinding(binding);
    while (mvkDescBind && remainCnt > 0) {

//        MVKLogDebug("Writing MVKDescriptorBinding with binding point %d.", binding);

        uint32_t srcStartIdx = origCnt - remainCnt;
        remainCnt = mvkDescBind->writeBindings(srcStartIdx, dstStartIdx, remainCnt,
                                               pImageInfo, pBufferInfo, pTexelBufferView);

        binding++;                              // If not consumed, move to next consecutive binding point
        mvkDescBind = getBinding(binding);
        dstStartIdx = 0;                        // Subsequent bindings start reading at first element
    }
}

// Create concrete implementations of the two variations of the writeDescriptorSets() function.
template void MVKDescriptorSet::writeDescriptorSets<VkWriteDescriptorSet>(const VkWriteDescriptorSet* pDescriptorAction,
																		  const VkDescriptorImageInfo* pImageInfo,
																		  const VkDescriptorBufferInfo* pBufferInfo,
																		  const VkBufferView* pTexelBufferView);
template void MVKDescriptorSet::writeDescriptorSets<VkCopyDescriptorSet>(const VkCopyDescriptorSet* pDescriptorAction,
																		 const VkDescriptorImageInfo* pImageInfo,
																		 const VkDescriptorBufferInfo* pBufferInfo,
																		 const VkBufferView* pTexelBufferView);

void MVKDescriptorSet::readDescriptorSets(const VkCopyDescriptorSet* pDescriptorCopy,
										  VkDescriptorImageInfo* pImageInfo,
										  VkDescriptorBufferInfo* pBufferInfo,
										  VkBufferView* pTexelBufferView) {
	uint32_t srcStartIdx = pDescriptorCopy->srcArrayElement;
    uint32_t binding = pDescriptorCopy->srcBinding;
    uint32_t origCnt = pDescriptorCopy->descriptorCount;
    uint32_t remainCnt = origCnt;

//    MVKLogDebug("Reading descriptor sets with buffer info %p starting at binding point %d.", pBufferInfo, binding);

    MVKDescriptorBinding* mvkDescBind = getBinding(binding);
    while (mvkDescBind && remainCnt > 0) {

//        MVKLogDebug("Reading MVKDescriptorBinding with binding point %d.", binding);

        uint32_t dstStartIdx = origCnt - remainCnt;
        remainCnt = mvkDescBind->readBindings(srcStartIdx, dstStartIdx, remainCnt,
                                              pImageInfo, pBufferInfo, pTexelBufferView);

        binding++;                              // If not consumed, move to next consecutive binding point
        mvkDescBind = getBinding(binding);
        srcStartIdx = 0;                        // Subsequent bindings start reading at first element
    }
}

// Returns the binding instance that is assigned the specified
// binding number, or returns null if no such binding exists.
MVKDescriptorBinding* MVKDescriptorSet::getBinding(uint32_t binding) {
    for (auto& mvkDB : _bindings) { if (mvkDB.hasBinding(binding)) { return &mvkDB; } }
    return nullptr;
}

MVKDescriptorSet::MVKDescriptorSet(MVKDevice* device,
								   MVKDescriptorSetLayout* layout) : MVKBaseDeviceObject(device) {

	// Create the binding slots, each referencing a corresponding binding layout
	uint32_t bindCnt = (uint32_t)layout->_bindings.size();
	_bindings.reserve(bindCnt);
	for (uint32_t i = 0; i < bindCnt; i++) {
        _bindings.emplace_back(&layout->_bindings[i]);
	}
}


#pragma mark -
#pragma mark MVKDescriptorPool

VkResult MVKDescriptorPool::allocateDescriptorSets(uint32_t count,
												   const VkDescriptorSetLayout* pSetLayouts,
												   VkDescriptorSet* pDescriptorSets) {
	if (_allocatedSetCount + count > _maxSets) {
		if (_device->_enabledExtensions.vk_KHR_maintenance1.enabled) {
			return VK_ERROR_OUT_OF_POOL_MEMORY;		// Failure is an acceptable test...don't log as error.
		} else {
			return mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "The maximum number of descriptor sets that can be allocated by this descriptor pool is %d.", _maxSets);
		}
	}

	for (uint32_t dsIdx = 0; dsIdx < count; dsIdx++) {
		MVKDescriptorSetLayout* mvkDSL = (MVKDescriptorSetLayout*)pSetLayouts[dsIdx];
		if (mvkDSL->isPushDescriptorLayout()) continue;
		MVKDescriptorSet* mvkDescSet = new MVKDescriptorSet(_device, mvkDSL);
		_allocatedSets.push_front(mvkDescSet);
		pDescriptorSets[dsIdx] = (VkDescriptorSet)mvkDescSet;
		_allocatedSetCount++;
	}
	return VK_SUCCESS;
}

VkResult MVKDescriptorPool::freeDescriptorSets(uint32_t count, const VkDescriptorSet* pDescriptorSets) {
	for (uint32_t dsIdx = 0; dsIdx < count; dsIdx++) {
		MVKDescriptorSet* mvkDS = (MVKDescriptorSet*)pDescriptorSets[dsIdx];
		if (mvkDS) {
			_allocatedSets.remove(mvkDS);
			_allocatedSetCount--;
			mvkDS->destroy();
		}
	}
	return VK_SUCCESS;
}

VkResult MVKDescriptorPool::reset(VkDescriptorPoolResetFlags flags) {
	mvkDestroyContainerContents(_allocatedSets);
	_allocatedSetCount = 0;
	return VK_SUCCESS;
}

MVKDescriptorPool::MVKDescriptorPool(MVKDevice* device,
									 const VkDescriptorPoolCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
	_maxSets = pCreateInfo->maxSets;
	_allocatedSetCount = 0;
}

// TODO: Destroying a descriptor pool implicitly destroys all descriptor sets created from it.

MVKDescriptorPool::~MVKDescriptorPool() {
//	MVKLogDebug("Pool %p destroyed with %d descriptor sets.", this, _allocatedSetCount);
	reset(0);
}


#pragma mark -
#pragma mark Support functions

/** Updates the resource bindings in the descriptor sets inditified in the specified content. */
void mvkUpdateDescriptorSets(uint32_t writeCount,
							 const VkWriteDescriptorSet* pDescriptorWrites,
							 uint32_t copyCount,
							 const VkCopyDescriptorSet* pDescriptorCopies) {

	// Perform the write updates
	for (uint32_t i = 0; i < writeCount; i++) {
		const VkWriteDescriptorSet* pDescWrite = &pDescriptorWrites[i];
		MVKDescriptorSet* dstSet = (MVKDescriptorSet*)pDescWrite->dstSet;
		dstSet->writeDescriptorSets(pDescWrite,
									pDescWrite->pImageInfo,
									pDescWrite->pBufferInfo,
									pDescWrite->pTexelBufferView);
	}

	// Perform the copy updates by reading bindings from one set and writing to other set.
	for (uint32_t i = 0; i < copyCount; i++) {
		const VkCopyDescriptorSet* pDescCopy = &pDescriptorCopies[i];

		uint32_t descCnt = pDescCopy->descriptorCount;
		VkDescriptorImageInfo imgInfos[descCnt];
		VkDescriptorBufferInfo buffInfos[descCnt];
		VkBufferView texelBuffInfos[descCnt];

		MVKDescriptorSet* srcSet = (MVKDescriptorSet*)pDescCopy->srcSet;
		srcSet->readDescriptorSets(pDescCopy, imgInfos, buffInfos, texelBuffInfos);

		MVKDescriptorSet* dstSet = (MVKDescriptorSet*)pDescCopy->dstSet;
		dstSet->writeDescriptorSets(pDescCopy, imgInfos, buffInfos, texelBuffInfos);
	}
}

void mvkPopulateShaderConverterContext(SPIRVToMSLConverterContext& context,
									   MVKShaderStageResourceBinding& ssRB,
									   spv::ExecutionModel stage,
									   uint32_t descriptorSetIndex,
									   uint32_t bindingIndex) {
	MSLResourceBinding ctxRB;
    ctxRB.stage = stage;
    ctxRB.descriptorSet = descriptorSetIndex;
    ctxRB.binding = bindingIndex;
    ctxRB.mslBuffer = ssRB.bufferIndex;
    ctxRB.mslTexture = ssRB.textureIndex;
    ctxRB.mslSampler = ssRB.samplerIndex;
    context.resourceBindings.push_back(ctxRB);
}


