intel: Changes to enable standalone shader compiler
diff --git a/icd/intel/compiler/shader/main.cpp b/icd/intel/compiler/shader/main.cpp
index 9fae962..eb16b6c 100644
--- a/icd/intel/compiler/shader/main.cpp
+++ b/icd/intel/compiler/shader/main.cpp
@@ -21,6 +21,11 @@
* 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
*
@@ -31,230 +36,60 @@
* offline compile GLSL code and examine the resulting GLSL IR.
*/
-#include "ast.h"
-#include "glsl_parser_extras.h"
-#include "ir_optimization.h"
-#include "program.h"
-#include "loop_analysis.h"
-#include "standalone_scaffolding.h"
+#include "gpu.h"
+#include "pipeline.h"
+#include "compiler_interface.h"
+#include "compiler/mesa-utils/src/glsl/ralloc.h"
+#include "pipeline_compiler_interface.h"
-static int glsl_version = 330;
-//extern "C" void
-//_mesa_error_no_memory(const char *caller)
-//{
-// fprintf(stderr, "Mesa error: out of memory in %s", caller);
-//}
-
-static void
-initialize_context(struct gl_context *ctx, gl_api api)
+static char* load_spv_file(const char *filename, size_t *psize)
{
- initialize_context_to_defaults(ctx, api);
+ long int size;
+ void *shader_code;
- /* The standalone compiler needs to claim support for almost
- * everything in order to compile the built-in functions.
- */
- ctx->Const.GLSLVersion = glsl_version;
- ctx->Extensions.ARB_ES3_compatibility = true;
- ctx->Const.MaxComputeWorkGroupCount[0] = 65535;
- ctx->Const.MaxComputeWorkGroupCount[1] = 65535;
- ctx->Const.MaxComputeWorkGroupCount[2] = 65535;
- ctx->Const.MaxComputeWorkGroupSize[0] = 1024;
- ctx->Const.MaxComputeWorkGroupSize[1] = 1024;
- ctx->Const.MaxComputeWorkGroupSize[2] = 64;
- ctx->Const.MaxComputeWorkGroupInvocations = 1024;
- ctx->Const.Program[MESA_SHADER_COMPUTE].MaxTextureImageUnits = 16;
- ctx->Const.Program[MESA_SHADER_COMPUTE].MaxUniformComponents = 1024;
- ctx->Const.Program[MESA_SHADER_COMPUTE].MaxInputComponents = 0; /* not used */
- ctx->Const.Program[MESA_SHADER_COMPUTE].MaxOutputComponents = 0; /* not used */
+ FILE *fp = fopen(filename, "rb");
+ if (!fp) return NULL;
- switch (ctx->Const.GLSLVersion) {
- case 100:
- ctx->Const.MaxClipPlanes = 0;
- ctx->Const.MaxCombinedTextureImageUnits = 8;
- ctx->Const.MaxDrawBuffers = 2;
- ctx->Const.MinProgramTexelOffset = 0;
- ctx->Const.MaxProgramTexelOffset = 0;
- ctx->Const.MaxLights = 0;
- ctx->Const.MaxTextureCoordUnits = 0;
- ctx->Const.MaxTextureUnits = 8;
+ fseek(fp, 0L, SEEK_END);
+ size = ftell(fp);
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 8;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 0;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents = 128 * 4;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxInputComponents = 0; /* not used */
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 32;
+ fseek(fp, 0L, SEEK_SET);
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits =
- ctx->Const.MaxCombinedTextureImageUnits;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents = 16 * 4;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents =
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxOutputComponents = 0; /* not used */
+ shader_code = malloc(size);
+ fread(shader_code, size, 1, fp);
- ctx->Const.MaxVarying = ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents / 4;
- break;
- case 110:
- case 120:
- ctx->Const.MaxClipPlanes = 6;
- ctx->Const.MaxCombinedTextureImageUnits = 2;
- ctx->Const.MaxDrawBuffers = 1;
- ctx->Const.MinProgramTexelOffset = 0;
- ctx->Const.MaxProgramTexelOffset = 0;
- ctx->Const.MaxLights = 8;
- ctx->Const.MaxTextureCoordUnits = 2;
- ctx->Const.MaxTextureUnits = 2;
+ *psize = size;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 16;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 0;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents = 512;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxInputComponents = 0; /* not used */
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 32;
-
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits =
- ctx->Const.MaxCombinedTextureImageUnits;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents = 64;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents =
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxOutputComponents = 0; /* not used */
-
- ctx->Const.MaxVarying = ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents / 4;
- break;
- case 130:
- case 140:
- ctx->Const.MaxClipPlanes = 8;
- ctx->Const.MaxCombinedTextureImageUnits = 16;
- ctx->Const.MaxDrawBuffers = 8;
- ctx->Const.MinProgramTexelOffset = -8;
- ctx->Const.MaxProgramTexelOffset = 7;
- ctx->Const.MaxLights = 8;
- ctx->Const.MaxTextureCoordUnits = 8;
- ctx->Const.MaxTextureUnits = 2;
-
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 16;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 16;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents = 1024;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxInputComponents = 0; /* not used */
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 64;
-
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = 16;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents = 1024;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents =
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxOutputComponents = 0; /* not used */
-
- ctx->Const.MaxVarying = ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents / 4;
- break;
- case 150:
- case 330:
- ctx->Const.MaxClipPlanes = 8;
- ctx->Const.MaxDrawBuffers = 8;
- ctx->Const.MinProgramTexelOffset = -8;
- ctx->Const.MaxProgramTexelOffset = 7;
- ctx->Const.MaxLights = 8;
- ctx->Const.MaxTextureCoordUnits = 8;
- ctx->Const.MaxTextureUnits = 2;
-
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 16;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 16;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents = 1024;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxInputComponents = 0; /* not used */
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 64;
-
- ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = 16;
- ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxUniformComponents = 1024;
- ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxInputComponents =
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents;
- ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxOutputComponents = 128;
-
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = 16;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents = 1024;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents =
- ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxOutputComponents;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxOutputComponents = 0; /* not used */
-
- ctx->Const.MaxCombinedTextureImageUnits =
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits
- + ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits
- + ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits;
-
- ctx->Const.MaxGeometryOutputVertices = 256;
- ctx->Const.MaxGeometryTotalOutputComponents = 1024;
-
-// ctx->Const.MaxGeometryVaryingComponents = 64;
-
- ctx->Const.MaxVarying = 60 / 4;
- break;
- case 300:
- ctx->Const.MaxClipPlanes = 8;
- ctx->Const.MaxCombinedTextureImageUnits = 32;
- ctx->Const.MaxDrawBuffers = 4;
- ctx->Const.MinProgramTexelOffset = -8;
- ctx->Const.MaxProgramTexelOffset = 7;
- ctx->Const.MaxLights = 0;
- ctx->Const.MaxTextureCoordUnits = 0;
- ctx->Const.MaxTextureUnits = 0;
-
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 16;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 16;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents = 1024;
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxInputComponents = 0; /* not used */
- ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 16 * 4;
-
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = 16;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents = 224;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents = 15 * 4;
- ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxOutputComponents = 0; /* not used */
-
- ctx->Const.MaxVarying = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents / 4;
- break;
- }
-
- ctx->Driver.NewShader = _mesa_new_shader;
+ return (char *) shader_code;
}
-/* Returned string will have 'ctx' as its ralloc owner. */
-static char *
-load_text_file(void *ctx, const char *file_name)
+
+static char* load_glsl_file(const char *filename, size_t *psize, VkShaderStage stage)
{
- char *text = NULL;
- size_t size;
- size_t total_read = 0;
- FILE *fp = fopen(file_name, "rb");
+ long int size;
+ void *shader_code;
- if (!fp) {
- return NULL;
- }
+ FILE *fp = fopen(filename, "r");
+ if (!fp) return NULL;
- fseek(fp, 0L, SEEK_END);
- size = ftell(fp);
- fseek(fp, 0L, SEEK_SET);
+ fseek(fp, 0L, SEEK_END);
+ size = ftell(fp) + sizeof(icd_spv_header) + 1;
- text = (char *) ralloc_size(ctx, size + 1);
- if (text != NULL) {
- do {
- size_t bytes = fread(text + total_read,
- 1, size - total_read, fp);
- if (bytes < size - total_read) {
- free(text);
- text = NULL;
- goto error;
- }
+ fseek(fp, 0L, SEEK_SET);
- if (bytes == 0) {
- break;
- }
+ 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;
- total_read += bytes;
- } while (total_read < size);
+ icd_spv_header* header = (icd_spv_header*)shader_code;
+ header->magic = ICD_SPV_MAGIC;
+ header->version = 0; // not SPV
+ header->gen_magic = stage;
- text[total_read] = '\0';
-error:;
- }
+ *psize = size;
- fclose(fp);
-
- return text;
+ return (char *) shader_code;
}
int dump_ast = 0;
@@ -271,186 +106,129 @@
{ NULL, 0, NULL, 0 }
};
-/**
- * \brief Print proper usage and exit with failure.
- */
-void
-usage_fail(const char *name)
-{
- const char *header =
- "usage: %s [options] <file.vert | file.geom | file.frag>\n"
- "\n"
- "Possible options are:\n";
- printf(header, name, name);
- for (const struct option *o = compiler_opts; o->name != 0; ++o) {
- printf(" --%s\n", o->name);
- }
- exit(EXIT_FAILURE);
+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 or .frag\n");
+ return false;
+ }
+
+ return true;
}
-extern "C" {
-/* Stubbed linkage for diskcache, which is not used for standalone compilation */
-extern int
-mesa_shader_diskcache_find(struct gl_context *ctx, struct gl_shader *shader)
+
+bool checkFileExt(char* fileName, const char* ext)
{
- return 1;
+ const unsigned fileNameLength = strlen(fileName);
+ if (strncmp(ext, &fileName[fileNameLength - strlen(ext)], strlen(ext)) != 0) {
+ return false;
+ }
+
+ return true;
}
-/* Stubbed linkage for diskcache, which is not used for standalone compilation */
-extern int
-mesa_shader_diskcache_cache(struct gl_context *ctx, struct gl_shader *shader)
-{
- return 1;
-}
-
-} // extern "C"
-
-
-void
-compile_shader(struct gl_context *ctx, struct gl_shader *shader)
-{
- struct _mesa_glsl_parse_state *state =
- new(shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader);
-
- // There's no _Shader set up in the context pipeline state for the standalone
- // compiler, so we fake it.
- GLbitfield flags = 0x0;
- const char *env = _mesa_getenv("MESA_GLSL");
- if (env) {
- if (strstr(env, "glassy"))
- flags |= GLSL_USE_GLASS;
- }
-
- if (flags & GLSL_USE_GLASS)
- ctx->Const.GlassMode = 2;
-
- _mesa_glsl_compile_shader(ctx, shader, dump_ast, dump_hir);
-
- /* Print out the resulting IR */
- if (!state->error && dump_lir) {
- _mesa_print_ir(stdout, shader->ir, state);
- }
-
- return;
-}
-
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
{
int status = EXIT_SUCCESS;
- struct gl_context local_ctx;
- struct gl_context *ctx = &local_ctx;
- bool glsl_es = false;
- int c;
- int idx = 0;
- while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1) {
- switch (c) {
- case 'v':
- glsl_version = strtol(optarg, NULL, 10);
- switch (glsl_version) {
- case 100:
- case 300:
- glsl_es = true;
- break;
- case 110:
- case 120:
- case 130:
- case 140:
- case 150:
- case 330:
- glsl_es = false;
- break;
- default:
- fprintf(stderr, "Unrecognized GLSL version `%s'\n", optarg);
- usage_fail(argv[0]);
- break;
- }
- break;
- default:
- break;
- }
+ switch (argc) {
+ case 2:
+ {
+ // Call vkCreateShader on the single shader
+
+ printf("Frontend compile %s\n", argv[1]);
+
+ void *shaderCode;
+ size_t size;
+
+ if (checkFileExt(argv[1], ".spv")) {
+ shaderCode = load_spv_file(argv[1], &size);
+ } else if (checkFileExt(argv[1], ".frag")) {
+ shaderCode = load_glsl_file(argv[1], &size, VK_SHADER_STAGE_FRAGMENT);
+ } else if (checkFileExt(argv[1], ".vert")) {
+ shaderCode = load_glsl_file(argv[1], &size, VK_SHADER_STAGE_VERTEX);
+ } else {
+ return EXIT_FAILURE;
+ }
+
+ assert(shaderCode);
+
+ struct intel_ir *shader_program = shader_create_ir(NULL, shaderCode, size);
+ 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]);
+
+ // 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]);
+ 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]);
+ 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;
}
- _mesa_create_shader_compiler();
-
- if (argc <= optind)
- usage_fail(argv[0]);
-
- initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL_COMPAT);
-
- struct gl_shader_program *whole_program;
-
- whole_program = rzalloc (NULL, struct gl_shader_program);
- assert(whole_program != NULL);
- whole_program->InfoLog = ralloc_strdup(whole_program, "");
-
- for (/* empty */; argc > optind; optind++) {
- whole_program->Shaders =
- reralloc(whole_program, whole_program->Shaders,
- struct gl_shader *, whole_program->NumShaders + 1);
- assert(whole_program->Shaders != NULL);
-
- struct gl_shader *shader = rzalloc(whole_program, gl_shader);
-
- whole_program->Shaders[whole_program->NumShaders] = shader;
- whole_program->NumShaders++;
-
- const unsigned len = strlen(argv[optind]);
- if (len < 6)
- usage_fail(argv[0]);
-
- const char *const ext = & argv[optind][len - 5];
- if (strncmp(".vert", ext, 5) == 0 || strncmp(".glsl", ext, 5) == 0)
- shader->Type = GL_VERTEX_SHADER;
- else if (strncmp(".geom", ext, 5) == 0)
- shader->Type = GL_GEOMETRY_SHADER;
- else if (strncmp(".frag", ext, 5) == 0)
- shader->Type = GL_FRAGMENT_SHADER;
- else if (strncmp(".comp", ext, 5) == 0)
- shader->Type = GL_COMPUTE_SHADER;
- else
- usage_fail(argv[0]);
- shader->Stage = _mesa_shader_enum_to_shader_stage(shader->Type);
-
- shader->Source = load_text_file(whole_program, argv[optind]);
- if (shader->Source == NULL) {
- printf("File \"%s\" does not exist.\n", argv[optind]);
- exit(EXIT_FAILURE);
- }
-
- compile_shader(ctx, shader);
-
- if (strlen(shader->InfoLog) > 0)
- printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
-
- if (!shader->CompileStatus) {
- status = EXIT_FAILURE;
- break;
- }
- }
-
- if ((status == EXIT_SUCCESS) && do_link) {
- assert(whole_program->NumShaders == 1);
-
- // for VK, we are independently compiling and linking individual
- // shaders, which matches this frontend's concept of SSO
- whole_program->SeparateShader = true;
-
- link_shaders(ctx, whole_program);
- status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;
-
- if (strlen(whole_program->InfoLog) > 0)
- printf("Info log for linking:\n%s\n", whole_program->InfoLog);
- }
-
- for (unsigned i = 0; i < MESA_SHADER_STAGES; i++)
- ralloc_free(whole_program->_LinkedShaders[i]);
-
- ralloc_free(whole_program);
- _mesa_glsl_release_types();
- _mesa_glsl_release_builtin_functions();
-
return status;
}