Пример #1
0
def run_glslang_glsl_shader_to_spirv_shader(
    glsl_shader_path: pathlib.Path,
    output_dir_path: pathlib.Path,
    glslang_validator_file_path: Optional[pathlib.Path] = None,
    time_limit: int = GLSLANG_DEFAULT_TIME_LIMIT,
) -> pathlib.Path:

    if not glslang_validator_file_path:
        glslang_validator_file_path = util.tool_on_path(
            binaries_util.GLSLANG_VALIDATOR_NAME
        )

    output_spirv_file_path = output_dir_path / (glsl_shader_path.name + ".spv")

    util.file_mkdirs_parent(output_spirv_file_path)

    subprocess_util.run(
        util.prepend_catchsegv_if_available(
            [
                str(glslang_validator_file_path),
                "-V",
                "-o",
                str(output_spirv_file_path),
                str(glsl_shader_path),
            ]
        ),
        timeout=time_limit,
    )

    return output_spirv_file_path
Пример #2
0
def run_spirv_opt_on_spirv_shader(
    input_spirv_file_path: pathlib.Path,
    output_dir_path: pathlib.Path,
    spirv_opt_args: List[str],
    spirv_opt_file_path: Optional[pathlib.Path] = None,
    spirv_opt_no_validate_after_all: bool = False,
    time_limit: int = SPIRV_OPT_DEFAULT_TIME_LIMIT,
) -> pathlib.Path:

    if not spirv_opt_file_path:
        spirv_opt_file_path = util.tool_on_path(binaries_util.SPIRV_OPT_NAME)

    output_spirv_file_path = output_dir_path / input_spirv_file_path.name

    util.file_mkdirs_parent(output_spirv_file_path)

    cmd = [
        str(spirv_opt_file_path),
        str(input_spirv_file_path),
        "-o",
        str(output_spirv_file_path),
    ]

    if not spirv_opt_no_validate_after_all:
        cmd.append("--validate-after-all")

    cmd += spirv_opt_args

    cmd = util.prepend_catchsegv_if_available(cmd)

    subprocess_util.run(cmd, timeout=time_limit)

    return output_spirv_file_path
Пример #3
0
def run_spirv_val_on_shader(
    shader_path: Path, spirv_val_path: Path, extra_args: Optional[List[str]] = None,
) -> None:
    cmd = util.prepend_catchsegv_if_available([str(spirv_val_path), str(shader_path)])
    if extra_args:
        cmd.extend(extra_args)

    subprocess_util.run(cmd)
def run_shader(
    shader_compiler_device: DeviceShaderCompiler,
    shader_path: Path,
    output_dir: Path,
    compiler_path: Path,
    timeout: int = DEFAULT_TIMEOUT,
) -> Path:
    output_file_path = output_dir / (shader_path.name + ".out")

    cmd = [str(compiler_path)]
    cmd += list(shader_compiler_device.args)
    cmd += [str(shader_path), "-o", str(output_file_path)]
    cmd = util.prepend_catchsegv_if_available(cmd)
    subprocess_util.run(cmd, verbose=True, timeout=timeout)
    return output_file_path
Пример #5
0
def run_spirv_dis_on_spirv_shader(
    input_spirv_file_path: pathlib.Path,
    output_dir_path: pathlib.Path,
    spirv_dis_file_path: Optional[pathlib.Path] = None,
) -> pathlib.Path:
    if not spirv_dis_file_path:
        spirv_dis_file_path = util.tool_on_path(binaries_util.SPIRV_DIS_NAME)

    output_spirv_file_path = output_dir_path / (
        util.remove_end(input_spirv_file_path.name, ".spv") + ".asm")

    util.file_mkdirs_parent(output_spirv_file_path)

    subprocess_util.run(
        util.prepend_catchsegv_if_available([
            str(spirv_dis_file_path),
            str(input_spirv_file_path),
            "-o",
            str(output_spirv_file_path),
            "--raw-id",
        ]))

    return output_spirv_file_path
def run_glslang_glsl_shader_to_spirv_shader(
    glsl_shader_path: pathlib.Path,
    output_dir_path: pathlib.Path,
    glslang_validator_file_path: Optional[pathlib.Path] = None,
    time_limit: int = GLSLANG_DEFAULT_TIME_LIMIT,
    preprocessor_cache: Optional[util.CommandCache] = None,
) -> pathlib.Path:

    if not glslang_validator_file_path:
        glslang_validator_file_path = util.tool_on_path(
            binaries_util.GLSLANG_VALIDATOR_NAME)

    output_spirv_file_path = output_dir_path / (glsl_shader_path.name + ".spv")

    util.file_mkdirs_parent(output_spirv_file_path)

    cmd = util.HashedCommand()
    cmd.append_program_path(glslang_validator_file_path)
    cmd.append_str("-V")
    cmd.append_str("-o")
    cmd.append_output_file(output_spirv_file_path)
    cmd.append_input_file(glsl_shader_path)

    if preprocessor_cache and preprocessor_cache.write_cached_output_file(
            cmd, output_spirv_file_path):
        return output_spirv_file_path

    cmd_str = util.prepend_catchsegv_if_available(cmd.cmd)
    subprocess_util.run(
        cmd_str,
        timeout=time_limit,
    )

    if preprocessor_cache:
        preprocessor_cache.add_output_to_cache(cmd, output_spirv_file_path)

    return output_spirv_file_path
Пример #7
0
def run_spirv_opt_on_spirv_shader(
    input_spirv_file_path: pathlib.Path,
    output_dir_path: pathlib.Path,
    spirv_opt_args: List[str],
    spirv_opt_file_path: Optional[pathlib.Path] = None,
    spirv_opt_no_validate_after_all: bool = False,
    time_limit: int = SPIRV_OPT_DEFAULT_TIME_LIMIT,
    preprocessor_cache: Optional[util.CommandCache] = None,
) -> pathlib.Path:

    if not spirv_opt_file_path:
        spirv_opt_file_path = util.tool_on_path(binaries_util.SPIRV_OPT_NAME)

    output_spirv_file_path = output_dir_path / input_spirv_file_path.name

    util.file_mkdirs_parent(output_spirv_file_path)

    cmd = util.HashedCommand()
    cmd.append_program_path(spirv_opt_file_path)
    cmd.append_input_file(input_spirv_file_path)
    cmd.append_str("-o")
    cmd.append_output_file(output_spirv_file_path)
    if not spirv_opt_no_validate_after_all:
        cmd.append_str("--validate-after-all")
    cmd.extend_str(spirv_opt_args)

    if preprocessor_cache and preprocessor_cache.write_cached_output_file(
            cmd, output_spirv_file_path):
        return output_spirv_file_path

    cmd_str = util.prepend_catchsegv_if_available(cmd.cmd)
    subprocess_util.run(cmd_str, timeout=time_limit)

    if preprocessor_cache:
        preprocessor_cache.add_output_to_cache(cmd, output_spirv_file_path)

    return output_spirv_file_path
Пример #8
0
def main_helper(  # pylint: disable=too-many-locals, too-many-branches, too-many-statements;
    settings_path: Path,
    iteration_seed_override: Optional[int] = None,
    fuzzing_tool_pattern: Optional[List[FuzzingTool]] = None,
    allow_no_stack_traces: bool = False,
    override_sigint: bool = True,
    use_amber_vulkan_loader: bool = False,
    active_device_names: Optional[List[str]] = None,
    update_ignored_crash_signatures_gerrit_cookie: Optional[str] = None,
) -> None:

    if not fuzzing_tool_pattern:
        fuzzing_tool_pattern = [FuzzingTool.GLSL_FUZZ]

    util.update_gcov_environment_variable_if_needed()

    if override_sigint:
        interrupt_util.override_sigint()

    try_get_root_file()

    settings = settings_util.read_or_create(settings_path)

    binary_manager = binaries_util.get_default_binary_manager(
        settings=settings)

    temp_dir = Path() / "temp"

    # Note: we use "is not None" so that if the user passes an empty Gerrit cookie, we still try to execute this code.
    if update_ignored_crash_signatures_gerrit_cookie is not None:
        git_tool = util.tool_on_path("git")
        downloaded_graphicsfuzz_tests_dir = (
            temp_dir / f"graphicsfuzz_cts_tests_{get_random_name()[:8]}")
        work_dir = temp_dir / f"graphicsfuzz_cts_run_{get_random_name()[:8]}"
        download_cts_gf_tests.download_cts_graphicsfuzz_tests(
            git_tool=git_tool,
            cookie=update_ignored_crash_signatures_gerrit_cookie,
            output_tests_dir=downloaded_graphicsfuzz_tests_dir,
        )
        download_cts_gf_tests.extract_shaders(
            tests_dir=downloaded_graphicsfuzz_tests_dir,
            binaries=binary_manager)
        with util.file_open_text(work_dir / "results.csv",
                                 "w") as results_out_handle:
            run_cts_gf_tests.main_helper(
                tests_dir=downloaded_graphicsfuzz_tests_dir,
                work_dir=work_dir,
                binaries=binary_manager,
                settings=settings,
                active_devices=devices_util.get_active_devices(
                    settings.device_list),
                results_out_handle=results_out_handle,
                updated_settings_output_path=settings_path,
            )
        return

    active_devices = devices_util.get_active_devices(
        settings.device_list, active_device_names=active_device_names)

    # Add host_preprocessor device from device list if it is missing.
    if not active_devices[0].HasField("preprocess"):
        for device in settings.device_list.devices:
            if device.HasField("preprocess"):
                active_devices.insert(0, device)
                break

    # Add host_preprocessor device (from scratch) if it is still missing.
    if not active_devices[0].HasField("preprocess"):
        active_devices.insert(
            0, Device(name="host_preprocessor", preprocess=DevicePreprocess()))

    reports_dir = Path() / "reports"
    fuzz_failures_dir = reports_dir / FUZZ_FAILURES_DIR_NAME
    references_dir = Path() / REFERENCES_DIR
    donors_dir = Path() / DONORS_DIR
    spirv_fuzz_shaders_dir = Path() / "spirv_fuzz_shaders"

    # Log a warning if there is no tool on the PATH for printing stack traces.
    prepended = util.prepend_catchsegv_if_available([], log_warning=True)
    if not allow_no_stack_traces and not prepended:
        raise AssertionError("Stopping because we cannot get stack traces.")

    spirv_fuzz_shaders: List[Path] = []
    references: List[Path] = []

    if FuzzingTool.SPIRV_FUZZ in fuzzing_tool_pattern:
        check_dir_exists(spirv_fuzz_shaders_dir)
        spirv_fuzz_shaders = sorted(spirv_fuzz_shaders_dir.rglob("*.json"))

    if FuzzingTool.GLSL_FUZZ in fuzzing_tool_pattern:
        check_dir_exists(references_dir)
        check_dir_exists(donors_dir)
        # TODO: make GraphicsFuzz find donors recursively.
        references = sorted(references_dir.rglob("*.json"))
        # Filter to only include .json files that have at least one shader (.frag, .vert, .comp) file.
        references = [
            ref for ref in references if shader_job_util.get_related_files(ref)
        ]

    if use_amber_vulkan_loader:
        library_path = binary_manager.get_binary_path_by_name(
            binaries_util.AMBER_VULKAN_LOADER_NAME).path.parent
        util.add_library_paths_to_environ([library_path], os.environ)

    fuzzing_tool_index = 0

    while True:

        interrupt_util.interrupt_if_needed()

        # We have to use "is not None" because the seed could be 0.
        if iteration_seed_override is not None:
            iteration_seed = iteration_seed_override
        else:
            iteration_seed = secrets.randbits(ITERATION_SEED_BITS)

        log(f"Iteration seed: {iteration_seed}")
        random.seed(iteration_seed)

        staging_name = get_random_name()[:8]
        staging_dir = temp_dir / staging_name

        try:
            util.mkdir_p_new(staging_dir)
        except FileExistsError:
            if iteration_seed_override is not None:
                raise
            log(f"Staging directory already exists: {str(staging_dir)}")
            log("Starting new iteration.")
            continue

        # Pseudocode:
        #  - Create test_dir(s) in staging directory.
        #  - Run test_dir(s) on all active devices (stop early if appropriate).
        #  - For each test failure on each device, copy the test to reports_dir, adding the device and crash signature.
        #  - Reduce each report (on the given device).
        #  - Produce a summary for each report.

        fuzzing_tool = fuzzing_tool_pattern[fuzzing_tool_index]
        fuzzing_tool_index = (fuzzing_tool_index +
                              1) % len(fuzzing_tool_pattern)

        if fuzzing_tool == FuzzingTool.SPIRV_FUZZ:
            fuzz_spirv_test.fuzz_spirv(
                staging_dir,
                reports_dir,
                fuzz_failures_dir,
                active_devices,
                spirv_fuzz_shaders,
                settings,
                binary_manager,
            )
        elif fuzzing_tool == FuzzingTool.GLSL_FUZZ:
            fuzz_glsl_test.fuzz_glsl(
                staging_dir,
                reports_dir,
                fuzz_failures_dir,
                active_devices,
                references,
                donors_dir,
                settings,
                binary_manager,
            )
        else:
            raise AssertionError(f"Unknown fuzzing tool: {fuzzing_tool}")

        if iteration_seed_override is not None:
            log("Stopping due to iteration_seed")
            break
        shutil.rmtree(staging_dir)
Пример #9
0
def run_amber_helper(
    amber_script_file: Path,
    output_dir: Path,
    dump_image: bool,
    dump_buffer: bool,
    amber_path: Path,
    skip_render: bool = False,
    debug_layers: bool = False,
    icd: Optional[Path] = None,
) -> Path:

    variant_image_file = output_dir / fuzz.VARIANT_IMAGE_FILE_NAME
    reference_image_file = output_dir / fuzz.REFERENCE_IMAGE_FILE_NAME
    buffer_file = output_dir / fuzz.BUFFER_FILE_NAME

    cmd = [
        str(amber_path),
        str(amber_script_file),
        "--log-graphics-calls-time",
        "--disable-spirv-val",
    ]

    if not debug_layers:
        cmd.append("-d")

    if skip_render:
        # -ps tells amber to stop after pipeline creation
        cmd.append("-ps")
    else:
        if dump_image:
            cmd.append("-I")
            cmd.append("variant_framebuffer")
            cmd.append("-i")
            cmd.append(str(variant_image_file))
            cmd.append("-I")
            cmd.append("reference_framebuffer")
            cmd.append("-i")
            cmd.append(str(reference_image_file))
        if dump_buffer:
            cmd.append("-b")
            cmd.append(str(buffer_file))
            cmd.append("-B")
            cmd.append("0")

    cmd = util.prepend_catchsegv_if_available(cmd)

    status = "UNEXPECTED_ERROR"

    result: Optional[types.CompletedProcess] = None
    env: Optional[Dict[str, str]] = None

    if icd:
        env = {"VK_ICD_FILENAMES": str(icd)}

    try:
        result = subprocess_util.run(
            cmd,
            check_exit_code=False,
            timeout=fuzz.AMBER_RUN_TIME_LIMIT,
            verbose=True,
            env=env,
        )
    except subprocess.TimeoutExpired:
        status = fuzz.STATUS_TIMEOUT

    if result:
        if result.returncode != 0:
            status = fuzz.STATUS_CRASH
        else:
            status = fuzz.STATUS_SUCCESS

    log("\nSTATUS " + status + "\n")

    util.file_write_text(result_util.get_status_path(output_dir), status)

    return output_dir
Пример #10
0
def run_spirv_val_on_shader(shader_path: Path, spirv_val_path: Path) -> None:
    subprocess_util.run(
        util.prepend_catchsegv_if_available(
            [str(spirv_val_path), str(shader_path)]))
Пример #11
0
def main_helper(  # pylint: disable=too-many-locals, too-many-branches, too-many-statements;
    settings_path: Path,
    iteration_seed_override: Optional[int],
    use_spirv_fuzz: bool,
    force_no_stack_traces: bool,
) -> None:

    util.update_gcov_environment_variable_if_needed()

    try:
        artifact_util.artifact_path_get_root()
    except FileNotFoundError:
        log(
            "Could not find ROOT file (in the current directory or above) to mark where binaries should be stored. "
            "Creating a ROOT file in the current directory."
        )
        util.file_write_text(Path(artifact_util.ARTIFACT_ROOT_FILE_NAME), "")

    settings = settings_util.read_or_create(settings_path)

    active_devices = devices_util.get_active_devices(settings.device_list)

    reports_dir = Path() / "reports"
    fuzz_failures_dir = reports_dir / FUZZ_FAILURES_DIR_NAME
    temp_dir = Path() / "temp"
    references_dir = Path() / "references"
    donors_dir = Path() / "donors"
    spirv_fuzz_shaders_dir = Path() / "spirv_fuzz_shaders"

    # Log a warning if there is no tool on the PATH for printing stack traces.
    prepended = util.prepend_catchsegv_if_available([], log_warning=True)
    if not force_no_stack_traces and not prepended:
        raise AssertionError("Stopping because we cannot get stack traces.")

    spirv_fuzz_shaders: List[Path] = []
    references: List[Path] = []

    if use_spirv_fuzz:
        check_dir_exists(spirv_fuzz_shaders_dir)
        spirv_fuzz_shaders = sorted(spirv_fuzz_shaders_dir.rglob("*.json"))
    else:
        check_dir_exists(references_dir)
        check_dir_exists(donors_dir)
        # TODO: make GraphicsFuzz find donors recursively.
        references = sorted(references_dir.rglob("*.json"))
        # Filter to only include .json files that have at least one shader (.frag, .vert, .comp) file.
        references = [
            ref for ref in references if shader_job_util.get_related_files(ref)
        ]

    binary_manager = binaries_util.get_default_binary_manager(
        settings=settings
    ).get_child_binary_manager(list(settings.custom_binaries), prepend=True)

    while True:

        # We have to use "is not None" because the seed could be 0.
        if iteration_seed_override is not None:
            iteration_seed = iteration_seed_override
        else:
            iteration_seed = secrets.randbits(ITERATION_SEED_BITS)

        log(f"Iteration seed: {iteration_seed}")
        random.seed(iteration_seed)

        staging_name = get_random_name()[:8]
        staging_dir = temp_dir / staging_name

        try:
            util.mkdir_p_new(staging_dir)
        except FileExistsError:
            if iteration_seed_override is not None:
                raise
            log(f"Staging directory already exists: {str(staging_dir)}")
            log(f"Starting new iteration.")
            continue

        # Pseudocode:
        #  - Create test_dir(s) in staging directory.
        #  - Run test_dir(s) on all active devices (stop early if appropriate).
        #  - For each test failure on each device, copy the test to reports_dir, adding the device and crash signature.
        #  - Reduce each report (on the given device).
        #  - Produce a summary for each report.

        if use_spirv_fuzz:
            fuzz_spirv_test.fuzz_spirv(
                staging_dir,
                reports_dir,
                fuzz_failures_dir,
                active_devices,
                spirv_fuzz_shaders,
                settings,
                binary_manager,
            )
        else:
            fuzz_glsl_test.fuzz_glsl(
                staging_dir,
                reports_dir,
                fuzz_failures_dir,
                active_devices,
                references,
                donors_dir,
                settings,
                binary_manager,
            )

        shutil.rmtree(staging_dir)

        if iteration_seed_override is not None:
            log("Stopping due to iteration_seed")
            break