mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-23 04:30:10 +00:00
renderer_vulkan: SPIRV TrivialVertexShader generation
Seems to work just fine when hardware-shaders are disabled!
This commit is contained in:
parent
99e83a4ab8
commit
3fb681bcc6
@ -89,8 +89,7 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
|
|||||||
DescriptorSetProvider{instance, pool, TEXTURE_BINDINGS},
|
DescriptorSetProvider{instance, pool, TEXTURE_BINDINGS},
|
||||||
DescriptorSetProvider{instance, pool, SHADOW_BINDINGS}},
|
DescriptorSetProvider{instance, pool, SHADOW_BINDINGS}},
|
||||||
trivial_vertex_shader{
|
trivial_vertex_shader{
|
||||||
instance, vk::ShaderStageFlagBits::eVertex,
|
instance, SPIRV::GenerateTrivialVertexShader(instance.IsShaderClipDistanceSupported())} {
|
||||||
GLSL::GenerateTrivialVertexShader(instance.IsShaderClipDistanceSupported(), true)} {
|
|
||||||
profile = Pica::Shader::Profile{
|
profile = Pica::Shader::Profile{
|
||||||
.has_separable_shaders = true,
|
.has_separable_shaders = true,
|
||||||
.has_clip_planes = instance.IsShaderClipDistanceSupported(),
|
.has_clip_planes = instance.IsShaderClipDistanceSupported(),
|
||||||
|
@ -13,8 +13,7 @@ namespace Pica::Shader::Generator::SPIRV {
|
|||||||
|
|
||||||
constexpr u32 SPIRV_VERSION_1_3 = 0x00010300;
|
constexpr u32 SPIRV_VERSION_1_3 = 0x00010300;
|
||||||
|
|
||||||
VertexModule::VertexModule(const PicaVSConfig& config_, const Profile& profile_)
|
VertexModule::VertexModule() : Sirit::Module{SPIRV_VERSION_1_3} {
|
||||||
: Sirit::Module{SPIRV_VERSION_1_3}, config{config_}, profile{profile_} {
|
|
||||||
DefineArithmeticTypes();
|
DefineArithmeticTypes();
|
||||||
DefineInterface();
|
DefineInterface();
|
||||||
DefineEntryPoint();
|
DefineEntryPoint();
|
||||||
@ -22,25 +21,19 @@ VertexModule::VertexModule(const PicaVSConfig& config_, const Profile& profile_)
|
|||||||
|
|
||||||
VertexModule::~VertexModule() = default;
|
VertexModule::~VertexModule() = default;
|
||||||
|
|
||||||
void VertexModule::Generate() {
|
|
||||||
AddLabel(OpLabel());
|
|
||||||
OpReturn();
|
|
||||||
OpFunctionEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VertexModule::DefineArithmeticTypes() {
|
void VertexModule::DefineArithmeticTypes() {
|
||||||
void_id = Name(TypeVoid(), "void_id");
|
ids.void_id = Name(TypeVoid(), "void_id");
|
||||||
bool_id = Name(TypeBool(), "bool_id");
|
ids.bool_id = Name(TypeBool(), "bool_id");
|
||||||
f32_id = Name(TypeFloat(32), "f32_id");
|
ids.f32_id = Name(TypeFloat(32), "f32_id");
|
||||||
i32_id = Name(TypeSInt(32), "i32_id");
|
ids.i32_id = Name(TypeSInt(32), "i32_id");
|
||||||
u32_id = Name(TypeUInt(32), "u32_id");
|
ids.u32_id = Name(TypeUInt(32), "u32_id");
|
||||||
|
|
||||||
for (u32 size = 2; size <= 4; size++) {
|
for (u32 size = 2; size <= 4; size++) {
|
||||||
const u32 i = size - 2;
|
const u32 i = size - 2;
|
||||||
vec_ids.ids[i] = Name(TypeVector(f32_id, size), fmt::format("vec{}_id", size));
|
ids.bvec_ids.ids[i] = Name(TypeVector(ids.bool_id, size), fmt::format("bvec{}_id", size));
|
||||||
ivec_ids.ids[i] = Name(TypeVector(i32_id, size), fmt::format("ivec{}_id", size));
|
ids.vec_ids.ids[i] = Name(TypeVector(ids.f32_id, size), fmt::format("vec{}_id", size));
|
||||||
uvec_ids.ids[i] = Name(TypeVector(u32_id, size), fmt::format("uvec{}_id", size));
|
ids.ivec_ids.ids[i] = Name(TypeVector(ids.i32_id, size), fmt::format("ivec{}_id", size));
|
||||||
bvec_ids.ids[i] = Name(TypeVector(bool_id, size), fmt::format("bvec{}_id", size));
|
ids.uvec_ids.ids[i] = Name(TypeVector(ids.u32_id, size), fmt::format("uvec{}_id", size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,17 +44,104 @@ void VertexModule::DefineEntryPoint() {
|
|||||||
const Id main_type{TypeFunction(TypeVoid())};
|
const Id main_type{TypeFunction(TypeVoid())};
|
||||||
const Id main_func{OpFunction(TypeVoid(), spv::FunctionControlMask::MaskNone, main_type)};
|
const Id main_func{OpFunction(TypeVoid(), spv::FunctionControlMask::MaskNone, main_type)};
|
||||||
|
|
||||||
AddEntryPoint(spv::ExecutionModel::Vertex, main_func, "main");
|
const Id interface_ids[] = {
|
||||||
|
ids.vert_in_position_id, ids.vert_in_color_id, ids.vert_in_texcoord0_id,
|
||||||
|
ids.vert_in_texcoord1_id, ids.vert_in_texcoord2_id, ids.vert_in_texcoord0_w_id,
|
||||||
|
ids.vert_in_normquat_id, ids.vert_in_view_id, ids.gl_position,
|
||||||
|
ids.vert_out_color_id, ids.vert_out_texcoord0_id, ids.vert_out_texcoord1_id,
|
||||||
|
ids.vert_out_texcoord2_id, ids.vert_out_texcoord0_w_id, ids.vert_out_normquat_id,
|
||||||
|
ids.vert_out_view_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
AddEntryPoint(spv::ExecutionModel::Vertex, main_func, "main", interface_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexModule::DefineInterface() {
|
void VertexModule::DefineInterface() {
|
||||||
// Define interface block
|
// Define interface block
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
ids.vert_in_position_id =
|
||||||
|
Name(DefineInput(ids.vec_ids.Get(4), ATTRIBUTE_POSITION), "vert_in_position_id");
|
||||||
|
ids.vert_in_color_id =
|
||||||
|
Name(DefineInput(ids.vec_ids.Get(4), ATTRIBUTE_COLOR), "vert_in_color_id");
|
||||||
|
ids.vert_in_texcoord0_id =
|
||||||
|
Name(DefineInput(ids.vec_ids.Get(2), ATTRIBUTE_TEXCOORD0), "vert_in_texcoord0_id");
|
||||||
|
ids.vert_in_texcoord1_id =
|
||||||
|
Name(DefineInput(ids.vec_ids.Get(2), ATTRIBUTE_TEXCOORD1), "vert_in_texcoord1_id");
|
||||||
|
ids.vert_in_texcoord2_id =
|
||||||
|
Name(DefineInput(ids.vec_ids.Get(2), ATTRIBUTE_TEXCOORD2), "vert_in_texcoord2_id");
|
||||||
|
ids.vert_in_texcoord0_w_id =
|
||||||
|
Name(DefineInput(ids.f32_id, ATTRIBUTE_TEXCOORD0_W), "vert_in_texcoord0_w_id");
|
||||||
|
ids.vert_in_normquat_id =
|
||||||
|
Name(DefineInput(ids.vec_ids.Get(4), ATTRIBUTE_NORMQUAT), "vert_in_normquat_id");
|
||||||
|
ids.vert_in_view_id = Name(DefineInput(ids.vec_ids.Get(3), ATTRIBUTE_VIEW), "vert_in_view_id");
|
||||||
|
|
||||||
|
// Outputs
|
||||||
|
ids.vert_out_color_id =
|
||||||
|
Name(DefineOutput(ids.vec_ids.Get(4), ATTRIBUTE_COLOR), "vert_out_color_id");
|
||||||
|
ids.vert_out_texcoord0_id =
|
||||||
|
Name(DefineOutput(ids.vec_ids.Get(2), ATTRIBUTE_TEXCOORD0), "vert_out_texcoord0_id");
|
||||||
|
ids.vert_out_texcoord1_id =
|
||||||
|
Name(DefineOutput(ids.vec_ids.Get(2), ATTRIBUTE_TEXCOORD1), "vert_out_texcoord1_id");
|
||||||
|
ids.vert_out_texcoord2_id =
|
||||||
|
Name(DefineOutput(ids.vec_ids.Get(2), ATTRIBUTE_TEXCOORD2), "vert_out_texcoord2_id");
|
||||||
|
ids.vert_out_texcoord0_w_id =
|
||||||
|
Name(DefineOutput(ids.f32_id, ATTRIBUTE_TEXCOORD0_W), "vert_out_texcoord0_w_id");
|
||||||
|
ids.vert_out_normquat_id =
|
||||||
|
Name(DefineOutput(ids.vec_ids.Get(4), ATTRIBUTE_NORMQUAT), "vert_out_normquat_id");
|
||||||
|
ids.vert_out_view_id =
|
||||||
|
Name(DefineOutput(ids.vec_ids.Get(3), ATTRIBUTE_VIEW), "vert_out_view_id");
|
||||||
|
|
||||||
|
// Built-ins
|
||||||
|
ids.gl_position = DefineVar(ids.vec_ids.Get(4), spv::StorageClass::Output);
|
||||||
|
Decorate(ids.gl_position, spv::Decoration::BuiltIn, spv::BuiltIn::Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexModule::Generate(Common::UniqueFunction<void, Sirit::Module&, const EmitterIDs&> proc) {
|
||||||
|
AddLabel(OpLabel());
|
||||||
|
proc(*this, ids);
|
||||||
|
OpReturn();
|
||||||
|
OpFunctionEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexModule::Generate(const PicaVSConfig& config, const Profile& profile) {
|
||||||
|
AddLabel(OpLabel());
|
||||||
|
OpReturn();
|
||||||
|
OpFunctionEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u32> GenerateTrivialVertexShader(bool use_clip_planes) {
|
||||||
|
VertexModule module;
|
||||||
|
module.Generate([](Sirit::Module& code, const VertexModule::EmitterIDs& ids) -> void {
|
||||||
|
code.OpStore(ids.gl_position, code.OpLoad(ids.vec_ids.Get(4), ids.vert_in_position_id));
|
||||||
|
|
||||||
|
// Negate Z
|
||||||
|
const Id pos_z = code.OpAccessChain(code.TypePointer(spv::StorageClass::Output, ids.f32_id),
|
||||||
|
ids.gl_position, code.Constant(ids.u32_id, 2));
|
||||||
|
|
||||||
|
code.OpStore(pos_z, code.OpFNegate(ids.f32_id, code.OpLoad(ids.f32_id, pos_z)));
|
||||||
|
|
||||||
|
// Pass-through
|
||||||
|
code.OpStore(ids.vert_out_color_id, code.OpLoad(ids.vec_ids.Get(4), ids.vert_in_color_id));
|
||||||
|
code.OpStore(ids.vert_out_texcoord0_id,
|
||||||
|
code.OpLoad(ids.vec_ids.Get(2), ids.vert_in_texcoord0_id));
|
||||||
|
code.OpStore(ids.vert_out_texcoord1_id,
|
||||||
|
code.OpLoad(ids.vec_ids.Get(2), ids.vert_in_texcoord1_id));
|
||||||
|
code.OpStore(ids.vert_out_texcoord2_id,
|
||||||
|
code.OpLoad(ids.vec_ids.Get(2), ids.vert_in_texcoord2_id));
|
||||||
|
code.OpStore(ids.vert_out_texcoord0_w_id,
|
||||||
|
code.OpLoad(ids.f32_id, ids.vert_in_texcoord0_w_id));
|
||||||
|
code.OpStore(ids.vert_out_normquat_id,
|
||||||
|
code.OpLoad(ids.vec_ids.Get(4), ids.vert_in_normquat_id));
|
||||||
|
code.OpStore(ids.vert_out_view_id, code.OpLoad(ids.vec_ids.Get(3), ids.vert_in_view_id));
|
||||||
|
});
|
||||||
|
return module.Assemble();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u32> GenerateVertexShader(const ShaderSetup& setup, const PicaVSConfig& config,
|
std::vector<u32> GenerateVertexShader(const ShaderSetup& setup, const PicaVSConfig& config,
|
||||||
const Profile& profile) {
|
const Profile& profile) {
|
||||||
VertexModule module(config, profile);
|
VertexModule module;
|
||||||
module.Generate();
|
module.Generate(config, profile);
|
||||||
return module.Assemble();
|
return module.Assemble();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include <sirit/sirit.h>
|
#include <sirit/sirit.h>
|
||||||
|
|
||||||
|
#include "common/unique_function.h"
|
||||||
|
|
||||||
namespace Pica {
|
namespace Pica {
|
||||||
struct ShaderSetup;
|
struct ShaderSetup;
|
||||||
}
|
}
|
||||||
@ -35,21 +37,37 @@ struct VectorIds {
|
|||||||
class VertexModule : public Sirit::Module {
|
class VertexModule : public Sirit::Module {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit VertexModule(const PicaVSConfig& config, const Profile& profile);
|
explicit VertexModule();
|
||||||
~VertexModule();
|
~VertexModule();
|
||||||
|
|
||||||
/// Emits SPIR-V bytecode corresponding to the provided pica vertex configuration
|
|
||||||
void Generate();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template <bool global = true>
|
||||||
|
[[nodiscard]] Id DefineVar(Id type, spv::StorageClass storage_class) {
|
||||||
|
const Id pointer_type_id{TypePointer(storage_class, type)};
|
||||||
|
return global ? AddGlobalVariable(pointer_type_id, storage_class)
|
||||||
|
: AddLocalVariable(pointer_type_id, storage_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Defines an input variable
|
||||||
|
[[nodiscard]] Id DefineInput(Id type, u32 location) {
|
||||||
|
const Id input_id{DefineVar(type, spv::StorageClass::Input)};
|
||||||
|
Decorate(input_id, spv::Decoration::Location, location);
|
||||||
|
return input_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Defines an output variable
|
||||||
|
[[nodiscard]] Id DefineOutput(Id type, u32 location) {
|
||||||
|
const Id output_id{DefineVar(type, spv::StorageClass::Output)};
|
||||||
|
Decorate(output_id, spv::Decoration::Location, location);
|
||||||
|
return output_id;
|
||||||
|
}
|
||||||
|
|
||||||
void DefineArithmeticTypes();
|
void DefineArithmeticTypes();
|
||||||
void DefineEntryPoint();
|
void DefineEntryPoint();
|
||||||
void DefineInterface();
|
void DefineInterface();
|
||||||
|
|
||||||
private:
|
public:
|
||||||
const PicaVSConfig& config;
|
struct EmitterIDs {
|
||||||
const Profile& profile;
|
|
||||||
|
|
||||||
Id void_id{};
|
Id void_id{};
|
||||||
Id bool_id{};
|
Id bool_id{};
|
||||||
Id f32_id{};
|
Id f32_id{};
|
||||||
@ -60,14 +78,49 @@ private:
|
|||||||
VectorIds ivec_ids{};
|
VectorIds ivec_ids{};
|
||||||
VectorIds uvec_ids{};
|
VectorIds uvec_ids{};
|
||||||
VectorIds bvec_ids{};
|
VectorIds bvec_ids{};
|
||||||
|
|
||||||
|
// Input vertex attributes
|
||||||
|
Id vert_in_position_id{};
|
||||||
|
Id vert_in_color_id{};
|
||||||
|
Id vert_in_texcoord0_id{};
|
||||||
|
Id vert_in_texcoord1_id{};
|
||||||
|
Id vert_in_texcoord2_id{};
|
||||||
|
Id vert_in_texcoord0_w_id{};
|
||||||
|
Id vert_in_normquat_id{};
|
||||||
|
Id vert_in_view_id{};
|
||||||
|
|
||||||
|
// Output vertex attributes
|
||||||
|
Id vert_out_color_id{};
|
||||||
|
Id vert_out_texcoord0_id{};
|
||||||
|
Id vert_out_texcoord1_id{};
|
||||||
|
Id vert_out_texcoord2_id{};
|
||||||
|
Id vert_out_texcoord0_w_id{};
|
||||||
|
Id vert_out_normquat_id{};
|
||||||
|
Id vert_out_view_id{};
|
||||||
|
|
||||||
|
// Built-ins
|
||||||
|
Id gl_position;
|
||||||
|
} ids;
|
||||||
|
|
||||||
|
/// Generate code using the provided SPIRV emitter context
|
||||||
|
void Generate(Common::UniqueFunction<void, Sirit::Module&, const EmitterIDs&> proc);
|
||||||
|
|
||||||
|
/// Emits SPIR-V bytecode corresponding to the provided pica vertex configuration
|
||||||
|
void Generate(const PicaVSConfig& config, const Profile& profile);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the SPIRV vertex shader program source code that accepts vertices from software shader
|
||||||
|
* and directly passes them to the fragment shader.
|
||||||
|
* @returns SPIRV shader assembly; empty on failure
|
||||||
|
*/
|
||||||
|
std::vector<u32> GenerateTrivialVertexShader(bool use_clip_planes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the SPIRV vertex shader program source code for the given VS program
|
* Generates the SPIRV vertex shader program source code for the given VS program
|
||||||
* @param config ShaderCacheKey object generated for the current Pica state, used for the shader
|
* @param config ShaderCacheKey object generated for the current Pica state, used for the shader
|
||||||
* configuration (NOTE: Use state in this struct only, not the Pica registers!)
|
* configuration (NOTE: Use state in this struct only, not the Pica registers!)
|
||||||
* @param separable_shader generates shader that can be used for separate shader object
|
* @returns SPIRV shader assembly; empty on failure
|
||||||
* @returns String of the shader source code; empty on failure
|
|
||||||
*/
|
*/
|
||||||
std::vector<u32> GenerateVertexShader(const Pica::ShaderSetup& setup, const PicaVSConfig& config,
|
std::vector<u32> GenerateVertexShader(const Pica::ShaderSetup& setup, const PicaVSConfig& config,
|
||||||
const Profile& profile);
|
const Profile& profile);
|
||||||
|
Loading…
Reference in New Issue
Block a user