Newer
Older
/*
* Copyright 2017 Józef Kucia for CodeWeavers
Conor McCarthy
committed
* 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,
enum vkd3d_shader_spirv_environment environment, uint32_t options, 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),
Józef Kucia
committed
options, &text, &diagnostic)))
{
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)
{
const static uint32_t options
= SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT;
struct vkd3d_shader_code text;
if (!vkd3d_spirv_binary_to_text(spirv, environment, options, &text))
{
const char *str, *current = text.code;
while ((str = strchr(current, '\n')))
{
TRACE("%.*s\n", (int)(str - current), current);
current = str + 1;
}
vkd3d_shader_free_shader_code(&text);
}
Józef Kucia
committed
}
Henri Verbeet
committed
static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv,
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)))
{
Józef Kucia
committed
FIXME("Failed to validate SPIR-V binary, ret %d.\n", ret);
FIXME("Diagnostic message: %s.\n", debugstr_a(diagnostic->error));
Józef Kucia
committed
}
spvDiagnosticDestroy(diagnostic);
spvContextDestroy(context);
}
#else
static uint32_t get_binary_to_text_options(enum vkd3d_shader_compile_option_formatting_flags formatting)
{
return 0;
}
static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_code *spirv,
enum vkd3d_shader_spirv_environment environment, uint32_t options, 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) {}
static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv,
enum vkd3d_shader_spirv_environment environment) {}
Józef Kucia
committed
Henri Verbeet
committed
static enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval,
unsigned int index)
{
switch (sysval)
{
Henri Verbeet
committed
case VKD3D_SHADER_SV_NONE:
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;
Henri Verbeet
committed
case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE:
return VKD3D_SIV_QUAD_U0_TESS_FACTOR + index;
Henri Verbeet
committed
case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT:
return VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR + index;
Henri Verbeet
committed
case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE:
return VKD3D_SIV_TRIANGLE_U_TESS_FACTOR + index;
Henri Verbeet
committed
case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT:
return VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR;
Henri Verbeet
committed
case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET:
Loading
Loading full blame...