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:
parent
4a0a5cd0b4
commit
0b90a53d76
@ -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];
|
||||
}
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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];
|
||||
|
Loading…
x
Reference in New Issue
Block a user