blob: 812330d2bcab8a2165c668f257f7b7a27277327d [file] [log] [blame]
/*
* Copyright © 2008, 2009 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <inttypes.h>
/** @file main.cpp
*
* This file is the main() routine and scaffolding for producing
* builtin_compiler (which doesn't include builtins itself and is used
* to generate the profile information for builtin_function.cpp), and
* for glsl_compiler (which does include builtins and can be used to
* offline compile GLSL code and examine the resulting GLSL IR.
*/
#include "gpu.h"
#include "pipeline.h"
#include "compiler_interface.h"
#include "compiler/mesa-utils/src/glsl/ralloc.h"
#include "pipeline_compiler_interface.h"
static char* load_spv_file(const char *filename, size_t *psize)
{
long int size;
void *shader_code;
FILE *fp = fopen(filename, "rb");
if (!fp) return NULL;
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
shader_code = malloc(size);
fread(shader_code, size, 1, fp);
*psize = size;
return (char *) shader_code;
}
static char* load_glsl_file(const char *filename, size_t *psize, VkShaderStageFlagBits stage)
{
long int size;
void *shader_code;
FILE *fp = fopen(filename, "r");
if (!fp) return NULL;
fseek(fp, 0L, SEEK_END);
size = ftell(fp) + sizeof(icd_spv_header) + 1;
fseek(fp, 0L, SEEK_SET);
shader_code = malloc(size);
fread((char *)shader_code + sizeof(icd_spv_header), size - sizeof(icd_spv_header), 1, fp);
((char *)shader_code)[size-1] = 0;
icd_spv_header* header = (icd_spv_header*)shader_code;
header->magic = ICD_SPV_MAGIC;
header->version = 0; // not SPV
header->gen_magic = stage;
*psize = size;
return (char *) shader_code;
}
int dump_ast = 0;
int dump_hir = 0;
int dump_lir = 0;
int do_link = 0;
const struct option compiler_opts[] = {
{ "dump-ast", no_argument, &dump_ast, 1 },
{ "dump-hir", no_argument, &dump_hir, 1 },
{ "dump-lir", no_argument, &dump_lir, 1 },
{ "link", no_argument, &do_link, 1 },
{ "version", required_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 }
};
bool checkFileName(char* fileName)
{
const unsigned fileNameLength = strlen(fileName);
if (fileNameLength < 5 ||
strncmp(".spv", &fileName[fileNameLength - 4], 4) != 0) {
printf("file must be .spv, .vert, .geom, or .frag\n");
return false;
}
return true;
}
bool checkFileExt(char* fileName, const char* ext)
{
const unsigned fileNameLength = strlen(fileName);
if (strncmp(ext, &fileName[fileNameLength - strlen(ext)], strlen(ext)) != 0) {
return false;
}
return true;
}
int main(int argc, char **argv)
{
int status = EXIT_SUCCESS;
switch (argc) {
case 2:
{
// Call vkCreateShader on the single shader
printf("Frontend compile %s\n", argv[1]);
fflush(stdout);
void *shaderCode;
size_t size;
VkShaderStageFlagBits stage = VK_SHADER_STAGE_VERTEX_BIT;
if (checkFileExt(argv[1], ".spv")) {
shaderCode = load_spv_file(argv[1], &size);
} else if (checkFileExt(argv[1], ".vert")) {
stage = VK_SHADER_STAGE_VERTEX_BIT;
} else if (checkFileExt(argv[1], ".geom")) {
stage = VK_SHADER_STAGE_GEOMETRY_BIT;
} else if (checkFileExt(argv[1], ".frag")) {
stage = VK_SHADER_STAGE_FRAGMENT_BIT;
} else {
return EXIT_FAILURE;
}
shaderCode = load_glsl_file(argv[1], &size, stage);
assert(shaderCode);
struct intel_ir *shader_program = shader_create_ir(NULL, shaderCode, size, stage);
assert(shader_program);
// Set up only the fields needed for backend compile
struct intel_gpu gpu = { 0 };
gpu.gen_opaque = INTEL_GEN(7.5);
gpu.gt = 3;
printf("Backend compile %s\n", argv[1]);
fflush(stdout);
// struct timespec before;
// clock_gettime(CLOCK_MONOTONIC, &before);
// uint64_t beforeNanoSeconds = before.tv_nsec + before.tv_sec*INT64_C(1000000000);
struct intel_pipeline_shader pipe_shader;
VkResult ret = intel_pipeline_shader_compile(&pipe_shader, &gpu, NULL, NULL, shader_program);
// struct timespec after;
// clock_gettime(CLOCK_MONOTONIC, &after);
// uint64_t afterNanoSeconds = after.tv_nsec + after.tv_sec*INT64_C(1000000000);
// printf("file: %s, intel_pipeline_shader_compile = %" PRIu64 " milliseconds\n", argv[1], (afterNanoSeconds - beforeNanoSeconds)/1000000);
// fflush(stdout);
if (ret != VK_SUCCESS)
return ret;
intel_pipeline_shader_cleanup(&pipe_shader, &gpu);
shader_destroy_ir(shader_program);
}
break;
case 3:
// Call vkCreateShader on both shaders, then call vkCreateGraphicsPipeline?
// Only need to hook this up if we start invoking the backend once for the whole pipeline
printf("Multiple shaders not hooked up yet\n");
break;
// Ensure both filenames have a .spv extension
if (!checkFileName(argv[1]))
return EXIT_FAILURE;
if (!checkFileName(argv[2]))
return EXIT_FAILURE;
void *shaderCode[2];
size_t size[2];
struct intel_ir *result[2];
// Compile first shader
shaderCode[0] = load_spv_file(argv[1], &size[0]);
assert(shaderCode[0]);
printf("Compiling %s\n", argv[1]);
result[0] = shader_create_ir(NULL, shaderCode[0], size[0], VK_SHADER_STAGE_VERTEX_BIT);
assert(result[0]);
// Compile second shader
shaderCode[1] = load_spv_file(argv[2], &size[1]);
assert(shaderCode[1]);
printf("Compiling %s\n", argv[2]);
result[1] = shader_create_ir(NULL, shaderCode[1], size[1], VK_SHADER_STAGE_FRAGMENT_BIT);
assert(result[1]);
shader_destroy_ir(result[0]);
shader_destroy_ir(result[1]);
break;
case 0:
case 1:
default:
printf("Please provide one .spv, .vert or .frag file as input\n");
break;
}
return status;
}