Newer
Older
/*
* Copyright 2017 Józef Kucia for CodeWeavers
* Copyright 2021 Conor McCarthy for CodeWeavers
*
* 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"
#include <stdarg.h>
#ifdef HAVE_SPIRV_UNIFIED1_SPIRV_H
# include "spirv/unified1/spirv.h"
#else
# include "vulkan/spirv.h"
#endif /* HAVE_SPIRV_UNIFIED1_SPIRV_H */
#ifdef HAVE_SPIRV_UNIFIED1_GLSL_STD_450_H
# include "spirv/unified1/GLSL.std.450.h"
#else
# include "vulkan/GLSL.std.450.h"
#endif /* HAVE_SPIRV_UNIFIED1_GLSL_STD_450_H */
Józef Kucia
committed
#ifdef HAVE_SPIRV_TOOLS
# include "spirv-tools/libspirv.h"
Józef Kucia
committed
Henri Verbeet
committed
static spv_target_env spv_target_env_from_vkd3d(enum vkd3d_shader_spirv_environment environment)
Henri Verbeet
committed
switch (environment)
Henri Verbeet
committed
case VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5:
return SPV_ENV_OPENGL_4_5;
Henri Verbeet
committed
case VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0:
return SPV_ENV_VULKAN_1_0;
default:
Henri Verbeet
committed
ERR("Invalid environment %#x.\n", environment);
return SPV_ENV_VULKAN_1_0;
}
}
static uint32_t get_binary_to_text_options(enum vkd3d_shader_compile_option_formatting_flags formatting)
{
uint32_t out = 0;
unsigned int i;
static const struct
{
enum vkd3d_shader_compile_option_formatting_flags vkd3d;
uint32_t spv;
bool invert;
}
valuemap[] =
{
{VKD3D_SHADER_COMPILE_OPTION_FORMATTING_COLOUR, SPV_BINARY_TO_TEXT_OPTION_COLOR },
{VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT, SPV_BINARY_TO_TEXT_OPTION_INDENT },
{VKD3D_SHADER_COMPILE_OPTION_FORMATTING_OFFSETS, SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET},
{VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER, true},
{VKD3D_SHADER_COMPILE_OPTION_FORMATTING_RAW_IDS, SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES, true},
for (i = 0; i < ARRAY_SIZE(valuemap); ++i)
{
if (valuemap[i].invert == !(formatting & valuemap[i].vkd3d))
out |= valuemap[i].spv;
return out;
}
static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_code *spirv,
Henri Verbeet
committed
enum vkd3d_shader_spirv_environment environment,
enum vkd3d_shader_compile_option_formatting_flags formatting, struct vkd3d_shader_code *out)
Józef Kucia
committed
{
spv_diagnostic diagnostic = NULL;
spv_text text = NULL;
spv_context context;
spv_result_t spvret;
enum vkd3d_result result = VKD3D_OK;
Józef Kucia
committed
Henri Verbeet
committed
context = spvContextCreate(spv_target_env_from_vkd3d(environment));
Józef Kucia
committed
if (!(spvret = spvBinaryToText(context, spirv->code, spirv->size / sizeof(uint32_t),
Henri Verbeet
committed
get_binary_to_text_options(formatting), &text, &diagnostic)))
Józef Kucia
committed
{
void *code = vkd3d_malloc(text->length);
if (code)
Józef Kucia
committed
{
memcpy(code, text->str, text->length);
out->size = text->length;
out->code = code;
Józef Kucia
committed
}
else
result = VKD3D_ERROR_OUT_OF_MEMORY;
Józef Kucia
committed
}
else
{
FIXME("Failed to convert SPIR-V binary to text, ret %d.\n", spvret);
Józef Kucia
committed
FIXME("Diagnostic message: %s.\n", debugstr_a(diagnostic->error));
result = VKD3D_ERROR;
Józef Kucia
committed
}
spvTextDestroy(text);
spvDiagnosticDestroy(diagnostic);
spvContextDestroy(context);
return result;
}
static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv,
enum vkd3d_shader_spirv_environment environment)
{
Henri Verbeet
committed
static const enum vkd3d_shader_compile_option_formatting_flags formatting
= VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT | VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER;
struct vkd3d_shader_code text;
Henri Verbeet
committed
if (!vkd3d_spirv_binary_to_text(spirv, environment, formatting, &text))
Elizabeth Figura
committed
vkd3d_shader_trace_text(text.code, text.size);
vkd3d_shader_free_shader_code(&text);
}
Józef Kucia
committed
}
Giovanni Mascellani
committed
static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv,
Henri Verbeet
committed
enum vkd3d_shader_spirv_environment environment)
Józef Kucia
committed
{
spv_diagnostic diagnostic = NULL;
spv_context context;
spv_result_t ret;
Henri Verbeet
committed
context = spvContextCreate(spv_target_env_from_vkd3d(environment));
Józef Kucia
committed
if ((ret = spvValidateBinary(context, spirv->code, spirv->size / sizeof(uint32_t),
&diagnostic)))
{
Giovanni Mascellani
committed
vkd3d_string_buffer_printf(buffer, "%s", diagnostic->error);
Józef Kucia
committed
}
spvDiagnosticDestroy(diagnostic);
spvContextDestroy(context);
Giovanni Mascellani
committed
return !ret;
Józef Kucia
committed
}
#else
static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_code *spirv,
Henri Verbeet
committed
enum vkd3d_shader_spirv_environment environment,
enum vkd3d_shader_compile_option_formatting_flags formatting, struct vkd3d_shader_code *out)
{
return VKD3D_ERROR;
}
Henri Verbeet
committed
static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv,
enum vkd3d_shader_spirv_environment environment) {}
Giovanni Mascellani
committed
static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv,
enum vkd3d_shader_spirv_environment environment)
{
return true;
}
Józef Kucia
committed
Conor McCarthy
committed
enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval,
unsigned int index)
{
switch (sysval)
{
case VKD3D_SHADER_SV_COVERAGE:
case VKD3D_SHADER_SV_DEPTH:
case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL:
case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL:
Henri Verbeet
committed
case VKD3D_SHADER_SV_NONE:
case VKD3D_SHADER_SV_STENCIL_REF:
case VKD3D_SHADER_SV_TARGET:
return VKD3D_SIV_NONE;
Henri Verbeet
committed
case VKD3D_SHADER_SV_POSITION:
return VKD3D_SIV_POSITION;
Henri Verbeet
committed
case VKD3D_SHADER_SV_CLIP_DISTANCE:
Henri Verbeet
committed
return VKD3D_SIV_CLIP_DISTANCE;
Henri Verbeet
committed
case VKD3D_SHADER_SV_CULL_DISTANCE:
Henri Verbeet
committed
return VKD3D_SIV_CULL_DISTANCE;
case VKD3D_SHADER_SV_INSTANCE_ID:
return VKD3D_SIV_INSTANCE_ID;
case VKD3D_SHADER_SV_IS_FRONT_FACE:
return VKD3D_SIV_IS_FRONT_FACE;
case VKD3D_SHADER_SV_PRIMITIVE_ID:
return VKD3D_SIV_PRIMITIVE_ID;
case VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX:
Loading
Loading full blame...