1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2005-2007  Brian Paul   All Rights Reserved.
3bf215546Sopenharmony_ci * Copyright (C) 2008  VMware, Inc.   All Rights Reserved.
4bf215546Sopenharmony_ci * Copyright © 2010 Intel Corporation
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
12bf215546Sopenharmony_ci *
13bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
14bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
15bf215546Sopenharmony_ci * Software.
16bf215546Sopenharmony_ci *
17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
24bf215546Sopenharmony_ci */
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "main/shaderapi.h"
27bf215546Sopenharmony_ci#include "main/shaderobj.h"
28bf215546Sopenharmony_ci#include "main/glspirv.h"
29bf215546Sopenharmony_ci#include "compiler/glsl/glsl_parser_extras.h"
30bf215546Sopenharmony_ci#include "compiler/glsl_types.h"
31bf215546Sopenharmony_ci#include "compiler/glsl/linker.h"
32bf215546Sopenharmony_ci#include "compiler/glsl/program.h"
33bf215546Sopenharmony_ci#include "compiler/glsl/shader_cache.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "state_tracker/st_glsl_to_ir.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ciextern "C" {
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci/**
40bf215546Sopenharmony_ci * Link a GLSL shader program.  Called via glLinkProgram().
41bf215546Sopenharmony_ci */
42bf215546Sopenharmony_civoid
43bf215546Sopenharmony_ci_mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
44bf215546Sopenharmony_ci{
45bf215546Sopenharmony_ci   unsigned int i;
46bf215546Sopenharmony_ci   bool spirv = false;
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci   _mesa_clear_shader_program_data(ctx, prog);
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci   prog->data = _mesa_create_shader_program_data();
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   prog->data->LinkStatus = LINKING_SUCCESS;
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci   for (i = 0; i < prog->NumShaders; i++) {
55bf215546Sopenharmony_ci      if (!prog->Shaders[i]->CompileStatus) {
56bf215546Sopenharmony_ci	 linker_error(prog, "linking with uncompiled/unspecialized shader");
57bf215546Sopenharmony_ci      }
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_ci      if (!i) {
60bf215546Sopenharmony_ci         spirv = (prog->Shaders[i]->spirv_data != NULL);
61bf215546Sopenharmony_ci      } else if (spirv && !prog->Shaders[i]->spirv_data) {
62bf215546Sopenharmony_ci         /* The GL_ARB_gl_spirv spec adds a new bullet point to the list of
63bf215546Sopenharmony_ci          * reasons LinkProgram can fail:
64bf215546Sopenharmony_ci          *
65bf215546Sopenharmony_ci          *    "All the shader objects attached to <program> do not have the
66bf215546Sopenharmony_ci          *     same value for the SPIR_V_BINARY_ARB state."
67bf215546Sopenharmony_ci          */
68bf215546Sopenharmony_ci         linker_error(prog,
69bf215546Sopenharmony_ci                      "not all attached shaders have the same "
70bf215546Sopenharmony_ci                      "SPIR_V_BINARY_ARB state");
71bf215546Sopenharmony_ci      }
72bf215546Sopenharmony_ci   }
73bf215546Sopenharmony_ci   prog->data->spirv = spirv;
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   if (prog->data->LinkStatus) {
76bf215546Sopenharmony_ci      if (!spirv)
77bf215546Sopenharmony_ci         link_shaders(ctx, prog);
78bf215546Sopenharmony_ci      else
79bf215546Sopenharmony_ci         _mesa_spirv_link_shaders(ctx, prog);
80bf215546Sopenharmony_ci   }
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   /* If LinkStatus is LINKING_SUCCESS, then reset sampler validated to true.
83bf215546Sopenharmony_ci    * Validation happens via the LinkShader call below. If LinkStatus is
84bf215546Sopenharmony_ci    * LINKING_SKIPPED, then SamplersValidated will have been restored from the
85bf215546Sopenharmony_ci    * shader cache.
86bf215546Sopenharmony_ci    */
87bf215546Sopenharmony_ci   if (prog->data->LinkStatus == LINKING_SUCCESS) {
88bf215546Sopenharmony_ci      prog->SamplersValidated = GL_TRUE;
89bf215546Sopenharmony_ci   }
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   if (prog->data->LinkStatus && !st_link_shader(ctx, prog)) {
92bf215546Sopenharmony_ci      prog->data->LinkStatus = LINKING_FAILURE;
93bf215546Sopenharmony_ci   }
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   if (prog->data->LinkStatus != LINKING_FAILURE)
96bf215546Sopenharmony_ci      _mesa_create_program_resource_hash(prog);
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   /* Return early if we are loading the shader from on-disk cache */
99bf215546Sopenharmony_ci   if (prog->data->LinkStatus == LINKING_SKIPPED)
100bf215546Sopenharmony_ci      return;
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci   if (ctx->_Shader->Flags & GLSL_DUMP) {
103bf215546Sopenharmony_ci      if (!prog->data->LinkStatus) {
104bf215546Sopenharmony_ci	 fprintf(stderr, "GLSL shader program %d failed to link\n", prog->Name);
105bf215546Sopenharmony_ci      }
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci      if (prog->data->InfoLog && prog->data->InfoLog[0] != 0) {
108bf215546Sopenharmony_ci	 fprintf(stderr, "GLSL shader program %d info log:\n", prog->Name);
109bf215546Sopenharmony_ci         fprintf(stderr, "%s\n", prog->data->InfoLog);
110bf215546Sopenharmony_ci      }
111bf215546Sopenharmony_ci   }
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci#ifdef ENABLE_SHADER_CACHE
114bf215546Sopenharmony_ci   if (prog->data->LinkStatus)
115bf215546Sopenharmony_ci      shader_cache_write_program_metadata(ctx, prog);
116bf215546Sopenharmony_ci#endif
117bf215546Sopenharmony_ci}
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci} /* extern "C" */
120