mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
0a73c75db8
Since the introduction of instruction arrays, the parser location no longer matches the location of the current instruction. Ultimately we'll likely want to add some kind of explicit location information to struct vkd3d_shader_instruction_array, because we might do transformations that change the order of the original instructions.
130 lines
4.1 KiB
C
130 lines
4.1 KiB
C
/*
|
|
* Copyright 2021 Atharva Nimbalkar
|
|
*
|
|
* 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.1 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include "vkd3d_shader_private.h"
|
|
|
|
struct vkd3d_glsl_generator
|
|
{
|
|
struct vkd3d_shader_version version;
|
|
struct vkd3d_string_buffer buffer;
|
|
struct vkd3d_shader_location location;
|
|
struct vkd3d_shader_message_context *message_context;
|
|
bool failed;
|
|
};
|
|
|
|
struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_version *version,
|
|
struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location)
|
|
{
|
|
struct vkd3d_glsl_generator *generator;
|
|
|
|
if (!(generator = vkd3d_malloc(sizeof(*generator))))
|
|
return NULL;
|
|
|
|
memset(generator, 0, sizeof(*generator));
|
|
generator->version = *version;
|
|
vkd3d_string_buffer_init(&generator->buffer);
|
|
generator->location = *location;
|
|
generator->message_context = message_context;
|
|
return generator;
|
|
}
|
|
|
|
static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error(
|
|
struct vkd3d_glsl_generator *generator,
|
|
enum vkd3d_shader_error error, const char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, fmt);
|
|
vkd3d_shader_verror(generator->message_context, &generator->location, error, fmt, args);
|
|
va_end(args);
|
|
generator->failed = true;
|
|
}
|
|
|
|
static void shader_glsl_ret(struct vkd3d_glsl_generator *generator,
|
|
const struct vkd3d_shader_instruction *ins)
|
|
{
|
|
const struct vkd3d_shader_version *version = &generator->version;
|
|
|
|
/*
|
|
* TODO: Implement in_subroutine
|
|
* TODO: shader_glsl_generate_shader_epilogue(generator);
|
|
*/
|
|
if (version->major >= 4)
|
|
{
|
|
vkd3d_string_buffer_printf(&generator->buffer, "return;\n");
|
|
}
|
|
}
|
|
|
|
static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator,
|
|
const struct vkd3d_shader_instruction *instruction)
|
|
{
|
|
switch (instruction->handler_idx)
|
|
{
|
|
case VKD3DSIH_DCL_INPUT:
|
|
case VKD3DSIH_DCL_OUTPUT:
|
|
case VKD3DSIH_DCL_OUTPUT_SIV:
|
|
break;
|
|
case VKD3DSIH_RET:
|
|
shader_glsl_ret(generator, instruction);
|
|
break;
|
|
default:
|
|
vkd3d_glsl_compiler_error(generator,
|
|
VKD3D_SHADER_ERROR_GLSL_INTERNAL,
|
|
"Unhandled instruction %#x", instruction->handler_idx);
|
|
break;
|
|
}
|
|
}
|
|
|
|
int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator,
|
|
struct vkd3d_shader_parser *parser, struct vkd3d_shader_code *out)
|
|
{
|
|
unsigned int i;
|
|
void *code;
|
|
|
|
vkd3d_string_buffer_printf(&generator->buffer, "#version 440\n\n");
|
|
vkd3d_string_buffer_printf(&generator->buffer, "void main()\n{\n");
|
|
|
|
generator->location.column = 0;
|
|
for (i = 0; i < parser->instructions.count; ++i)
|
|
{
|
|
generator->location.line = i + 1;
|
|
vkd3d_glsl_handle_instruction(generator, &parser->instructions.elements[i]);
|
|
}
|
|
|
|
if (generator->failed)
|
|
return VKD3D_ERROR_INVALID_SHADER;
|
|
|
|
vkd3d_string_buffer_printf(&generator->buffer, "}\n");
|
|
|
|
if ((code = vkd3d_malloc(generator->buffer.buffer_size)))
|
|
{
|
|
memcpy(code, generator->buffer.buffer, generator->buffer.content_size);
|
|
out->size = generator->buffer.content_size;
|
|
out->code = code;
|
|
}
|
|
else return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
|
|
return VKD3D_OK;
|
|
}
|
|
|
|
void vkd3d_glsl_generator_destroy(struct vkd3d_glsl_generator *generator)
|
|
{
|
|
vkd3d_string_buffer_cleanup(&generator->buffer);
|
|
vkd3d_free(generator);
|
|
}
|