blob: 2a07854c3acb00ca687306084bcb007a8716de43 [file] [log] [blame]
/*
* 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(MTLPixelFormat mtlPixFmt) {
id<MTLRenderPipelineState> rps = _cmdBlitImageMTLRenderPipelineStates[mtlPixFmt];
if ( !rps ) {
rps = _device->getCommandResourceFactory()->newCmdBlitImageMTLRenderPipelineState(mtlPixFmt); // retained
_cmdBlitImageMTLRenderPipelineStates[mtlPixFmt] = 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;
}