2019-01-19 22:15:48 +00:00
|
|
|
|
/* RetroArch - A frontend for libretro.
|
|
|
|
|
* Copyright (C) 2010-2017 - Hans-Kristian Arntzen
|
2019-02-03 23:49:35 +00:00
|
|
|
|
*
|
2019-01-19 22:15:48 +00:00
|
|
|
|
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
|
|
|
|
* of the GNU General Public License as published by the Free Software Found-
|
|
|
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* RetroArch 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 General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License along with RetroArch.
|
|
|
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2018-01-31 00:08:36 +00:00
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <iostream>
|
2018-06-21 05:56:40 +00:00
|
|
|
|
#include <spirv_glsl.hpp>
|
2018-01-31 00:08:36 +00:00
|
|
|
|
#include <spirv_hlsl.hpp>
|
2018-06-21 05:56:40 +00:00
|
|
|
|
#include <spirv_msl.hpp>
|
2018-08-16 08:14:42 +00:00
|
|
|
|
#include <compat/strl.h>
|
2018-08-14 14:02:31 +00:00
|
|
|
|
#include <string>
|
2018-01-31 00:08:36 +00:00
|
|
|
|
#include <stdint.h>
|
2018-10-19 17:18:54 +00:00
|
|
|
|
#include <algorithm>
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
2018-02-01 14:07:12 +00:00
|
|
|
|
#include "glslang_util.h"
|
2018-01-31 00:08:36 +00:00
|
|
|
|
#include "slang_preprocess.h"
|
|
|
|
|
#include "slang_reflection.h"
|
2019-01-12 17:51:06 +00:00
|
|
|
|
#include "slang_reflection.hpp"
|
2018-01-31 00:08:36 +00:00
|
|
|
|
#include "slang_process.h"
|
|
|
|
|
|
2018-02-03 16:10:20 +00:00
|
|
|
|
#include "../../verbosity.h"
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_SPIRV_CROSS
|
2018-01-31 00:08:36 +00:00
|
|
|
|
using namespace spirv_cross;
|
2018-02-03 16:10:20 +00:00
|
|
|
|
#endif
|
2018-01-31 00:08:36 +00:00
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
template <typename P>
|
2018-04-23 12:56:02 +00:00
|
|
|
|
static bool set_unique_map(unordered_map<string, P>& m,
|
|
|
|
|
const string& name, const P& p)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
|
|
|
|
auto itr = m.find(name);
|
|
|
|
|
if (itr != end(m))
|
|
|
|
|
{
|
|
|
|
|
RARCH_ERR("[slang]: Alias \"%s\" already exists.\n", name.c_str());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m[name] = p;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-31 11:00:39 +00:00
|
|
|
|
template <typename M, typename S>
|
2018-04-23 12:56:02 +00:00
|
|
|
|
static string get_semantic_name(const unordered_map<string, M>* map,
|
|
|
|
|
S semantic, unsigned index)
|
2018-01-31 11:00:39 +00:00
|
|
|
|
{
|
|
|
|
|
for (const pair<string, M>& m : *map)
|
|
|
|
|
{
|
|
|
|
|
if (m.second.semantic == semantic && m.second.index == index)
|
|
|
|
|
return m.first;
|
|
|
|
|
}
|
|
|
|
|
return string();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static string
|
2018-04-23 12:56:02 +00:00
|
|
|
|
get_semantic_name(slang_reflection& reflection,
|
|
|
|
|
slang_semantic semantic, unsigned index)
|
2018-01-31 11:00:39 +00:00
|
|
|
|
{
|
|
|
|
|
static const char* names[] = {
|
|
|
|
|
"MVP",
|
|
|
|
|
"OutputSize",
|
|
|
|
|
"FinalViewportSize",
|
|
|
|
|
"FrameCount",
|
2019-05-24 18:46:19 +00:00
|
|
|
|
"FrameDirection",
|
2018-01-31 11:00:39 +00:00
|
|
|
|
};
|
|
|
|
|
if ((int)semantic < sizeof(names) / sizeof(*names))
|
|
|
|
|
return std::string(names[semantic]);
|
|
|
|
|
|
|
|
|
|
return get_semantic_name(reflection.semantic_map, semantic, index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static string
|
2018-04-23 12:56:02 +00:00
|
|
|
|
get_semantic_name(slang_reflection& reflection,
|
|
|
|
|
slang_texture_semantic semantic, unsigned index)
|
2018-01-31 11:00:39 +00:00
|
|
|
|
{
|
|
|
|
|
static const char* names[] = {
|
|
|
|
|
"Original", "Source", "OriginalHistory", "PassOutput", "PassFeedback",
|
|
|
|
|
};
|
|
|
|
|
if ((int)semantic < (int)SLANG_TEXTURE_SEMANTIC_ORIGINAL_HISTORY)
|
|
|
|
|
return std::string(names[semantic]);
|
|
|
|
|
else if ((int)semantic < sizeof(names) / sizeof(*names))
|
|
|
|
|
return std::string(names[semantic]) + to_string(index);
|
|
|
|
|
|
|
|
|
|
return get_semantic_name(reflection.texture_semantic_map, semantic, index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static string get_size_semantic_name(
|
2018-04-23 12:56:02 +00:00
|
|
|
|
slang_reflection& reflection,
|
|
|
|
|
slang_texture_semantic semantic, unsigned index)
|
2018-01-31 11:00:39 +00:00
|
|
|
|
{
|
|
|
|
|
static const char* names[] = {
|
|
|
|
|
"OriginalSize", "SourceSize", "OriginalHistorySize", "PassOutputSize", "PassFeedbackSize",
|
|
|
|
|
};
|
|
|
|
|
if ((int)semantic < (int)SLANG_TEXTURE_SEMANTIC_ORIGINAL_HISTORY)
|
|
|
|
|
return std::string(names[semantic]);
|
|
|
|
|
if ((int)semantic < sizeof(names) / sizeof(*names))
|
|
|
|
|
return std::string(names[semantic]) + to_string(index);
|
|
|
|
|
|
|
|
|
|
return get_semantic_name(reflection.texture_semantic_uniform_map, semantic, index);
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-31 00:08:36 +00:00
|
|
|
|
static bool slang_process_reflection(
|
|
|
|
|
const Compiler* vs_compiler,
|
|
|
|
|
const Compiler* ps_compiler,
|
|
|
|
|
const ShaderResources& vs_resources,
|
|
|
|
|
const ShaderResources& ps_resources,
|
|
|
|
|
video_shader* shader_info,
|
|
|
|
|
unsigned pass_number,
|
2018-02-03 16:22:47 +00:00
|
|
|
|
const semantics_map_t* map,
|
2018-01-31 00:08:36 +00:00
|
|
|
|
pass_semantics_t* out)
|
|
|
|
|
{
|
2018-04-21 06:47:09 +00:00
|
|
|
|
int semantic;
|
|
|
|
|
unsigned i;
|
2018-04-23 12:56:02 +00:00
|
|
|
|
vector<texture_sem_t> textures;
|
|
|
|
|
vector<uniform_sem_t> uniforms[SLANG_CBUFFER_MAX];
|
2018-01-31 00:08:36 +00:00
|
|
|
|
unordered_map<string, slang_texture_semantic_map> texture_semantic_map;
|
|
|
|
|
unordered_map<string, slang_texture_semantic_map> texture_semantic_uniform_map;
|
|
|
|
|
|
2018-04-21 06:47:09 +00:00
|
|
|
|
for (i = 0; i <= pass_number; i++)
|
2018-02-01 19:10:07 +00:00
|
|
|
|
{
|
2018-02-01 21:22:56 +00:00
|
|
|
|
if (!*shader_info->pass[i].alias)
|
2018-02-01 19:10:07 +00:00
|
|
|
|
continue;
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
2018-02-01 19:10:07 +00:00
|
|
|
|
string name = shader_info->pass[i].alias;
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
2018-02-01 19:10:07 +00:00
|
|
|
|
if (!set_unique_map(
|
|
|
|
|
texture_semantic_map, name,
|
2019-02-03 23:49:35 +00:00
|
|
|
|
slang_texture_semantic_map{
|
2018-04-23 12:56:02 +00:00
|
|
|
|
SLANG_TEXTURE_SEMANTIC_PASS_OUTPUT, i }))
|
2018-02-01 19:10:07 +00:00
|
|
|
|
return false;
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
2018-02-01 19:10:07 +00:00
|
|
|
|
if (!set_unique_map(
|
|
|
|
|
texture_semantic_uniform_map, name + "Size",
|
2019-02-03 23:49:35 +00:00
|
|
|
|
slang_texture_semantic_map{
|
2018-04-23 12:56:02 +00:00
|
|
|
|
SLANG_TEXTURE_SEMANTIC_PASS_OUTPUT, i }))
|
2018-02-01 19:10:07 +00:00
|
|
|
|
return false;
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
2018-02-01 19:10:07 +00:00
|
|
|
|
if (!set_unique_map(
|
|
|
|
|
texture_semantic_map, name + "Feedback",
|
2019-02-03 23:49:35 +00:00
|
|
|
|
slang_texture_semantic_map{
|
2018-04-23 12:56:02 +00:00
|
|
|
|
SLANG_TEXTURE_SEMANTIC_PASS_FEEDBACK, i }))
|
2018-02-01 19:10:07 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (!set_unique_map(
|
|
|
|
|
texture_semantic_uniform_map, name + "FeedbackSize",
|
2019-02-03 23:49:35 +00:00
|
|
|
|
slang_texture_semantic_map{
|
2018-04-23 12:56:02 +00:00
|
|
|
|
SLANG_TEXTURE_SEMANTIC_PASS_FEEDBACK, i }))
|
2018-02-01 19:10:07 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
2018-04-21 06:47:09 +00:00
|
|
|
|
for (i = 0; i < shader_info->luts; i++)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
|
|
|
|
if (!set_unique_map(
|
|
|
|
|
texture_semantic_map, shader_info->lut[i].id,
|
2019-02-03 23:49:35 +00:00
|
|
|
|
slang_texture_semantic_map{
|
2018-04-23 12:56:02 +00:00
|
|
|
|
SLANG_TEXTURE_SEMANTIC_USER, i }))
|
2018-01-31 00:08:36 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (!set_unique_map(
|
2018-04-23 12:56:02 +00:00
|
|
|
|
texture_semantic_uniform_map,
|
|
|
|
|
string(shader_info->lut[i].id) + "Size",
|
2019-02-03 23:49:35 +00:00
|
|
|
|
slang_texture_semantic_map{
|
2018-04-23 12:56:02 +00:00
|
|
|
|
SLANG_TEXTURE_SEMANTIC_USER, i }))
|
2018-01-31 00:08:36 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-31 11:00:39 +00:00
|
|
|
|
unordered_map<string, slang_semantic_map> uniform_semantic_map;
|
2018-02-01 19:10:07 +00:00
|
|
|
|
|
2018-04-21 06:47:09 +00:00
|
|
|
|
for (i = 0; i < shader_info->num_parameters; i++)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
2018-02-11 21:56:37 +00:00
|
|
|
|
if (!set_unique_map(
|
|
|
|
|
uniform_semantic_map, shader_info->parameters[i].id,
|
|
|
|
|
slang_semantic_map{ SLANG_SEMANTIC_FLOAT_PARAMETER, i }))
|
|
|
|
|
return false;
|
2018-01-31 00:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
slang_reflection sl_reflection;
|
|
|
|
|
sl_reflection.pass_number = pass_number;
|
|
|
|
|
sl_reflection.texture_semantic_map = &texture_semantic_map;
|
|
|
|
|
sl_reflection.texture_semantic_uniform_map = &texture_semantic_uniform_map;
|
2018-01-31 11:00:39 +00:00
|
|
|
|
sl_reflection.semantic_map = &uniform_semantic_map;
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
2018-04-23 12:56:02 +00:00
|
|
|
|
if (!slang_reflect(*vs_compiler, *ps_compiler,
|
|
|
|
|
vs_resources, ps_resources, &sl_reflection))
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
2018-04-23 12:56:02 +00:00
|
|
|
|
RARCH_ERR("[slang]: Failed to reflect SPIR-V."
|
|
|
|
|
" Resource usage is inconsistent with "
|
2018-01-31 00:08:36 +00:00
|
|
|
|
"expectations.\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out->cbuffers[SLANG_CBUFFER_UBO].stage_mask = sl_reflection.ubo_stage_mask;
|
|
|
|
|
out->cbuffers[SLANG_CBUFFER_UBO].binding = sl_reflection.ubo_binding;
|
2018-06-21 05:52:01 +00:00
|
|
|
|
out->cbuffers[SLANG_CBUFFER_UBO].size = (unsigned)((sl_reflection.ubo_size + 0xF) & ~0xF);
|
2018-01-31 00:08:36 +00:00
|
|
|
|
out->cbuffers[SLANG_CBUFFER_PC].stage_mask = sl_reflection.push_constant_stage_mask;
|
|
|
|
|
out->cbuffers[SLANG_CBUFFER_PC].binding = sl_reflection.ubo_binding ? 0 : 1;
|
2018-06-21 05:52:01 +00:00
|
|
|
|
out->cbuffers[SLANG_CBUFFER_PC].size = (unsigned)((sl_reflection.push_constant_size + 0xF) & ~0xF);
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
2018-04-21 06:47:09 +00:00
|
|
|
|
for (semantic = 0; semantic < SLANG_NUM_BASE_SEMANTICS; semantic++)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
2018-02-03 16:22:47 +00:00
|
|
|
|
slang_semantic_meta& src = sl_reflection.semantics[semantic];
|
2018-02-01 16:48:27 +00:00
|
|
|
|
if (src.push_constant || src.uniform)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
2018-02-03 16:22:47 +00:00
|
|
|
|
uniform_sem_t uniform = { map->uniforms[semantic],
|
2019-02-03 23:49:35 +00:00
|
|
|
|
src.num_components
|
2018-04-23 12:56:02 +00:00
|
|
|
|
* (unsigned)sizeof(float) };
|
|
|
|
|
string uniform_id = get_semantic_name(
|
|
|
|
|
sl_reflection, (slang_semantic)semantic, 0);
|
2018-02-01 16:48:27 +00:00
|
|
|
|
|
2018-08-16 08:14:42 +00:00
|
|
|
|
strlcpy(uniform.id, uniform_id.c_str(), sizeof(uniform.id));
|
2018-02-01 16:48:27 +00:00
|
|
|
|
|
|
|
|
|
if (src.push_constant)
|
|
|
|
|
{
|
2018-06-21 05:52:01 +00:00
|
|
|
|
uniform.offset = (unsigned)src.push_constant_offset;
|
2018-02-01 16:48:27 +00:00
|
|
|
|
uniforms[SLANG_CBUFFER_PC].push_back(uniform);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-06-21 05:52:01 +00:00
|
|
|
|
uniform.offset = (unsigned)src.ubo_offset;
|
2018-02-01 16:48:27 +00:00
|
|
|
|
uniforms[SLANG_CBUFFER_UBO].push_back(uniform);
|
|
|
|
|
}
|
2018-01-31 00:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-21 06:47:09 +00:00
|
|
|
|
for (i = 0; i < sl_reflection.semantic_float_parameters.size(); i++)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
2018-02-01 16:48:27 +00:00
|
|
|
|
slang_semantic_meta& src = sl_reflection.semantic_float_parameters[i];
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
2018-02-01 16:48:27 +00:00
|
|
|
|
if (src.push_constant || src.uniform)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
2019-02-03 23:49:35 +00:00
|
|
|
|
uniform_sem_t uniform = {
|
2018-04-23 12:56:02 +00:00
|
|
|
|
&shader_info->parameters[i].current, sizeof(float) };
|
2018-02-01 16:48:27 +00:00
|
|
|
|
|
2018-04-23 12:56:02 +00:00
|
|
|
|
string uniform_id = get_semantic_name(
|
|
|
|
|
sl_reflection, SLANG_SEMANTIC_FLOAT_PARAMETER, i);
|
2018-08-16 08:14:42 +00:00
|
|
|
|
strlcpy(uniform.id, uniform_id.c_str(), sizeof(uniform.id));
|
2018-02-01 16:48:27 +00:00
|
|
|
|
|
|
|
|
|
if (src.push_constant)
|
|
|
|
|
{
|
2018-06-21 05:52:01 +00:00
|
|
|
|
uniform.offset = (unsigned)src.push_constant_offset;
|
2018-02-01 16:48:27 +00:00
|
|
|
|
uniforms[SLANG_CBUFFER_PC].push_back(uniform);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-06-21 05:52:01 +00:00
|
|
|
|
uniform.offset = (unsigned)src.ubo_offset;
|
2018-02-01 16:48:27 +00:00
|
|
|
|
uniforms[SLANG_CBUFFER_UBO].push_back(uniform);
|
|
|
|
|
}
|
2018-01-31 00:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-21 06:47:09 +00:00
|
|
|
|
for (semantic = 0; semantic < SLANG_NUM_TEXTURE_SEMANTICS; semantic++)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
2018-04-21 06:47:09 +00:00
|
|
|
|
unsigned index;
|
|
|
|
|
|
2019-02-03 23:49:35 +00:00
|
|
|
|
for (index = 0; index <
|
2018-04-23 12:56:02 +00:00
|
|
|
|
sl_reflection.semantic_textures[semantic].size(); index++)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
2019-02-03 23:49:35 +00:00
|
|
|
|
slang_texture_semantic_meta& src =
|
2018-04-23 12:56:02 +00:00
|
|
|
|
sl_reflection.semantic_textures[semantic][index];
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
|
|
|
|
if (src.stage_mask)
|
|
|
|
|
{
|
2018-02-03 16:22:47 +00:00
|
|
|
|
texture_sem_t texture = {
|
2018-02-11 21:56:37 +00:00
|
|
|
|
(void*)((uintptr_t)map->textures[semantic].image + index * map->textures[semantic].image_stride)
|
2018-02-03 16:22:47 +00:00
|
|
|
|
};
|
2018-02-11 21:56:37 +00:00
|
|
|
|
|
|
|
|
|
if (semantic == SLANG_TEXTURE_SEMANTIC_USER)
|
|
|
|
|
{
|
2018-04-23 12:56:02 +00:00
|
|
|
|
texture.wrap = shader_info->lut[index].wrap;
|
|
|
|
|
texture.filter = shader_info->lut[index].filter;
|
2018-02-11 21:56:37 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-04-23 12:56:02 +00:00
|
|
|
|
texture.wrap = shader_info->pass[pass_number].wrap;
|
|
|
|
|
texture.filter = shader_info->pass[pass_number].filter;
|
2018-02-11 21:56:37 +00:00
|
|
|
|
}
|
2018-02-03 16:22:47 +00:00
|
|
|
|
texture.stage_mask = src.stage_mask;
|
|
|
|
|
texture.binding = src.binding;
|
2018-04-23 12:56:02 +00:00
|
|
|
|
string id = get_semantic_name(
|
|
|
|
|
sl_reflection, (slang_texture_semantic)semantic, index);
|
2018-01-31 11:00:39 +00:00
|
|
|
|
|
2018-08-16 08:14:42 +00:00
|
|
|
|
strlcpy(texture.id, id.c_str(), sizeof(texture.id));
|
2018-01-31 11:00:39 +00:00
|
|
|
|
|
2018-01-31 00:08:36 +00:00
|
|
|
|
textures.push_back(texture);
|
2018-02-02 18:57:45 +00:00
|
|
|
|
|
2018-02-03 16:22:47 +00:00
|
|
|
|
if (semantic == SLANG_TEXTURE_SEMANTIC_PASS_FEEDBACK)
|
|
|
|
|
shader_info->pass[index].feedback = true;
|
2018-02-03 12:29:00 +00:00
|
|
|
|
|
2018-02-03 16:22:47 +00:00
|
|
|
|
if (semantic == SLANG_TEXTURE_SEMANTIC_ORIGINAL_HISTORY &&
|
2018-05-03 12:52:37 +00:00
|
|
|
|
(unsigned)shader_info->history_size < index)
|
2018-02-03 16:22:47 +00:00
|
|
|
|
shader_info->history_size = index;
|
2018-02-01 16:48:27 +00:00
|
|
|
|
}
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
2018-02-01 16:48:27 +00:00
|
|
|
|
if (src.push_constant || src.uniform)
|
|
|
|
|
{
|
2018-02-03 16:22:47 +00:00
|
|
|
|
uniform_sem_t uniform = {
|
2019-02-03 23:49:35 +00:00
|
|
|
|
(void*)((uintptr_t)map->textures[semantic].size
|
2018-04-23 12:56:02 +00:00
|
|
|
|
+ index * map->textures[semantic].size_stride),
|
2018-02-03 16:22:47 +00:00
|
|
|
|
4 * sizeof(float)
|
|
|
|
|
};
|
2018-01-31 11:00:39 +00:00
|
|
|
|
|
|
|
|
|
string uniform_id =
|
2018-04-23 12:56:02 +00:00
|
|
|
|
get_size_semantic_name(
|
|
|
|
|
sl_reflection,
|
|
|
|
|
(slang_texture_semantic)semantic, index);
|
2018-01-31 11:00:39 +00:00
|
|
|
|
|
2018-08-16 08:14:42 +00:00
|
|
|
|
strlcpy(uniform.id, uniform_id.c_str(), sizeof(uniform.id));
|
2018-01-31 11:00:39 +00:00
|
|
|
|
|
2018-01-31 00:08:36 +00:00
|
|
|
|
if (src.push_constant)
|
|
|
|
|
{
|
2018-06-21 05:52:01 +00:00
|
|
|
|
uniform.offset = (unsigned)src.push_constant_offset;
|
2018-01-31 00:08:36 +00:00
|
|
|
|
uniforms[SLANG_CBUFFER_PC].push_back(uniform);
|
|
|
|
|
}
|
2018-02-01 16:48:27 +00:00
|
|
|
|
else
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
2018-06-21 05:52:01 +00:00
|
|
|
|
uniform.offset = (unsigned)src.ubo_offset;
|
2018-01-31 00:08:36 +00:00
|
|
|
|
uniforms[SLANG_CBUFFER_UBO].push_back(uniform);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-21 05:52:01 +00:00
|
|
|
|
out->texture_count = (int)textures.size();
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
|
|
|
|
textures.push_back({ NULL });
|
2018-04-23 12:56:02 +00:00
|
|
|
|
out->textures = (texture_sem_t*)
|
|
|
|
|
malloc(textures.size() * sizeof(*textures.data()));
|
|
|
|
|
memcpy(out->textures, textures.data(),
|
|
|
|
|
textures.size() * sizeof(*textures.data()));
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
2018-04-21 06:47:09 +00:00
|
|
|
|
for (i = 0; i < SLANG_CBUFFER_MAX; i++)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
|
|
|
|
if (uniforms[i].empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
2018-06-21 05:52:01 +00:00
|
|
|
|
out->cbuffers[i].uniform_count = (int)uniforms[i].size();
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
|
|
|
|
uniforms[i].push_back({ NULL });
|
|
|
|
|
out->cbuffers[i].uniforms =
|
2018-04-23 12:56:02 +00:00
|
|
|
|
(uniform_sem_t*)
|
|
|
|
|
malloc(uniforms[i].size() * sizeof(*uniforms[i].data()));
|
|
|
|
|
|
2018-01-31 00:08:36 +00:00
|
|
|
|
memcpy(
|
|
|
|
|
out->cbuffers[i].uniforms, uniforms[i].data(),
|
|
|
|
|
uniforms[i].size() * sizeof(*uniforms[i].data()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool slang_process(
|
|
|
|
|
video_shader* shader_info,
|
|
|
|
|
unsigned pass_number,
|
|
|
|
|
enum rarch_shader_type dst_type,
|
|
|
|
|
unsigned version,
|
|
|
|
|
const semantics_map_t* semantics_map,
|
|
|
|
|
pass_semantics_t* out)
|
|
|
|
|
{
|
2018-04-23 12:56:02 +00:00
|
|
|
|
glslang_output output;
|
2018-01-31 00:08:36 +00:00
|
|
|
|
Compiler* vs_compiler = NULL;
|
|
|
|
|
Compiler* ps_compiler = NULL;
|
|
|
|
|
video_shader_pass& pass = shader_info->pass[pass_number];
|
|
|
|
|
|
|
|
|
|
if (!glslang_compile_shader(pass.source.path, &output))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (!slang_preprocess_parse_parameters(output.meta, shader_info))
|
|
|
|
|
return false;
|
|
|
|
|
|
2018-02-03 22:35:04 +00:00
|
|
|
|
if (!*pass.alias && !output.meta.name.empty())
|
2018-08-16 08:14:42 +00:00
|
|
|
|
strlcpy(pass.alias, output.meta.name.c_str(), sizeof(pass.alias) - 1);
|
2018-02-01 19:10:07 +00:00
|
|
|
|
|
2018-02-01 14:07:12 +00:00
|
|
|
|
out->format = output.meta.rt_format;
|
|
|
|
|
|
|
|
|
|
if (out->format == SLANG_FORMAT_UNKNOWN)
|
|
|
|
|
{
|
|
|
|
|
if (pass.fbo.srgb_fbo)
|
|
|
|
|
out->format = SLANG_FORMAT_R8G8B8A8_SRGB;
|
|
|
|
|
else if (pass.fbo.fp_fbo)
|
|
|
|
|
out->format = SLANG_FORMAT_R16G16B16A16_SFLOAT;
|
|
|
|
|
else
|
|
|
|
|
out->format = SLANG_FORMAT_R8G8B8A8_UNORM;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-31 00:08:36 +00:00
|
|
|
|
pass.source.string.vertex = NULL;
|
|
|
|
|
pass.source.string.fragment = NULL;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
ShaderResources vs_resources;
|
|
|
|
|
ShaderResources ps_resources;
|
|
|
|
|
string vs_code;
|
|
|
|
|
string ps_code;
|
|
|
|
|
|
2018-06-21 04:29:53 +00:00
|
|
|
|
switch (dst_type)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
2018-06-21 04:29:53 +00:00
|
|
|
|
case RARCH_SHADER_HLSL:
|
|
|
|
|
case RARCH_SHADER_CG:
|
2018-06-25 19:51:05 +00:00
|
|
|
|
#ifdef ENABLE_HLSL
|
2018-06-21 04:29:53 +00:00
|
|
|
|
vs_compiler = new CompilerHLSL(output.vertex);
|
|
|
|
|
ps_compiler = new CompilerHLSL(output.fragment);
|
2018-06-25 19:51:05 +00:00
|
|
|
|
#endif
|
2018-06-21 04:29:53 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case RARCH_SHADER_METAL:
|
|
|
|
|
vs_compiler = new CompilerMSL(output.vertex);
|
|
|
|
|
ps_compiler = new CompilerMSL(output.fragment);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
vs_compiler = new CompilerGLSL(output.vertex);
|
|
|
|
|
ps_compiler = new CompilerGLSL(output.fragment);
|
|
|
|
|
break;
|
2018-01-31 00:08:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vs_resources = vs_compiler->get_shader_resources();
|
|
|
|
|
ps_resources = ps_compiler->get_shader_resources();
|
|
|
|
|
|
2018-02-01 21:22:56 +00:00
|
|
|
|
if (!vs_resources.uniform_buffers.empty())
|
2018-04-23 12:56:02 +00:00
|
|
|
|
vs_compiler->set_decoration(
|
|
|
|
|
vs_resources.uniform_buffers[0].id, spv::DecorationBinding, 0);
|
2018-02-01 21:22:56 +00:00
|
|
|
|
if (!ps_resources.uniform_buffers.empty())
|
2018-04-23 12:56:02 +00:00
|
|
|
|
ps_compiler->set_decoration(
|
|
|
|
|
ps_resources.uniform_buffers[0].id, spv::DecorationBinding, 0);
|
2018-02-01 20:45:36 +00:00
|
|
|
|
|
2018-02-01 21:22:56 +00:00
|
|
|
|
if (!vs_resources.push_constant_buffers.empty())
|
|
|
|
|
vs_compiler->set_decoration(
|
|
|
|
|
vs_resources.push_constant_buffers[0].id, spv::DecorationBinding, 1);
|
|
|
|
|
if (!ps_resources.push_constant_buffers.empty())
|
|
|
|
|
ps_compiler->set_decoration(
|
|
|
|
|
ps_resources.push_constant_buffers[0].id, spv::DecorationBinding, 1);
|
2018-02-01 20:45:36 +00:00
|
|
|
|
|
2018-06-26 11:18:17 +00:00
|
|
|
|
#ifdef ENABLE_HLSL
|
2018-01-31 00:08:36 +00:00
|
|
|
|
if (dst_type == RARCH_SHADER_HLSL || dst_type == RARCH_SHADER_CG)
|
|
|
|
|
{
|
|
|
|
|
CompilerHLSL::Options options;
|
|
|
|
|
CompilerHLSL* vs = (CompilerHLSL*)vs_compiler;
|
|
|
|
|
CompilerHLSL* ps = (CompilerHLSL*)ps_compiler;
|
|
|
|
|
options.shader_model = version;
|
2018-06-21 05:52:01 +00:00
|
|
|
|
vs->set_hlsl_options(options);
|
|
|
|
|
ps->set_hlsl_options(options);
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
2018-04-23 12:56:02 +00:00
|
|
|
|
#if 0
|
2018-03-06 03:12:58 +00:00
|
|
|
|
CompilerGLSL::Options glsl_options;
|
|
|
|
|
glsl_options.vertex.flip_vert_y = true;
|
|
|
|
|
((CompilerGLSL*)vs)->set_options(glsl_options);
|
|
|
|
|
((CompilerGLSL*)ps)->set_options(glsl_options);
|
2018-04-23 12:56:02 +00:00
|
|
|
|
#endif
|
2018-03-06 03:12:58 +00:00
|
|
|
|
|
2018-01-31 00:08:36 +00:00
|
|
|
|
/* not exactly a vertex attribute but this remaps
|
|
|
|
|
* float2 FragCoord :TEXCOORD# to float4 FragCoord : SV_POSITION */
|
|
|
|
|
std::vector<HLSLVertexAttributeRemap> ps_attrib_remap;
|
2018-02-01 19:10:07 +00:00
|
|
|
|
|
2018-02-03 12:29:00 +00:00
|
|
|
|
VariableTypeRemapCallback ps_var_remap_cb =
|
|
|
|
|
[&](const SPIRType& type, const std::string& var_name, std::string& name_of_type) {
|
|
|
|
|
if (var_name == "FragCoord")
|
|
|
|
|
name_of_type = "float4";
|
|
|
|
|
};
|
2018-02-02 00:50:18 +00:00
|
|
|
|
for (Resource& resource : ps_resources.stage_inputs)
|
|
|
|
|
{
|
|
|
|
|
if (ps->get_name(resource.id) == "FragCoord")
|
|
|
|
|
{
|
|
|
|
|
uint32_t location = ps->get_decoration(resource.id, spv::DecorationLocation);
|
|
|
|
|
ps_attrib_remap.push_back({ location, "SV_Position" });
|
|
|
|
|
ps->set_variable_type_remap_callback(ps_var_remap_cb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-02 11:32:31 +00:00
|
|
|
|
vs_code = vs->compile();
|
2018-01-31 00:08:36 +00:00
|
|
|
|
ps_code = ps->compile(ps_attrib_remap);
|
|
|
|
|
}
|
2018-06-26 11:18:17 +00:00
|
|
|
|
else
|
|
|
|
|
#endif
|
2019-06-04 19:52:58 +00:00
|
|
|
|
if (dst_type == RARCH_SHADER_METAL)
|
2018-06-21 04:29:53 +00:00
|
|
|
|
{
|
|
|
|
|
CompilerMSL::Options options;
|
|
|
|
|
CompilerMSL* vs = (CompilerMSL*)vs_compiler;
|
|
|
|
|
CompilerMSL* ps = (CompilerMSL*)ps_compiler;
|
|
|
|
|
options.msl_version = version;
|
|
|
|
|
vs->set_msl_options(options);
|
|
|
|
|
ps->set_msl_options(options);
|
|
|
|
|
|
|
|
|
|
std::vector<MSLVertexAttr> vs_attrib_remap;
|
|
|
|
|
std::vector<MSLResourceBinding> vs_res;
|
|
|
|
|
|
|
|
|
|
for (Resource& resource : vs_resources.stage_inputs)
|
|
|
|
|
{
|
|
|
|
|
std::string name = vs->get_name(resource.id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vs_code = vs->compile();
|
|
|
|
|
ps_code = ps->compile();
|
|
|
|
|
}
|
2019-06-04 19:52:58 +00:00
|
|
|
|
else if (dst_type == RARCH_SHADER_GLSL)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
|
|
|
|
CompilerGLSL::Options options;
|
|
|
|
|
CompilerGLSL* vs = (CompilerGLSL*)vs_compiler;
|
|
|
|
|
CompilerGLSL* ps = (CompilerGLSL*)ps_compiler;
|
|
|
|
|
options.version = version;
|
2018-06-21 05:34:27 +00:00
|
|
|
|
ps->set_common_options(options);
|
|
|
|
|
vs->set_common_options(options);
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
|
|
|
|
vs_code = vs->compile();
|
|
|
|
|
ps_code = ps->compile();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
goto error;
|
|
|
|
|
|
2018-01-31 18:36:31 +00:00
|
|
|
|
pass.source.string.vertex = strdup(vs_code.c_str());
|
|
|
|
|
pass.source.string.fragment = strdup(ps_code.c_str());
|
2018-01-31 00:08:36 +00:00
|
|
|
|
|
|
|
|
|
if (!slang_process_reflection(
|
2018-04-23 12:56:02 +00:00
|
|
|
|
vs_compiler, ps_compiler,
|
|
|
|
|
vs_resources, ps_resources, shader_info, pass_number,
|
2018-01-31 00:08:36 +00:00
|
|
|
|
semantics_map, out))
|
|
|
|
|
goto error;
|
|
|
|
|
|
2018-04-23 12:56:02 +00:00
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
2018-01-31 00:08:36 +00:00
|
|
|
|
{
|
2018-01-31 18:36:31 +00:00
|
|
|
|
RARCH_ERR("[slang]: SPIRV-Cross threw exception: %s.\n", e.what());
|
2018-01-31 00:08:36 +00:00
|
|
|
|
goto error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete vs_compiler;
|
|
|
|
|
delete ps_compiler;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
error:
|
|
|
|
|
free(pass.source.string.vertex);
|
|
|
|
|
free(pass.source.string.fragment);
|
|
|
|
|
|
|
|
|
|
pass.source.string.vertex = NULL;
|
|
|
|
|
pass.source.string.fragment = NULL;
|
|
|
|
|
|
|
|
|
|
delete vs_compiler;
|
|
|
|
|
delete ps_compiler;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|