def fuzz_glsl(  # pylint: disable=too-many-locals;
    staging_dir: Path,
    reports_dir: Path,
    fuzz_failures_dir: Path,
    active_devices: List[Device],
    references: List[Path],
    donors_dir: Path,
    settings: Settings,
    binary_manager: binaries_util.BinaryManager,
) -> None:
    staging_name = staging_dir.name
    template_source_dir = staging_dir / "source_template"

    # Pick a randomly chosen reference.
    unprepared_reference_shader_job: Path = random.choice(references)

    # The "graphicsfuzz-tool" tool is designed to be on your PATH so that e.g. ".bat" will be appended on Windows.
    # So we use tool_on_path with a custom PATH to get the actual file we want to execute.
    graphicsfuzz_tool_path = util.tool_on_path(
        "graphicsfuzz-tool",
        str(
            binary_manager.get_binary_path_by_name(
                "graphicsfuzz-tool").path.parent),
    )

    try:
        with util.file_open_text(staging_dir / "log.txt", "w") as log_file:
            try:
                gflogging.push_stream_for_logging(log_file)

                # Create the prepared (for Vulkan GLSL) reference.
                glsl_generate_util.run_prepare_reference(
                    graphicsfuzz_tool_path,
                    unprepared_reference_shader_job,
                    template_source_dir / test_util.REFERENCE_DIR /
                    test_util.SHADER_JOB,
                    legacy_graphics_fuzz_vulkan_arg=settings.
                    legacy_graphics_fuzz_vulkan_arg,
                )

                # Generate the variant (GraphicsFuzz requires the unprepared reference as input).
                glsl_generate_util.run_generate(
                    graphicsfuzz_tool_path,
                    unprepared_reference_shader_job,
                    donors_dir,
                    template_source_dir / test_util.VARIANT_DIR /
                    test_util.SHADER_JOB,
                    seed=str(
                        random.getrandbits(
                            glsl_generate_util.GENERATE_SEED_BITS)),
                    other_args=list(settings.extra_graphics_fuzz_generate_args)
                    if settings.extra_graphics_fuzz_generate_args else None,
                    legacy_graphics_fuzz_vulkan_arg=settings.
                    legacy_graphics_fuzz_vulkan_arg,
                )
            finally:
                gflogging.pop_stream_for_logging()
    except subprocess.CalledProcessError:
        util.mkdirs_p(fuzz_failures_dir)
        if len(list(
                fuzz_failures_dir.iterdir())) < settings.maximum_fuzz_failures:
            util.copy_dir(staging_dir, fuzz_failures_dir / staging_dir.name)
        return

    reference_name = unprepared_reference_shader_job.stem

    stable_shader = reference_name.startswith("stable_")

    common_spirv_args = list(settings.common_spirv_args)

    test_dirs = [
        make_test(
            template_source_dir,
            staging_dir / f"{staging_name}_no_opt_test",
            spirv_opt_args=None,
            binary_manager=binary_manager,
            derived_from=reference_name,
            stable_shader=stable_shader,
            common_spirv_args=common_spirv_args,
        ),
        make_test(
            template_source_dir,
            staging_dir / f"{staging_name}_opt_O_test",
            spirv_opt_args=["-O"],
            binary_manager=binary_manager,
            derived_from=reference_name,
            stable_shader=stable_shader,
            common_spirv_args=common_spirv_args,
        ),
    ]

    if not settings.spirv_opt_just_o:
        test_dirs += [
            make_test(
                template_source_dir,
                staging_dir / f"{staging_name}_opt_Os_test",
                spirv_opt_args=["-Os"],
                binary_manager=binary_manager,
                derived_from=reference_name,
                stable_shader=stable_shader,
                common_spirv_args=common_spirv_args,
            ),
            make_test(
                template_source_dir,
                staging_dir / f"{staging_name}_opt_rand1_test",
                spirv_opt_args=spirv_opt_util.random_spirv_opt_args(),
                binary_manager=binary_manager,
                derived_from=reference_name,
                stable_shader=stable_shader,
                common_spirv_args=common_spirv_args,
            ),
            make_test(
                template_source_dir,
                staging_dir / f"{staging_name}_opt_rand2_test",
                spirv_opt_args=spirv_opt_util.random_spirv_opt_args(),
                binary_manager=binary_manager,
                derived_from=reference_name,
                stable_shader=stable_shader,
                common_spirv_args=common_spirv_args,
            ),
            make_test(
                template_source_dir,
                staging_dir / f"{staging_name}_opt_rand3_test",
                spirv_opt_args=spirv_opt_util.random_spirv_opt_args(),
                binary_manager=binary_manager,
                derived_from=reference_name,
                stable_shader=stable_shader,
                common_spirv_args=common_spirv_args,
            ),
        ]

    for test_dir in test_dirs:
        interrupt_util.interrupt_if_needed()
        if handle_test(test_dir, reports_dir, active_devices, binary_manager,
                       settings):
            # If we generated a report, don't bother trying other optimization combinations.
            break
示例#2
0
def main() -> None:  # pylint: disable=too-many-locals;
    parser = argparse.ArgumentParser(
        description="Generates an AmberScript test from a shader job.")

    parser.add_argument(
        "shader_job",
        help="The input .json shader job file.",
    )

    parser.add_argument(
        "--output",
        help="Output directory.",
        default="output",
    )

    parser.add_argument(
        "--spirv_opt_args",
        help=
        "Arguments for spirv-opt as a space-separated string, or an empty string to skip running spirv-opt.",
        default="",
    )

    parser.add_argument(
        "--settings",
        help=
        "Path to a settings JSON file for this instance. The file will be generated if needed. ",
        default="settings.json",
    )

    parsed_args = parser.parse_args(sys.argv[1:])

    shader_job: Path = Path(parsed_args.shader_job)
    out_dir: Path = Path(parsed_args.output)
    spirv_opt_args_str: str = parsed_args.spirv_opt_args
    settings_path: Path = Path(parsed_args.settings)

    spirv_opt_args: List[str] = []
    if spirv_opt_args_str:
        spirv_opt_args = spirv_opt_args_str.split(" ")

    settings = settings_util.read_or_create(settings_path)

    binary_manager = binaries_util.get_default_binary_manager(settings)

    staging_dir = out_dir / "staging"

    template_source_dir = staging_dir / "source_template"
    test_dir = staging_dir / "test"

    run_output_dir: Path = out_dir / "run"

    # Remove stale directories.
    if staging_dir.is_dir():
        shutil.rmtree(staging_dir)
    if run_output_dir.is_dir():
        shutil.rmtree(run_output_dir)

    # Create source template and call |make_test|.

    if shader_job_util.get_related_suffixes_that_exist(
            shader_job, language_suffix=[shader_job_util.SUFFIX_SPIRV]):
        # This is a SPIR-V shader job.

        shader_job_util.copy(
            shader_job,
            template_source_dir / test_util.VARIANT_DIR / test_util.SHADER_JOB,
            language_suffix=shader_job_util.SUFFIXES_SPIRV_FUZZ_INPUT,
        )

        fuzz_spirv_amber_test.make_test(
            template_source_dir,
            test_dir,
            spirv_opt_args=spirv_opt_args,
            binary_manager=binary_manager,
            derived_from=shader_job.stem,
            stable_shader=False,
            common_spirv_args=list(settings.common_spirv_args),
        )

    elif shader_job_util.get_related_suffixes_that_exist(
            shader_job, language_suffix=[shader_job_util.SUFFIX_GLSL]):
        # This is a GLSL shader job.

        # The "graphicsfuzz-tool" tool is designed to be on your PATH so that e.g. ".bat" will be appended on Windows.
        # So we use tool_on_path with a custom PATH to get the actual file we want to execute.
        graphicsfuzz_tool_path = util.tool_on_path(
            "graphicsfuzz-tool",
            str(
                binary_manager.get_binary_path_by_name(
                    "graphicsfuzz-tool").path.parent),
        )

        with util.file_open_text(staging_dir / "log.txt", "w") as log_file:
            try:
                gflogging.push_stream_for_logging(log_file)

                # Create the prepared (for Vulkan GLSL) reference.
                glsl_generate_util.run_prepare_reference(
                    graphicsfuzz_tool_path,
                    shader_job,
                    template_source_dir / test_util.VARIANT_DIR /
                    test_util.SHADER_JOB,
                    legacy_graphics_fuzz_vulkan_arg=settings.
                    legacy_graphics_fuzz_vulkan_arg,
                )
            finally:
                gflogging.pop_stream_for_logging()

        fuzz_glsl_amber_test.make_test(
            template_source_dir,
            test_dir,
            spirv_opt_args=spirv_opt_args,
            binary_manager=binary_manager,
            derived_from=shader_job.stem,
            stable_shader=False,
            common_spirv_args=list(settings.common_spirv_args),
        )

    else:
        raise AssertionError(
            "Unexpected shader job type; expected GLSL or SPIR-V shaders.")

    preprocessor_cache = util.CommandCache()

    fuzz_test_util.run_shader_job(
        source_dir=test_util.get_source_dir(test_dir),
        output_dir=run_output_dir,
        binary_manager=binary_manager,
        device=Device(host=DeviceHost()),
        preprocessor_cache=preprocessor_cache,
        stop_after_amber=True,
    )