Example #1
0
def run_spirv_opt_on_spirv_shader_job(
    input_spirv_shader_job_json_file_path: pathlib.Path,
    output_spirv_shader_job_json_file_path: pathlib.Path,
    spirv_opt_args: List[str],
    spirv_opt_file_path: Optional[pathlib.Path] = None,
    spirv_opt_no_validate_after_all: bool = False,
    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)

    shader_files = shader_job_util.get_related_files(
        input_spirv_shader_job_json_file_path,
        language_suffix=[shader_job_util.SUFFIX_SPIRV],
    )

    util.copy_file(input_spirv_shader_job_json_file_path,
                   output_spirv_shader_job_json_file_path)

    for shader_file in shader_files:
        run_spirv_opt_on_spirv_shader(
            shader_file,
            output_spirv_shader_job_json_file_path.parent,
            spirv_opt_args,
            spirv_opt_file_path,
            spirv_opt_no_validate_after_all,
            preprocessor_cache=preprocessor_cache,
        )

    return output_spirv_shader_job_json_file_path
Example #2
0
def run_glslang_glsl_to_spirv_job(
    glsl_shader_job_json_file_path: pathlib.Path,
    spirv_shader_job_json_file_path: pathlib.Path,
    glslang_validator_file_path: Optional[pathlib.Path] = None,
) -> pathlib.Path:

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

    glsl_shader_files = shader_job_util.get_related_files(
        glsl_shader_job_json_file_path
    )

    util.copy_file(glsl_shader_job_json_file_path, spirv_shader_job_json_file_path)

    for glsl_shader_file in glsl_shader_files:
        run_glslang_glsl_shader_to_spirv_shader(
            glsl_shader_file,
            spirv_shader_job_json_file_path.parent,
            glslang_validator_file_path,
        )

    return spirv_shader_job_json_file_path
Example #3
0
def run_generate(
    spirv_fuzz_path: Path,
    reference_shader_spv: Path,
    output_shader_spv: Path,
    donors_list_path: Path,
    seed: Optional[str] = None,
    other_args: Optional[List[str]] = None,
) -> Path:

    util.check(
        output_shader_spv.suffix == shader_job_util.SUFFIX_SPIRV,
        AssertionError(f"Expected {str(output_shader_spv)} to end with .spv"),
    )

    util.file_mkdirs_parent(output_shader_spv)
    cmd = [
        str(spirv_fuzz_path),
        str(reference_shader_spv),
        "-o",
        str(output_shader_spv),
        f"--donors={str(donors_list_path)}",
        "--fuzzer-pass-validation",
    ]

    if seed:
        cmd.append(f"--seed={seed}")

    if other_args:
        cmd.extend(other_args)

    subprocess_util.run(cmd)

    # reference.spv -> output.spv_orig

    util.copy_file(
        reference_shader_spv,
        output_shader_spv.with_suffix(shader_job_util.SUFFIX_SPIRV_ORIG),
    )

    # reference.spv.facts -> output.spv.facts

    source_facts_path = reference_shader_spv.with_suffix(
        shader_job_util.SUFFIX_FACTS)
    dest_facts_path = output_shader_spv.with_suffix(
        shader_job_util.SUFFIX_FACTS)

    if source_facts_path.exists():
        util.copy_file(source_facts_path, dest_facts_path)

    return output_shader_spv
Example #4
0
def run_replay(
    spirv_fuzz_path: Path,
    variant_shader_spv: Path,
    output_shader_spv: Path,
    other_args: Optional[List[str]] = None,
) -> Path:
    """Replays all transformations except the last to get a similar variant shader."""
    util.check(
        output_shader_spv.suffix == shader_job_util.SUFFIX_SPIRV,
        AssertionError(f"Expected {str(output_shader_spv)} to end with .spv"),
    )

    util.file_mkdirs_parent(output_shader_spv)

    # Copy shader.<STAGE>.facts.
    if variant_shader_spv.with_suffix(shader_job_util.SUFFIX_FACTS).is_file():
        util.copy_file(
            variant_shader_spv.with_suffix(shader_job_util.SUFFIX_FACTS),
            output_shader_spv.with_suffix(shader_job_util.SUFFIX_FACTS),
        )

    # Copy shader.<STAGE>.spv_orig.
    orig_spv = util.copy_file(
        variant_shader_spv.with_suffix(shader_job_util.SUFFIX_SPIRV_ORIG),
        output_shader_spv.with_suffix(shader_job_util.SUFFIX_SPIRV_ORIG),
    )

    transformations = variant_shader_spv.with_suffix(
        shader_job_util.SUFFIX_TRANSFORMATIONS)

    cmd = [
        str(spirv_fuzz_path),
        str(orig_spv),
        "-o",
        str(output_shader_spv),
        f"--replay={str(transformations)}",
        "--replay-range=-1",  # replays all transformations except the last
    ]

    if other_args:
        cmd.extend(other_args)

    subprocess_util.run(cmd)

    return output_shader_spv
Example #5
0
def copy(
    shader_job_file_path: pathlib.Path,
    output_shader_job_file_path: pathlib.Path,
    extensions: Union[Tuple[str, ...], List[str]] = EXT_ALL,
    language_suffix: Union[Tuple[str, ...], List[str]] = (SUFFIX_GLSL, ),
) -> pathlib.Path:

    util.copy_file(shader_job_file_path, output_shader_job_file_path)

    suffixes_that_exist = get_related_suffixes_that_exist(
        shader_job_file_path, extensions, language_suffix)

    for suffix in suffixes_that_exist:
        util.copy_file(
            shader_job_file_path.with_suffix(suffix),
            output_shader_job_file_path.with_suffix(suffix),
        )

    return output_shader_job_file_path
Example #6
0
def run_generate_on_shader_job(
    spirv_fuzz_path: Path,
    reference_shader_json: Path,
    output_shader_json: Path,
    donor_shader_job_paths: Optional[List[Path]] = None,
    seed: Optional[str] = None,
    other_args: Optional[List[str]] = None,
) -> Path:

    if donor_shader_job_paths is None:
        donor_shader_job_paths = []

    util.copy_file(reference_shader_json, output_shader_json)

    suffixes_that_exist = shader_job_util.get_related_suffixes_that_exist(
        reference_shader_json, shader_job_util.EXT_ALL,
        [shader_job_util.SUFFIX_SPIRV])

    for suffix in suffixes_that_exist:

        # Create a donors list file "donors.{suffix}.txt" containing the file paths to all relevant donor .spv shaders.
        donor_list_contents = ""
        for donor_shader_job_path in donor_shader_job_paths:
            donor_shader_path = donor_shader_job_path.with_suffix(suffix)
            if donor_shader_path.exists():
                donor_list_contents += f"{str(donor_shader_path)}\n"
        donors_list_path = util.file_write_text(
            reference_shader_json.parent / f"donors{suffix}.txt",
            donor_list_contents)

        run_generate(
            spirv_fuzz_path,
            reference_shader_json.with_suffix(suffix),
            output_shader_json.with_suffix(suffix),
            donors_list_path=donors_list_path,
            seed=seed,
            other_args=other_args,
        )

    return output_shader_json
Example #7
0
def run_spirv_shader_job_to_spirv_asm_shader_job(
    input_spirv_job_json_file_path: pathlib.Path,
    output_spirv_job_json_file_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)

    shader_files = shader_job_util.get_related_files(
        input_spirv_job_json_file_path,
        language_suffix=[shader_job_util.SUFFIX_SPIRV])

    util.copy_file(input_spirv_job_json_file_path,
                   output_spirv_job_json_file_path)

    for shader_file in shader_files:
        run_spirv_dis_on_spirv_shader(shader_file,
                                      output_spirv_job_json_file_path.parent,
                                      spirv_dis_file_path)

    return output_spirv_job_json_file_path
Example #8
0
def run_replay_on_shader_job(
    spirv_fuzz_path: Path,
    variant_shader_job_json: Path,
    output_shader_job_json: Path,
    other_args: Optional[List[str]] = None,
) -> Path:
    """Replays all transformations except the last on all shaders to get a similar variant shader job."""
    util.copy_file(variant_shader_job_json, output_shader_job_json)

    suffixes_that_exist = shader_job_util.get_related_suffixes_that_exist(
        variant_shader_job_json, shader_job_util.EXT_ALL,
        [shader_job_util.SUFFIX_SPIRV])

    for suffix in suffixes_that_exist:

        run_replay(
            spirv_fuzz_path,
            variant_shader_job_json.with_suffix(suffix),
            output_shader_job_json.with_suffix(suffix),
            other_args=other_args,
        )

    return output_shader_job_json
Example #9
0
def run_generate_on_shader_job(
    spirv_fuzz_path: Path,
    reference_shader_json: Path,
    output_shader_json: Path,
    seed: Optional[str] = None,
    other_args: Optional[List[str]] = None,
) -> Path:

    util.copy_file(reference_shader_json, output_shader_json)

    suffixes_that_exist = shader_job_util.get_related_suffixes_that_exist(
        reference_shader_json, shader_job_util.EXT_ALL,
        [shader_job_util.SUFFIX_SPIRV])

    for suffix in suffixes_that_exist:
        run_generate(
            spirv_fuzz_path,
            reference_shader_json.with_suffix(suffix),
            output_shader_json.with_suffix(suffix),
            seed,
            other_args,
        )

    return output_shader_json
Example #10
0
def run_reduction_part(
    reduction_part_output_dir: Path,
    source_dir_to_reduce: Path,
    shader_job_name_to_reduce: str,
    extension_to_reduce: str,
    preserve_semantics: bool,
    binary_manager: binaries_util.BinaryManager,
    settings: Settings,
) -> Path:
    test = test_util.metadata_read_from_source_dir(source_dir_to_reduce)

    check(
        bool(test.device and test.device.name),
        AssertionError(
            f"Cannot reduce {str(source_dir_to_reduce)}; device must be specified"
        ),
    )

    check(
        bool(test.crash_signature),
        AssertionError(
            f"Cannot reduce {str(source_dir_to_reduce)} because there is no crash string specified."
        ),
    )

    output_dir = test_util.get_reduction_work_directory(
        reduction_part_output_dir, shader_job_name_to_reduce)

    final_shader_path = run_spirv_reduce_or_shrink(
        source_dir=source_dir_to_reduce,
        name_of_shader_job_to_reduce=shader_job_name_to_reduce,
        extension_to_reduce=extension_to_reduce,
        output_dir=output_dir,
        preserve_semantics=preserve_semantics,
        binary_manager=binary_manager,
        settings=settings,
    )

    check(
        final_shader_path.exists(),
        fuzz_glsl_test.ReductionFailedError("Reduction failed.", output_dir),
    )

    # Finally, create the source_dir so the returned directory can be used as a test_dir.

    # Copy the original source directory.
    util.copy_dir(source_dir_to_reduce,
                  test_util.get_source_dir(reduction_part_output_dir))

    # And then replace the shader.

    # Destination file. E.g. reductions/source/variant/shader.frag.spv
    output_shader_prefix = (
        test_util.get_source_dir(reduction_part_output_dir) /
        shader_job_name_to_reduce /
        test_util.SHADER_JOB).with_suffix(extension_to_reduce +
                                          shader_job_util.SUFFIX_SPIRV)

    util.copy_file(
        final_shader_path.with_suffix(shader_job_util.SUFFIX_SPIRV),
        output_shader_prefix.with_suffix(shader_job_util.SUFFIX_SPIRV),
    )

    if preserve_semantics:
        util.copy_file(
            final_shader_path.with_suffix(
                shader_job_util.SUFFIX_TRANSFORMATIONS),
            output_shader_prefix.with_suffix(
                shader_job_util.SUFFIX_TRANSFORMATIONS),
        )

        util.copy_file(
            final_shader_path.with_suffix(
                shader_job_util.SUFFIX_TRANSFORMATIONS_JSON),
            output_shader_prefix.with_suffix(
                shader_job_util.SUFFIX_TRANSFORMATIONS_JSON),
        )

    return test_util.get_source_dir(reduction_part_output_dir)
Example #11
0
def run_reduction(
    test_dir_reduction_output: Path,
    test_dir_to_reduce: Path,
    shader_job_name_to_reduce: str,
    extension_to_reduce: str,
    preserve_semantics: bool,
    binary_manager: binaries_util.BinaryManager,
    reduction_name: str = "reduction1",
) -> Path:
    test = test_util.metadata_read(test_dir_to_reduce)

    check(
        bool(test.device and test.device.name),
        AssertionError(
            f"Cannot reduce {str(test_dir_to_reduce)}; "
            f"device must be specified in {str(test_util.get_metadata_path(test_dir_to_reduce))}"
        ),
    )

    check(
        bool(test.crash_signature),
        AssertionError(
            f"Cannot reduce {str(test_dir_to_reduce)} because there is no crash string specified."
        ),
    )

    # E.g. reports/crashes/no_signature/d50c96e8_opt_rand2_test_phone_ABC/results/phone_ABC/reductions/1
    # Will contain work/ and source/
    reduced_test_dir = test_util.get_reduced_test_dir(
        test_dir_reduction_output, test.device.name, reduction_name)

    source_dir = test_util.get_source_dir(test_dir_to_reduce)
    output_dir = test_util.get_reduction_work_directory(
        reduced_test_dir, shader_job_name_to_reduce)
    if preserve_semantics:
        final_shader_path = run_spirv_reduce_or_shrink(
            source_dir=source_dir,
            name_of_shader_job_to_reduce=shader_job_name_to_reduce,
            extension_to_reduce=extension_to_reduce,
            output_dir=output_dir,
            preserve_semantics=preserve_semantics,
            binary_manager=binary_manager,
        )
    else:
        final_shader_path = run_spirv_reduce_or_shrink(
            source_dir=source_dir,
            name_of_shader_job_to_reduce=shader_job_name_to_reduce,
            extension_to_reduce=extension_to_reduce,
            output_dir=output_dir,
            preserve_semantics=preserve_semantics,
            binary_manager=binary_manager,
        )

    check(
        final_shader_path.exists(),
        ReductionFailedError("Reduction failed.", reduction_name, output_dir),
    )

    # Finally, create the source_dir so the returned directory can be used as a test_dir.

    # Copy the original source directory.
    util.copy_dir(source_dir, test_util.get_source_dir(reduced_test_dir))

    # And then replace the shader.

    # Destination file. E.g. reductions/source/variant/shader.frag.spv
    output_shader_prefix = (
        test_util.get_source_dir(reduced_test_dir) /
        shader_job_name_to_reduce /
        test_util.SHADER_JOB).with_suffix(extension_to_reduce +
                                          shader_job_util.SUFFIX_SPIRV)

    util.copy_file(
        final_shader_path.with_suffix(shader_job_util.SUFFIX_SPIRV),
        output_shader_prefix.with_suffix(shader_job_util.SUFFIX_SPIRV),
    )

    if preserve_semantics:
        util.copy_file(
            final_shader_path.with_suffix(
                shader_job_util.SUFFIX_TRANSFORMATIONS),
            output_shader_prefix.with_suffix(
                shader_job_util.SUFFIX_TRANSFORMATIONS),
        )

        util.copy_file(
            final_shader_path.with_suffix(
                shader_job_util.SUFFIX_TRANSFORMATIONS_JSON),
            output_shader_prefix.with_suffix(
                shader_job_util.SUFFIX_TRANSFORMATIONS_JSON),
        )

    return reduced_test_dir