Fixes for CTS multithread tests.

MTLDevice retains an internal object web that is used during the creation of
new objects, such as pipeline states, libraries, functions, and samplers.
Simultaneously creating and destroying objects of these types can trigger
race conditions on the internal MTLDevice content.

Wrap the following in @synchronized (mtlDevice) {...}:
- MTLRenderPipelineState creation and destruction
- MTLComputePipelineState creation and destruction
- MTLLibrary creation
- MTLFunction creation and specialization
- MTLSampler creation and destruction
This commit is contained in:
Bill Hollings 2021-02-17 09:33:04 -05:00
parent 4a0a5cd0b4
commit 0b90a53d76
3 changed files with 63 additions and 42 deletions

View File

@ -1972,9 +1972,10 @@ MVKSampler::MVKSampler(MVKDevice* device, const VkSamplerCreateInfo* pCreateInfo
_requiresConstExprSampler = (pCreateInfo->compareEnable && !_device->_pMetalFeatures->depthSampleCompare) || _ycbcrConversion;
@autoreleasepool {
MTLSamplerDescriptor* mtlSampDesc = newMTLSamplerDescriptor(pCreateInfo); // temp retain
_mtlSamplerState = [getMTLDevice() newSamplerStateWithDescriptor: mtlSampDesc];
[mtlSampDesc release]; // temp release
auto mtlDev = getMTLDevice();
@synchronized (mtlDev) {
_mtlSamplerState = [mtlDev newSamplerStateWithDescriptor: [newMTLSamplerDescriptor(pCreateInfo) autorelease]];
}
}
initConstExprSampler(pCreateInfo);
@ -2060,5 +2061,7 @@ void MVKSampler::initConstExprSampler(const VkSamplerCreateInfo* pCreateInfo) {
}
MVKSampler::~MVKSampler() {
[_mtlSamplerState release];
@synchronized (getMTLDevice()) {
[_mtlSamplerState release];
}
}

View File

@ -1603,15 +1603,17 @@ bool MVKGraphicsPipeline::isRasterizationDisabled(const VkGraphicsPipelineCreate
}
MVKGraphicsPipeline::~MVKGraphicsPipeline() {
[_mtlTessVertexStageDesc release];
@synchronized (getMTLDevice()) {
[_mtlTessVertexStageDesc release];
[_mtlTessVertexStageState release];
[_mtlTessVertexStageIndex16State release];
[_mtlTessVertexStageIndex32State release];
[_mtlTessControlStageState release];
[_mtlPipelineState release];
[_mtlTessVertexStageState release];
[_mtlTessVertexStageIndex16State release];
[_mtlTessVertexStageIndex32State release];
[_mtlTessControlStageState release];
[_mtlPipelineState release];
for (id<MTLFunction> func : _mtlTessVertexFunctions) { [func release]; }
for (id<MTLFunction> func : _mtlTessVertexFunctions) { [func release]; }
}
}
@ -1716,7 +1718,9 @@ MVKMTLFunction MVKComputePipeline::getMTLFunction(const VkComputePipelineCreateI
}
MVKComputePipeline::~MVKComputePipeline() {
[_mtlPipelineState release];
@synchronized (getMTLDevice()) {
[_mtlPipelineState release];
}
}
@ -2147,11 +2151,14 @@ id<MTLRenderPipelineState> MVKRenderPipelineCompiler::newMTLRenderPipelineState(
unique_lock<mutex> lock(_completionLock);
compile(lock, ^{
[_owner->getMTLDevice() newRenderPipelineStateWithDescriptor: mtlRPLDesc
completionHandler: ^(id<MTLRenderPipelineState> ps, NSError* error) {
bool isLate = compileComplete(ps, error);
if (isLate) { destroy(); }
}];
auto mtlDev = _owner->getMTLDevice();
@synchronized (mtlDev) {
[mtlDev newRenderPipelineStateWithDescriptor: mtlRPLDesc
completionHandler: ^(id<MTLRenderPipelineState> ps, NSError* error) {
bool isLate = compileComplete(ps, error);
if (isLate) { destroy(); }
}];
}
});
return [_mtlRenderPipelineState retain];
@ -2178,11 +2185,14 @@ id<MTLComputePipelineState> MVKComputePipelineCompiler::newMTLComputePipelineSta
unique_lock<mutex> lock(_completionLock);
compile(lock, ^{
[_owner->getMTLDevice() newComputePipelineStateWithFunction: mtlFunction
completionHandler: ^(id<MTLComputePipelineState> ps, NSError* error) {
bool isLate = compileComplete(ps, error);
if (isLate) { destroy(); }
}];
auto mtlDev = _owner->getMTLDevice();
@synchronized (mtlDev) {
[mtlDev newComputePipelineStateWithFunction: mtlFunction
completionHandler: ^(id<MTLComputePipelineState> ps, NSError* error) {
bool isLate = compileComplete(ps, error);
if (isLate) { destroy(); }
}];
}
});
return [_mtlComputePipelineState retain];
@ -2192,12 +2202,15 @@ id<MTLComputePipelineState> MVKComputePipelineCompiler::newMTLComputePipelineSta
unique_lock<mutex> lock(_completionLock);
compile(lock, ^{
[_owner->getMTLDevice() newComputePipelineStateWithDescriptor: plDesc
options: MTLPipelineOptionNone
completionHandler: ^(id<MTLComputePipelineState> ps, MTLComputePipelineReflection*, NSError* error) {
bool isLate = compileComplete(ps, error);
if (isLate) { destroy(); }
}];
auto mtlDev = _owner->getMTLDevice();
@synchronized (mtlDev) {
[mtlDev newComputePipelineStateWithDescriptor: plDesc
options: MTLPipelineOptionNone
completionHandler: ^(id<MTLComputePipelineState> ps, MTLComputePipelineReflection*, NSError* error) {
bool isLate = compileComplete(ps, error);
if (isLate) { destroy(); }
}];
}
});
return [_mtlComputePipelineState retain];

View File

@ -62,7 +62,7 @@ MVKMTLFunction MVKShaderLibrary::getMTLFunction(const VkSpecializationInfo* pSpe
if ( !_mtlLibrary ) { return MVKMTLFunctionNull; }
@synchronized (_mtlLibrary) {
@synchronized (_owner->getMTLDevice()) {
@autoreleasepool {
NSString* mtlFuncName = @(_shaderConversionResults.entryPoint.mtlFunctionName.c_str());
MVKDevice* mvkDev = _owner->getDevice();
@ -423,13 +423,16 @@ id<MTLLibrary> MVKShaderLibraryCompiler::newMTLLibrary(NSString* mslSourceCode,
unique_lock<mutex> lock(_completionLock);
compile(lock, ^{
[_owner->getMTLDevice() newLibraryWithSource: mslSourceCode
options: _owner->getDevice()->getMTLCompileOptions(shaderConversionResults.entryPoint.supportsFastMath,
shaderConversionResults.isPositionInvariant)
completionHandler: ^(id<MTLLibrary> mtlLib, NSError* error) {
bool isLate = compileComplete(mtlLib, error);
if (isLate) { destroy(); }
}];
auto mtlDev = _owner->getMTLDevice();
@synchronized (mtlDev) {
[mtlDev newLibraryWithSource: mslSourceCode
options: _owner->getDevice()->getMTLCompileOptions(shaderConversionResults.entryPoint.supportsFastMath,
shaderConversionResults.isPositionInvariant)
completionHandler: ^(id<MTLLibrary> mtlLib, NSError* error) {
bool isLate = compileComplete(mtlLib, error);
if (isLate) { destroy(); }
}];
}
});
return [_mtlLibrary retain];
@ -467,12 +470,14 @@ id<MTLFunction> MVKFunctionSpecializer::newMTLFunction(id<MTLLibrary> mtlLibrary
unique_lock<mutex> lock(_completionLock);
compile(lock, ^{
[mtlLibrary newFunctionWithName: funcName
constantValues: constantValues
completionHandler: ^(id<MTLFunction> mtlFunc, NSError* error) {
bool isLate = compileComplete(mtlFunc, error);
if (isLate) { destroy(); }
}];
@synchronized (_owner->getMTLDevice()) {
[mtlLibrary newFunctionWithName: funcName
constantValues: constantValues
completionHandler: ^(id<MTLFunction> mtlFunc, NSError* error) {
bool isLate = compileComplete(mtlFunc, error);
if (isLate) { destroy(); }
}];
}
});
return [_mtlFunction retain];