Enable async MTLLibrary and MTLRenderPipelineState creation.

Renables the Programs test on the Metal bots.

Bug: skia:9817
Change-Id: Ie1f0b520e37793e5a45ab85a55fd3cdc5f775977
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/266572
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Jim Van Verth 2020-01-30 16:56:04 -05:00 committed by Skia Commit-Bot
parent fae37b0741
commit b71f023957
5 changed files with 72 additions and 601 deletions

View File

@ -1,531 +0,0 @@
[
{
"cmd": [
"vpython",
"-u",
"RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
"--json-output",
"/path/to/tmp/json",
"ensure-directory",
"--mode",
"0777",
"[START_DIR]/tmp"
],
"infra_step": true,
"name": "makedirs tmp_dir"
},
{
"cmd": [
"vpython",
"-u",
"RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
"--json-output",
"/path/to/tmp/json",
"copy",
"[START_DIR]/skia/infra/bots/assets/skp/VERSION",
"/path/to/tmp/"
],
"infra_step": true,
"name": "Get skp VERSION",
"~followup_annotations": [
"@@@STEP_LOG_LINE@VERSION@42@@@",
"@@@STEP_LOG_END@VERSION@@@"
]
},
{
"cmd": [
"vpython",
"-u",
"RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
"--json-output",
"/path/to/tmp/json",
"copy",
"42",
"[START_DIR]/tmp/SKP_VERSION"
],
"infra_step": true,
"name": "write SKP_VERSION",
"~followup_annotations": [
"@@@STEP_LOG_LINE@SKP_VERSION@42@@@",
"@@@STEP_LOG_END@SKP_VERSION@@@"
]
},
{
"cmd": [
"vpython",
"-u",
"RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
"--json-output",
"/path/to/tmp/json",
"copy",
"[START_DIR]/skia/infra/bots/assets/skimage/VERSION",
"/path/to/tmp/"
],
"infra_step": true,
"name": "Get skimage VERSION",
"~followup_annotations": [
"@@@STEP_LOG_LINE@VERSION@42@@@",
"@@@STEP_LOG_END@VERSION@@@"
]
},
{
"cmd": [
"vpython",
"-u",
"RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
"--json-output",
"/path/to/tmp/json",
"copy",
"42",
"[START_DIR]/tmp/SK_IMAGE_VERSION"
],
"infra_step": true,
"name": "write SK_IMAGE_VERSION",
"~followup_annotations": [
"@@@STEP_LOG_LINE@SK_IMAGE_VERSION@42@@@",
"@@@STEP_LOG_END@SK_IMAGE_VERSION@@@"
]
},
{
"cmd": [
"vpython",
"-u",
"RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
"--json-output",
"/path/to/tmp/json",
"copy",
"[START_DIR]/skia/infra/bots/assets/svg/VERSION",
"/path/to/tmp/"
],
"infra_step": true,
"name": "Get svg VERSION",
"~followup_annotations": [
"@@@STEP_LOG_LINE@VERSION@42@@@",
"@@@STEP_LOG_END@VERSION@@@"
]
},
{
"cmd": [
"vpython",
"-u",
"RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
"--json-output",
"/path/to/tmp/json",
"copy",
"42",
"[START_DIR]/tmp/SVG_VERSION"
],
"infra_step": true,
"name": "write SVG_VERSION",
"~followup_annotations": [
"@@@STEP_LOG_LINE@SVG_VERSION@42@@@",
"@@@STEP_LOG_END@SVG_VERSION@@@"
]
},
{
"cmd": [
"vpython",
"-u",
"RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
"--json-output",
"/path/to/tmp/json",
"rmtree",
"[START_DIR]/test"
],
"infra_step": true,
"name": "rmtree test"
},
{
"cmd": [
"vpython",
"-u",
"RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
"--json-output",
"/path/to/tmp/json",
"ensure-directory",
"--mode",
"0777",
"[START_DIR]/test"
],
"infra_step": true,
"name": "makedirs test"
},
{
"cmd": [
"python",
"-u",
"\nimport contextlib\nimport math\nimport socket\nimport sys\nimport time\nimport urllib2\n\nHASHES_URL = sys.argv[1]\nRETRIES = 5\nTIMEOUT = 60\nWAIT_BASE = 15\n\nsocket.setdefaulttimeout(TIMEOUT)\nfor retry in range(RETRIES):\n try:\n with contextlib.closing(\n urllib2.urlopen(HASHES_URL, timeout=TIMEOUT)) as w:\n hashes = w.read()\n with open(sys.argv[2], 'w') as f:\n f.write(hashes)\n break\n except Exception as e:\n print 'Failed to get uninteresting hashes from %s:' % HASHES_URL\n print e\n if retry == RETRIES:\n raise\n waittime = WAIT_BASE * math.pow(2, retry)\n print 'Retry in %d seconds.' % waittime\n time.sleep(waittime)\n",
"https://example.com/hashes.txt",
"[START_DIR]/tmp/uninteresting_hashes.txt"
],
"env": {
"CHROME_HEADLESS": "1",
"PATH": "<PATH>:RECIPE_REPO[depot_tools]"
},
"infra_step": true,
"name": "get uninteresting hashes",
"~followup_annotations": [
"@@@STEP_LOG_LINE@python.inline@@@@",
"@@@STEP_LOG_LINE@python.inline@import contextlib@@@",
"@@@STEP_LOG_LINE@python.inline@import math@@@",
"@@@STEP_LOG_LINE@python.inline@import socket@@@",
"@@@STEP_LOG_LINE@python.inline@import sys@@@",
"@@@STEP_LOG_LINE@python.inline@import time@@@",
"@@@STEP_LOG_LINE@python.inline@import urllib2@@@",
"@@@STEP_LOG_LINE@python.inline@@@@",
"@@@STEP_LOG_LINE@python.inline@HASHES_URL = sys.argv[1]@@@",
"@@@STEP_LOG_LINE@python.inline@RETRIES = 5@@@",
"@@@STEP_LOG_LINE@python.inline@TIMEOUT = 60@@@",
"@@@STEP_LOG_LINE@python.inline@WAIT_BASE = 15@@@",
"@@@STEP_LOG_LINE@python.inline@@@@",
"@@@STEP_LOG_LINE@python.inline@socket.setdefaulttimeout(TIMEOUT)@@@",
"@@@STEP_LOG_LINE@python.inline@for retry in range(RETRIES):@@@",
"@@@STEP_LOG_LINE@python.inline@ try:@@@",
"@@@STEP_LOG_LINE@python.inline@ with contextlib.closing(@@@",
"@@@STEP_LOG_LINE@python.inline@ urllib2.urlopen(HASHES_URL, timeout=TIMEOUT)) as w:@@@",
"@@@STEP_LOG_LINE@python.inline@ hashes = w.read()@@@",
"@@@STEP_LOG_LINE@python.inline@ with open(sys.argv[2], 'w') as f:@@@",
"@@@STEP_LOG_LINE@python.inline@ f.write(hashes)@@@",
"@@@STEP_LOG_LINE@python.inline@ break@@@",
"@@@STEP_LOG_LINE@python.inline@ except Exception as e:@@@",
"@@@STEP_LOG_LINE@python.inline@ print 'Failed to get uninteresting hashes from %s:' % HASHES_URL@@@",
"@@@STEP_LOG_LINE@python.inline@ print e@@@",
"@@@STEP_LOG_LINE@python.inline@ if retry == RETRIES:@@@",
"@@@STEP_LOG_LINE@python.inline@ raise@@@",
"@@@STEP_LOG_LINE@python.inline@ waittime = WAIT_BASE * math.pow(2, retry)@@@",
"@@@STEP_LOG_LINE@python.inline@ print 'Retry in %d seconds.' % waittime@@@",
"@@@STEP_LOG_LINE@python.inline@ time.sleep(waittime)@@@",
"@@@STEP_LOG_END@python.inline@@@"
]
},
{
"cmd": [
"python",
"-u",
"import os\nprint os.environ.get('SWARMING_BOT_ID', '')\n"
],
"name": "get swarming bot id",
"~followup_annotations": [
"@@@STEP_LOG_LINE@python.inline@import os@@@",
"@@@STEP_LOG_LINE@python.inline@print os.environ.get('SWARMING_BOT_ID', '')@@@",
"@@@STEP_LOG_END@python.inline@@@"
]
},
{
"cmd": [
"python",
"-u",
"import os\nprint os.environ.get('SWARMING_TASK_ID', '')\n"
],
"name": "get swarming task id",
"~followup_annotations": [
"@@@STEP_LOG_LINE@python.inline@import os@@@",
"@@@STEP_LOG_LINE@python.inline@print os.environ.get('SWARMING_TASK_ID', '')@@@",
"@@@STEP_LOG_END@python.inline@@@"
]
},
{
"cmd": [
"[START_DIR]/build/dm",
"--resourcePath",
"[START_DIR]/skia/resources",
"--skps",
"[START_DIR]/skp",
"--images",
"[START_DIR]/skimage/dm",
"--colorImages",
"[START_DIR]/skimage/colorspace",
"--nameByHash",
"--properties",
"gitHash",
"abc123",
"builder",
"Test-Mac10.13-Clang-MacBook10.1-GPU-IntelHD615-x86_64-Release-All-Metal",
"buildbucket_build_id",
"123454321",
"task_id",
"task_12345",
"swarming_bot_id",
"skia-bot-123",
"swarming_task_id",
"123456",
"--svgs",
"[START_DIR]/svg",
"--key",
"arch",
"x86_64",
"compiler",
"Clang",
"configuration",
"Release",
"cpu_or_gpu",
"GPU",
"cpu_or_gpu_value",
"IntelHD615",
"extra_config",
"Metal",
"model",
"MacBook10.1",
"os",
"Mac10.13",
"style",
"default",
"--uninterestingHashesFile",
"[START_DIR]/tmp/uninteresting_hashes.txt",
"--writePath",
"[START_DIR]/[SWARM_OUT_DIR]",
"--randomProcessorTest",
"--nocpu",
"--config",
"mtl",
"--src",
"tests",
"gm",
"image",
"colorImage",
"svg",
"--blacklist",
"_",
"test",
"_",
"Programs",
"_",
"svg",
"_",
"svgparse_",
"_",
"image",
"gen_platf",
"rgba32abf.bmp",
"_",
"image",
"gen_platf",
"rgb24prof.bmp",
"_",
"image",
"gen_platf",
"rgb24lprof.bmp",
"_",
"image",
"gen_platf",
"8bpp-pixeldata-cropped.bmp",
"_",
"image",
"gen_platf",
"4bpp-pixeldata-cropped.bmp",
"_",
"image",
"gen_platf",
"32bpp-pixeldata-cropped.bmp",
"_",
"image",
"gen_platf",
"24bpp-pixeldata-cropped.bmp",
"_",
"image",
"gen_platf",
"frame_larger_than_image.gif",
"_",
"image",
"gen_platf",
"inc0.png",
"_",
"image",
"gen_platf",
"inc1.png",
"_",
"image",
"gen_platf",
"inc2.png",
"_",
"image",
"gen_platf",
"inc3.png",
"_",
"image",
"gen_platf",
"inc4.png",
"_",
"image",
"gen_platf",
"inc5.png",
"_",
"image",
"gen_platf",
"inc6.png",
"_",
"image",
"gen_platf",
"inc7.png",
"_",
"image",
"gen_platf",
"inc8.png",
"_",
"image",
"gen_platf",
"inc9.png",
"_",
"image",
"gen_platf",
"inc10.png",
"_",
"image",
"gen_platf",
"inc11.png",
"_",
"image",
"gen_platf",
"inc12.png",
"_",
"image",
"gen_platf",
"inc13.png",
"_",
"image",
"gen_platf",
"inc14.png",
"_",
"image",
"gen_platf",
"incInterlaced.png",
"_",
"image",
"gen_platf",
"incInterlaced.gif",
"_",
"image",
"gen_platf",
"inc1.gif",
"_",
"image",
"gen_platf",
"inc0.gif",
"_",
"image",
"gen_platf",
"butterfly.gif",
"_",
"image",
"gen_platf",
"testimgari.jpg",
"_",
"image",
"gen_platf",
"rle8-height-negative.bmp",
"_",
"image",
"gen_platf",
"rle4-height-negative.bmp",
"_",
"image",
"gen_platf",
"error",
"_",
"image",
"_",
"interlaced1.png",
"_",
"image",
"_",
"interlaced2.png",
"_",
"image",
"_",
"interlaced3.png",
"_",
"image",
"_",
".arw",
"_",
"image",
"_",
".cr2",
"_",
"image",
"_",
".dng",
"_",
"image",
"_",
".nef",
"_",
"image",
"_",
".nrw",
"_",
"image",
"_",
".orf",
"_",
"image",
"_",
".raf",
"_",
"image",
"_",
".rw2",
"_",
"image",
"_",
".pef",
"_",
"image",
"_",
".srw",
"_",
"image",
"_",
".ARW",
"_",
"image",
"_",
".CR2",
"_",
"image",
"_",
".DNG",
"_",
"image",
"_",
".NEF",
"_",
"image",
"_",
".NRW",
"_",
"image",
"_",
".ORF",
"_",
"image",
"_",
".RAF",
"_",
"image",
"_",
".RW2",
"_",
"image",
"_",
".PEF",
"_",
"image",
"_",
".SRW",
"--match",
"~^SRGBReadWritePixels$",
"~^GrMeshTest$",
"--nonativeFonts",
"--verbose"
],
"env": {
"CHROME_HEADLESS": "1",
"PATH": "<PATH>:RECIPE_REPO[depot_tools]"
},
"name": "dm"
},
{
"name": "$result"
}
]

View File

@ -222,10 +222,6 @@ def dm_flags(api, bot):
# skbug.com/9235
blacklist('_ test _ Programs')
if 'Metal' in bot and 'MacBook10.1-' in bot:
# skbug.com/9817
blacklist('_ test _ Programs')
# skbug.com/9033 - these devices run out of memory on this test
# when opList splitting reduction is enabled
if 'GPU' in bot and ('Nexus7' in bot or
@ -1082,7 +1078,6 @@ TEST_BUILDERS = [
'Test-Win2019-Clang-GCE-CPU-AVX2-x86_64-Debug-All-FSAA',
'Test-iOS-Clang-iPadPro-GPU-PowerVRGT7800-arm64-Release-All',
'Test-Mac10.13-Clang-MacBook10.1-GPU-IntelHD615-x86_64-Debug-All-CommandBuffer',
'Test-Mac10.13-Clang-MacBook10.1-GPU-IntelHD615-x86_64-Release-All-Metal',
'Test-Android-Clang-TecnoSpark3Pro-GPU-PowerVRGE8320-arm-Debug-All-Android',
]

View File

@ -516,29 +516,23 @@ GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(GrRenderTarget* renderTa
SkASSERT(pipelineDescriptor.vertexDescriptor);
SkASSERT(pipelineDescriptor.colorAttachments[0]);
#if defined(SK_BUILD_FOR_MAC) && defined(GR_USE_COMPLETION_HANDLER)
bool timedout;
id<MTLRenderPipelineState> pipelineState = GrMtlNewRenderPipelineStateWithDescriptor(
fGpu->device(), pipelineDescriptor, &timedout);
if (timedout) {
// try a second time
pipelineState = GrMtlNewRenderPipelineStateWithDescriptor(
fGpu->device(), pipelineDescriptor, &timedout);
}
if (!pipelineState) {
return nullptr;
}
#else
NSError* error = nil;
#if defined(SK_BUILD_FOR_MAC)
id<MTLRenderPipelineState> pipelineState = GrMtlNewRenderPipelineStateWithDescriptor(
fGpu->device(), pipelineDescriptor, &error);
#else
id<MTLRenderPipelineState> pipelineState =
[fGpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
error: &error];
#endif
if (error) {
SkDebugf("Error creating pipeline: %s\n",
[[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
return nullptr;
}
#endif
if (!pipelineState) {
return nullptr;
}
uint32_t bufferSize = buffer_size(fUniformHandler.fCurrentUBOOffset,
fUniformHandler.fCurrentUBOMaxAlignment);

View File

@ -80,13 +80,13 @@ id<MTLLibrary> GrCompileMtlShaderLibrary(const GrMtlGpu* gpu,
* Replacement for newLibraryWithSource:options:error that has a timeout.
*/
id<MTLLibrary> GrMtlNewLibraryWithSource(id<MTLDevice>, NSString* mslCode,
MTLCompileOptions*, bool* timedout);
MTLCompileOptions*, NSError**);
/**
* Replacement for newRenderPipelineStateWithDescriptor:error that has a timeout.
*/
id<MTLRenderPipelineState> GrMtlNewRenderPipelineStateWithDescriptor(
id<MTLDevice>, MTLRenderPipelineDescriptor*, bool* timedout);
id<MTLDevice>, MTLRenderPipelineDescriptor*, NSError**);
/**
* Returns a MTLTexture corresponding to the GrSurface.

View File

@ -9,6 +9,7 @@
#include "include/gpu/GrSurface.h"
#include "include/private/GrTypesPriv.h"
#include "include/private/SkMutex.h"
#include "src/gpu/mtl/GrMtlGpu.h"
#include "src/gpu/mtl/GrMtlRenderTarget.h"
#include "src/gpu/mtl/GrMtlTexture.h"
@ -86,87 +87,99 @@ id<MTLLibrary> GrCompileMtlShaderLibrary(const GrMtlGpu* gpu,
#endif
MTLCompileOptions* defaultOptions = [[MTLCompileOptions alloc] init];
#if defined(SK_BUILD_FOR_MAC) && defined(GR_USE_COMPLETION_HANDLER)
bool timedout;
id<MTLLibrary> compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), mtlCode,
defaultOptions, &timedout);
if (timedout) {
// try again
compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), mtlCode,
defaultOptions, &timedout);
}
#else
NSError* error = nil;
#if defined(SK_BUILD_FOR_MAC)
id<MTLLibrary> compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), mtlCode,
defaultOptions, &error);
#else
id<MTLLibrary> compiledLibrary = [gpu->device() newLibraryWithSource: mtlCode
options: defaultOptions
error: &error];
#endif
if (error) {
SkDebugf("Error compiling MSL shader: %s\n%s\n",
shaderString.c_str(),
[[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
return nil;
}
#endif
return compiledLibrary;
}
id<MTLLibrary> GrMtlNewLibraryWithSource(id<MTLDevice> device, NSString* mslCode,
MTLCompileOptions* options, bool* timedout) {
dispatch_semaphore_t compilerSemaphore = dispatch_semaphore_create(0);
// Wrapper to get atomic assignment for compiles and pipeline creation
class MtlCompileResult : public SkRefCnt {
public:
MtlCompileResult() : fCompiledObject(nil), fError(nil) {}
~MtlCompileResult() = default;
void set(id compiledObject, NSError* error) {
SkAutoMutexExclusive automutex(fMutex);
fCompiledObject = compiledObject;
fError = error;
}
std::pair<id, NSError*> get() {
SkAutoMutexExclusive automutex(fMutex);
return std::make_pair(fCompiledObject, fError);
}
private:
SkMutex fMutex;
id fCompiledObject SK_GUARDED_BY(fMutex);
NSError* fError SK_GUARDED_BY(fMutex);
};
id<MTLLibrary> GrMtlNewLibraryWithSource(id<MTLDevice> device, NSString* mslCode,
MTLCompileOptions* options, NSError** error) {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
sk_sp<MtlCompileResult> compileResult(new MtlCompileResult);
// We have to increment the ref for the Obj-C block manually because it won't do it for us
compileResult->ref();
MTLNewLibraryCompletionHandler completionHandler =
^(id<MTLLibrary> library, NSError* error) {
compileResult->set(library, error);
dispatch_semaphore_signal(semaphore);
compileResult->unref();
};
__block dispatch_semaphore_t semaphore = compilerSemaphore;
__block id<MTLLibrary> compiledLibrary;
[device newLibraryWithSource: mslCode
options: options
completionHandler:
^(id<MTLLibrary> library, NSError* error) {
if (error) {
SkDebugf("Error compiling MSL shader: %s\n%s\n",
mslCode,
[[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
}
compiledLibrary = library;
dispatch_semaphore_signal(semaphore);
}
];
completionHandler: completionHandler];
// Wait 100 ms for the compiler
if (dispatch_semaphore_wait(compilerSemaphore, dispatch_time(DISPATCH_TIME_NOW, 100000))) {
// Wait 5 seconds for the compiler
if (dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 5000000UL))) {
SkDebugf("Timeout compiling MSL shader\n");
*timedout = true;
return nil;
}
*timedout = false;
id<MTLLibrary> compiledLibrary;
std::tie(compiledLibrary, *error) = compileResult->get();
return compiledLibrary;
}
id<MTLRenderPipelineState> GrMtlNewRenderPipelineStateWithDescriptor(
id<MTLDevice> device, MTLRenderPipelineDescriptor* pipelineDescriptor, bool* timedout) {
dispatch_semaphore_t pipelineSemaphore = dispatch_semaphore_create(0);
__block dispatch_semaphore_t semaphore = pipelineSemaphore;
__block id<MTLRenderPipelineState> pipelineState;
[device newRenderPipelineStateWithDescriptor: pipelineDescriptor
completionHandler:
id<MTLDevice> device, MTLRenderPipelineDescriptor* pipelineDescriptor, NSError** error) {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
sk_sp<MtlCompileResult> compileResult(new MtlCompileResult);
// We have to increment the ref for the Obj-C block manually because it won't do it for us
compileResult->ref();
MTLNewRenderPipelineStateCompletionHandler completionHandler =
^(id<MTLRenderPipelineState> state, NSError* error) {
if (error) {
SkDebugf("Error creating pipeline: %s\n",
[[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
}
pipelineState = state;
compileResult->set(state, error);
dispatch_semaphore_signal(semaphore);
}
];
compileResult->unref();
};
// Wait 500 ms for pipeline creation
if (dispatch_semaphore_wait(pipelineSemaphore, dispatch_time(DISPATCH_TIME_NOW, 500000))) {
[device newRenderPipelineStateWithDescriptor: pipelineDescriptor
completionHandler: completionHandler];
// Wait 5 seconds for pipeline creation
if (dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 5000000UL))) {
SkDebugf("Timeout creating pipeline.\n");
*timedout = true;
return nil;
}
*timedout = false;
id<MTLRenderPipelineState> pipelineState;
std::tie(pipelineState, *error) = compileResult->get();
return pipelineState;
}