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;
|
_requiresConstExprSampler = (pCreateInfo->compareEnable && !_device->_pMetalFeatures->depthSampleCompare) || _ycbcrConversion;
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
MTLSamplerDescriptor* mtlSampDesc = newMTLSamplerDescriptor(pCreateInfo); // temp retain
|
auto mtlDev = getMTLDevice();
|
||||||
_mtlSamplerState = [getMTLDevice() newSamplerStateWithDescriptor: mtlSampDesc];
|
@synchronized (mtlDev) {
|
||||||
[mtlSampDesc release]; // temp release
|
_mtlSamplerState = [mtlDev newSamplerStateWithDescriptor: [newMTLSamplerDescriptor(pCreateInfo) autorelease]];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initConstExprSampler(pCreateInfo);
|
initConstExprSampler(pCreateInfo);
|
||||||
@ -2060,5 +2061,7 @@ void MVKSampler::initConstExprSampler(const VkSamplerCreateInfo* pCreateInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MVKSampler::~MVKSampler() {
|
MVKSampler::~MVKSampler() {
|
||||||
|
@synchronized (getMTLDevice()) {
|
||||||
[_mtlSamplerState release];
|
[_mtlSamplerState release];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1603,6 +1603,7 @@ bool MVKGraphicsPipeline::isRasterizationDisabled(const VkGraphicsPipelineCreate
|
|||||||
}
|
}
|
||||||
|
|
||||||
MVKGraphicsPipeline::~MVKGraphicsPipeline() {
|
MVKGraphicsPipeline::~MVKGraphicsPipeline() {
|
||||||
|
@synchronized (getMTLDevice()) {
|
||||||
[_mtlTessVertexStageDesc release];
|
[_mtlTessVertexStageDesc release];
|
||||||
|
|
||||||
[_mtlTessVertexStageState release];
|
[_mtlTessVertexStageState release];
|
||||||
@ -1612,6 +1613,7 @@ MVKGraphicsPipeline::~MVKGraphicsPipeline() {
|
|||||||
[_mtlPipelineState 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() {
|
MVKComputePipeline::~MVKComputePipeline() {
|
||||||
|
@synchronized (getMTLDevice()) {
|
||||||
[_mtlPipelineState release];
|
[_mtlPipelineState release];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2147,11 +2151,14 @@ id<MTLRenderPipelineState> MVKRenderPipelineCompiler::newMTLRenderPipelineState(
|
|||||||
unique_lock<mutex> lock(_completionLock);
|
unique_lock<mutex> lock(_completionLock);
|
||||||
|
|
||||||
compile(lock, ^{
|
compile(lock, ^{
|
||||||
[_owner->getMTLDevice() newRenderPipelineStateWithDescriptor: mtlRPLDesc
|
auto mtlDev = _owner->getMTLDevice();
|
||||||
|
@synchronized (mtlDev) {
|
||||||
|
[mtlDev newRenderPipelineStateWithDescriptor: mtlRPLDesc
|
||||||
completionHandler: ^(id<MTLRenderPipelineState> ps, NSError* error) {
|
completionHandler: ^(id<MTLRenderPipelineState> ps, NSError* error) {
|
||||||
bool isLate = compileComplete(ps, error);
|
bool isLate = compileComplete(ps, error);
|
||||||
if (isLate) { destroy(); }
|
if (isLate) { destroy(); }
|
||||||
}];
|
}];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return [_mtlRenderPipelineState retain];
|
return [_mtlRenderPipelineState retain];
|
||||||
@ -2178,11 +2185,14 @@ id<MTLComputePipelineState> MVKComputePipelineCompiler::newMTLComputePipelineSta
|
|||||||
unique_lock<mutex> lock(_completionLock);
|
unique_lock<mutex> lock(_completionLock);
|
||||||
|
|
||||||
compile(lock, ^{
|
compile(lock, ^{
|
||||||
[_owner->getMTLDevice() newComputePipelineStateWithFunction: mtlFunction
|
auto mtlDev = _owner->getMTLDevice();
|
||||||
|
@synchronized (mtlDev) {
|
||||||
|
[mtlDev newComputePipelineStateWithFunction: mtlFunction
|
||||||
completionHandler: ^(id<MTLComputePipelineState> ps, NSError* error) {
|
completionHandler: ^(id<MTLComputePipelineState> ps, NSError* error) {
|
||||||
bool isLate = compileComplete(ps, error);
|
bool isLate = compileComplete(ps, error);
|
||||||
if (isLate) { destroy(); }
|
if (isLate) { destroy(); }
|
||||||
}];
|
}];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return [_mtlComputePipelineState retain];
|
return [_mtlComputePipelineState retain];
|
||||||
@ -2192,12 +2202,15 @@ id<MTLComputePipelineState> MVKComputePipelineCompiler::newMTLComputePipelineSta
|
|||||||
unique_lock<mutex> lock(_completionLock);
|
unique_lock<mutex> lock(_completionLock);
|
||||||
|
|
||||||
compile(lock, ^{
|
compile(lock, ^{
|
||||||
[_owner->getMTLDevice() newComputePipelineStateWithDescriptor: plDesc
|
auto mtlDev = _owner->getMTLDevice();
|
||||||
|
@synchronized (mtlDev) {
|
||||||
|
[mtlDev newComputePipelineStateWithDescriptor: plDesc
|
||||||
options: MTLPipelineOptionNone
|
options: MTLPipelineOptionNone
|
||||||
completionHandler: ^(id<MTLComputePipelineState> ps, MTLComputePipelineReflection*, NSError* error) {
|
completionHandler: ^(id<MTLComputePipelineState> ps, MTLComputePipelineReflection*, NSError* error) {
|
||||||
bool isLate = compileComplete(ps, error);
|
bool isLate = compileComplete(ps, error);
|
||||||
if (isLate) { destroy(); }
|
if (isLate) { destroy(); }
|
||||||
}];
|
}];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return [_mtlComputePipelineState retain];
|
return [_mtlComputePipelineState retain];
|
||||||
|
@ -62,7 +62,7 @@ MVKMTLFunction MVKShaderLibrary::getMTLFunction(const VkSpecializationInfo* pSpe
|
|||||||
|
|
||||||
if ( !_mtlLibrary ) { return MVKMTLFunctionNull; }
|
if ( !_mtlLibrary ) { return MVKMTLFunctionNull; }
|
||||||
|
|
||||||
@synchronized (_mtlLibrary) {
|
@synchronized (_owner->getMTLDevice()) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
NSString* mtlFuncName = @(_shaderConversionResults.entryPoint.mtlFunctionName.c_str());
|
NSString* mtlFuncName = @(_shaderConversionResults.entryPoint.mtlFunctionName.c_str());
|
||||||
MVKDevice* mvkDev = _owner->getDevice();
|
MVKDevice* mvkDev = _owner->getDevice();
|
||||||
@ -423,13 +423,16 @@ id<MTLLibrary> MVKShaderLibraryCompiler::newMTLLibrary(NSString* mslSourceCode,
|
|||||||
unique_lock<mutex> lock(_completionLock);
|
unique_lock<mutex> lock(_completionLock);
|
||||||
|
|
||||||
compile(lock, ^{
|
compile(lock, ^{
|
||||||
[_owner->getMTLDevice() newLibraryWithSource: mslSourceCode
|
auto mtlDev = _owner->getMTLDevice();
|
||||||
|
@synchronized (mtlDev) {
|
||||||
|
[mtlDev newLibraryWithSource: mslSourceCode
|
||||||
options: _owner->getDevice()->getMTLCompileOptions(shaderConversionResults.entryPoint.supportsFastMath,
|
options: _owner->getDevice()->getMTLCompileOptions(shaderConversionResults.entryPoint.supportsFastMath,
|
||||||
shaderConversionResults.isPositionInvariant)
|
shaderConversionResults.isPositionInvariant)
|
||||||
completionHandler: ^(id<MTLLibrary> mtlLib, NSError* error) {
|
completionHandler: ^(id<MTLLibrary> mtlLib, NSError* error) {
|
||||||
bool isLate = compileComplete(mtlLib, error);
|
bool isLate = compileComplete(mtlLib, error);
|
||||||
if (isLate) { destroy(); }
|
if (isLate) { destroy(); }
|
||||||
}];
|
}];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return [_mtlLibrary retain];
|
return [_mtlLibrary retain];
|
||||||
@ -467,12 +470,14 @@ id<MTLFunction> MVKFunctionSpecializer::newMTLFunction(id<MTLLibrary> mtlLibrary
|
|||||||
unique_lock<mutex> lock(_completionLock);
|
unique_lock<mutex> lock(_completionLock);
|
||||||
|
|
||||||
compile(lock, ^{
|
compile(lock, ^{
|
||||||
|
@synchronized (_owner->getMTLDevice()) {
|
||||||
[mtlLibrary newFunctionWithName: funcName
|
[mtlLibrary newFunctionWithName: funcName
|
||||||
constantValues: constantValues
|
constantValues: constantValues
|
||||||
completionHandler: ^(id<MTLFunction> mtlFunc, NSError* error) {
|
completionHandler: ^(id<MTLFunction> mtlFunc, NSError* error) {
|
||||||
bool isLate = compileComplete(mtlFunc, error);
|
bool isLate = compileComplete(mtlFunc, error);
|
||||||
if (isLate) { destroy(); }
|
if (isLate) { destroy(); }
|
||||||
}];
|
}];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return [_mtlFunction retain];
|
return [_mtlFunction retain];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user