/*
 * MVKCommandEncodingPool.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 "MVKCommandEncodingPool.h"
#include "MVKImage.h"

using namespace std;

#pragma mark -
#pragma mark MVKCommandEncodingPool

id<MTLRenderPipelineState> MVKCommandEncodingPool::getCmdClearMTLRenderPipelineState(MVKRPSKeyClearAtt& attKey) {
	id<MTLRenderPipelineState> rps = _cmdClearMTLRenderPipelineStates[attKey];
	if ( !rps ) {
		rps = _device->getCommandResourceFactory()->newCmdClearMTLRenderPipelineState(attKey);		// retained
		_cmdClearMTLRenderPipelineStates[attKey] = rps;
	}
	return rps;
}

id<MTLRenderPipelineState> MVKCommandEncodingPool::getCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey) {
    id<MTLRenderPipelineState> rps = _cmdBlitImageMTLRenderPipelineStates[blitKey];
    if ( !rps ) {
        rps = _device->getCommandResourceFactory()->newCmdBlitImageMTLRenderPipelineState(blitKey);	// retained
        _cmdBlitImageMTLRenderPipelineStates[blitKey] = rps;
    }
    return rps;
}

id<MTLSamplerState> MVKCommandEncodingPool::getCmdBlitImageMTLSamplerState(MTLSamplerMinMagFilter mtlFilter) {
    switch (mtlFilter) {
        case MTLSamplerMinMagFilterNearest:
            if ( !_cmdBlitImageNearestMTLSamplerState ) {
                _cmdBlitImageNearestMTLSamplerState = _device->getCommandResourceFactory()->newCmdBlitImageMTLSamplerState(mtlFilter);	// retained
            }
            return _cmdBlitImageNearestMTLSamplerState;

        case MTLSamplerMinMagFilterLinear:
            if ( !_cmdBlitImageLinearMTLSamplerState ) {
                _cmdBlitImageLinearMTLSamplerState = _device->getCommandResourceFactory()->newCmdBlitImageMTLSamplerState(mtlFilter);		// retained
            }
            return _cmdBlitImageLinearMTLSamplerState;
    }
}

id<MTLDepthStencilState> MVKCommandEncodingPool::getMTLDepthStencilState(bool useDepth, bool useStencil) {

    if (useDepth && useStencil) {
        if ( !_cmdClearDepthAndStencilDepthStencilState ) {
            _cmdClearDepthAndStencilDepthStencilState = _device->getCommandResourceFactory()->newMTLDepthStencilState(useDepth, useStencil);  // retained
        }
        return _cmdClearDepthAndStencilDepthStencilState;
    }

    if (useDepth) {
        if ( !_cmdClearDepthOnlyDepthStencilState ) {
            _cmdClearDepthOnlyDepthStencilState = _device->getCommandResourceFactory()->newMTLDepthStencilState(useDepth, useStencil);  // retained
        }
        return _cmdClearDepthOnlyDepthStencilState;
    }

    if (useStencil) {
        if ( !_cmdClearStencilOnlyDepthStencilState ) {
            _cmdClearStencilOnlyDepthStencilState = _device->getCommandResourceFactory()->newMTLDepthStencilState(useDepth, useStencil);  // retained
        }
        return _cmdClearStencilOnlyDepthStencilState;
    }

    if ( !_cmdClearDefaultDepthStencilState ) {
        _cmdClearDefaultDepthStencilState = _device->getCommandResourceFactory()->newMTLDepthStencilState(useDepth, useStencil);  // retained
    }
    return _cmdClearDefaultDepthStencilState;
}

const MVKMTLBufferAllocation* MVKCommandEncodingPool::acquireMTLBufferAllocation(NSUInteger length) {
    return _mtlBufferAllocator.acquireMTLBufferRegion(length);
}


id<MTLDepthStencilState> MVKCommandEncodingPool::getMTLDepthStencilState(MVKMTLDepthStencilDescriptorData& dsData) {
    id<MTLDepthStencilState> dss = _mtlDepthStencilStates[dsData];
    if ( !dss ) {
        dss = _device->getCommandResourceFactory()->newMTLDepthStencilState(dsData);		// retained
        _mtlDepthStencilStates[dsData] = dss;
    }
    return dss;
}

MVKImage* MVKCommandEncodingPool::getTransferMVKImage(MVKImageDescriptorData& imgData) {
    MVKImage* mvkImg = _transferImages[imgData];
    if ( !mvkImg ) {
        mvkImg = _device->getCommandResourceFactory()->newMVKImage(imgData);
        mvkImg->bindDeviceMemory(_transferImageMemory, 0);
        _transferImages[imgData] = mvkImg;
    }
    return mvkImg;
}

id<MTLComputePipelineState> MVKCommandEncodingPool::getCopyBufferBytesComputePipelineState() {
    if (_mtlCopyBufferBytesComputePipelineState == nil) {
        _mtlCopyBufferBytesComputePipelineState = _device->getCommandResourceFactory()->newCopyBytesMTLComputePipelineState();
    }
    return _mtlCopyBufferBytesComputePipelineState;
}

#pragma mark Construction

MVKCommandEncodingPool::MVKCommandEncodingPool(MVKDevice* device) : MVKBaseDeviceObject(device),
    _mtlBufferAllocator(device, device->_pMetalFeatures->maxMTLBufferSize) {

    _cmdBlitImageLinearMTLSamplerState = nil;
    _cmdBlitImageNearestMTLSamplerState = nil;
    _cmdClearDepthAndStencilDepthStencilState = nil;
    _cmdClearDepthOnlyDepthStencilState = nil;
    _cmdClearStencilOnlyDepthStencilState = nil;
    _cmdClearDefaultDepthStencilState = nil;
    _mtlCopyBufferBytesComputePipelineState = nil;

    initTextureDeviceMemory();
}

// Initializes the empty device memory used to back temporary VkImages.
void MVKCommandEncodingPool::initTextureDeviceMemory() {
    VkMemoryAllocateInfo allocInfo = {
        .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
        .pNext = NULL,
        .allocationSize = 0,
        .memoryTypeIndex = _device->getVulkanMemoryTypeIndex(MTLStorageModePrivate),
    };
    _transferImageMemory = _device->allocateMemory(&allocInfo, nullptr);
}

MVKCommandEncodingPool::~MVKCommandEncodingPool() {
    if (_transferImageMemory) { _transferImageMemory->destroy(); }
	destroyMetalResources();
}

/**  Ensure all cached Metal components are released. */
void MVKCommandEncodingPool::destroyMetalResources() {
    for (auto& pair : _cmdBlitImageMTLRenderPipelineStates) { [pair.second release]; }
    _cmdBlitImageMTLRenderPipelineStates.clear();

    for (auto& pair : _cmdClearMTLRenderPipelineStates) { [pair.second release]; }
    _cmdClearMTLRenderPipelineStates.clear();

    for (auto& pair : _mtlDepthStencilStates) { [pair.second release]; }
    _mtlDepthStencilStates.clear();

    for (auto& pair : _transferImages) { pair.second->destroy(); }
    _transferImages.clear();

    [_cmdBlitImageLinearMTLSamplerState release];
    _cmdBlitImageLinearMTLSamplerState = nil;

    [_cmdBlitImageNearestMTLSamplerState release];
    _cmdBlitImageNearestMTLSamplerState = nil;

    [_cmdClearDepthAndStencilDepthStencilState release];
    _cmdClearDepthAndStencilDepthStencilState = nil;

    [_cmdClearDepthOnlyDepthStencilState release];
    _cmdClearDepthOnlyDepthStencilState = nil;

    [_cmdClearStencilOnlyDepthStencilState release];
    _cmdClearStencilOnlyDepthStencilState = nil;

    [_cmdClearDefaultDepthStencilState release];
    _cmdClearDefaultDepthStencilState = nil;

    [_mtlCopyBufferBytesComputePipelineState release];
    _mtlCopyBufferBytesComputePipelineState = nil;
}

