Files
gtk/gsk/gskslprogram.c
Benjamin Otte 8431b63b5d gsksl: Add support for stages
The stage is just passed to everywhere it's needed. The compiler does
not keep a stage property, instead it requires passing the stage as an
argument to every compilation.

As a side effect, environment treatment has changed:
Environments now allow creating "similar" (for lack of a better term)
environments with different version/profile.
We use this to pass the stage as part of the environment.
2017-10-30 02:58:03 +01:00

169 lines
4.5 KiB
C

/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslprogramprivate.h"
#include "gsksldeclarationprivate.h"
#include "gskslenvironmentprivate.h"
#include "gskslfunctionprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gskslprinterprivate.h"
#include "gskslscopeprivate.h"
#include "gsksltokenizerprivate.h"
#include "gsksltypeprivate.h"
#include "gskspvwriterprivate.h"
struct _GskSlProgram {
GObject parent_instance;
GskSlShaderStage stage;
GskSlScope *scope;
GSList *declarations;
};
G_DEFINE_TYPE (GskSlProgram, gsk_sl_program, G_TYPE_OBJECT)
static void
gsk_sl_program_dispose (GObject *object)
{
GskSlProgram *program = GSK_SL_PROGRAM (object);
g_slist_free_full (program->declarations, (GDestroyNotify) gsk_sl_declaration_unref);
g_clear_pointer (&program->scope, gsk_sl_scope_unref);
G_OBJECT_CLASS (gsk_sl_program_parent_class)->dispose (object);
}
static void
gsk_sl_program_class_init (GskSlProgramClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gsk_sl_program_dispose;
}
static void
gsk_sl_program_init (GskSlProgram *program)
{
}
void
gsk_sl_program_parse (GskSlProgram *program,
GskSlPreprocessor *preproc)
{
GskSlDeclaration *declaration;
const GskSlToken *token;
program->stage = gsk_sl_environment_get_stage (gsk_sl_preprocessor_get_environment (preproc));
program->scope = gsk_sl_environment_create_scope (gsk_sl_preprocessor_get_environment (preproc));
for (token = gsk_sl_preprocessor_get (preproc);
!gsk_sl_token_is (token, GSK_SL_TOKEN_EOF);
token = gsk_sl_preprocessor_get (preproc))
{
declaration = gsk_sl_declaration_parse (program->scope, preproc);
if (declaration)
program->declarations = g_slist_prepend (program->declarations, declaration);
}
program->declarations = g_slist_reverse (program->declarations);
}
void
gsk_sl_program_print (GskSlProgram *program,
GString *string)
{
GskSlPrinter *printer;
GskSlFunction *function;
gboolean need_newline = FALSE;
GSList *l;
char *str;
g_return_if_fail (GSK_IS_SL_PROGRAM (program));
g_return_if_fail (string != NULL);
printer = gsk_sl_printer_new ();
for (l = program->declarations; l; l = l->next)
{
function = gsk_sl_declaration_get_function (l->data);
if ((function || need_newline) && l != program->declarations)
gsk_sl_printer_newline (printer);
gsk_sl_declaration_print (l->data, printer);
need_newline = function != NULL;
}
str = gsk_sl_printer_write_to_string (printer);
g_string_append (string, str);
g_free (str);
gsk_sl_printer_unref (printer);
}
static void
gsk_sl_program_write_spv_initializer (GskSpvWriter *writer,
gpointer data)
{
GskSlProgram *program = data;
GSList *l;
for (l = program->declarations; l; l = l->next)
gsk_sl_declaration_write_initializer_spv (l->data, writer);
}
static GskSlFunction *
gsk_sl_program_get_entry_point (GskSlProgram *program)
{
GSList *l;
for (l = program->declarations; l; l = l->next)
{
GskSlFunction *function = gsk_sl_declaration_get_function (l->data);
if (function && g_str_equal (gsk_sl_function_get_name (function), "main"))
return function;
}
return NULL;
}
GBytes *
gsk_sl_program_to_spirv (GskSlProgram *program)
{
GskSpvWriter *writer;
GBytes *bytes;
g_return_val_if_fail (GSK_IS_SL_PROGRAM (program), NULL);
writer = gsk_spv_writer_new (program->stage);
bytes = gsk_spv_writer_write (writer,
gsk_sl_program_get_entry_point (program),
gsk_sl_program_write_spv_initializer,
program);
gsk_spv_writer_unref (writer);
return bytes;
}