renderer_vulkan: Remove general vertex-spv generation interface

Keep this a `TODO` for now.
This commit is contained in:
Wunkolo 2024-03-03 13:49:52 -08:00
parent eaa5b74f5e
commit eb814f77c7
4 changed files with 48 additions and 72 deletions

View File

@ -409,10 +409,9 @@ bool PipelineCache::UseProgrammableVertexShader(const Pica::RegsInternal& regs,
std::vector<u32> code;
// Disabled for programmable shaders for now
if (use_spirv && false) {
// Directly generate SPIRV
code = SPIRV::GenerateVertexShader(setup, config, profile);
// TODO: Generate vertex shader SPIRV from the given VS program
// code = SPIRV::GenerateVertexShader(setup, config, profile);
} else {
// Generate GLSL
const std::string program = GLSL::GenerateVertexShader(setup, config, true);
@ -427,7 +426,7 @@ bool PipelineCache::UseProgrammableVertexShader(const Pica::RegsInternal& regs,
const u64 code_hash = Common::ComputeHash64(std::as_bytes(std::span(code)));
auto [iter, new_program] = programmable_vertex_cache.try_emplace(code_hash, instance);
const auto [iter, new_program] = programmable_vertex_cache.try_emplace(code_hash, instance);
auto& shader = iter->second;
// Queue worker thread to create shader module

View File

@ -7,6 +7,7 @@
#include <array>
#include <sirit/sirit.h>
#include "common/common_types.h"
#include "spv_shader_gen.h"
#include "video_core/pica/regs_framebuffer.h"
#include "video_core/pica/regs_texturing.h"

View File

@ -209,83 +209,69 @@ void VertexModule::Generate(Common::UniqueFunction<void, Sirit::Module&, const E
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([use_clip_planes](Sirit::Module& code,
module.Generate([use_clip_planes](Sirit::Module& spv,
const VertexModule::EmitterIDs& ids) -> void {
const Id pos_sanitized = code.OpFunctionCall(
ids.vec.Get(4), ids.sanitize_vertex, code.OpLoad(ids.vec.Get(4), ids.vert_in_position));
const Id pos_sanitized = spv.OpFunctionCall(
ids.vec.Get(4), ids.sanitize_vertex, spv.OpLoad(ids.vec.Get(4), ids.vert_in_position));
// Negate Z
const Id neg_z =
code.OpFNegate(ids.f32, code.OpCompositeExtract(ids.f32, pos_sanitized, 2));
const Id negated_z = code.OpCompositeInsert(ids.vec.Get(4), neg_z, pos_sanitized, 2);
const Id neg_z = spv.OpFNegate(ids.f32, spv.OpCompositeExtract(ids.f32, pos_sanitized, 2));
const Id negated_z = spv.OpCompositeInsert(ids.vec.Get(4), neg_z, pos_sanitized, 2);
code.OpStore(ids.gl_position, negated_z);
spv.OpStore(ids.gl_position, negated_z);
// Pass-through
code.OpStore(ids.vert_out_color, code.OpLoad(ids.vec.Get(4), ids.vert_in_color));
code.OpStore(ids.vert_out_texcoord0, code.OpLoad(ids.vec.Get(2), ids.vert_in_texcoord0));
code.OpStore(ids.vert_out_texcoord1, code.OpLoad(ids.vec.Get(2), ids.vert_in_texcoord1));
code.OpStore(ids.vert_out_texcoord2, code.OpLoad(ids.vec.Get(2), ids.vert_in_texcoord2));
code.OpStore(ids.vert_out_texcoord0_w, code.OpLoad(ids.f32, ids.vert_in_texcoord0_w));
code.OpStore(ids.vert_out_normquat, code.OpLoad(ids.vec.Get(4), ids.vert_in_normquat));
code.OpStore(ids.vert_out_view, code.OpLoad(ids.vec.Get(3), ids.vert_in_view));
spv.OpStore(ids.vert_out_color, spv.OpLoad(ids.vec.Get(4), ids.vert_in_color));
spv.OpStore(ids.vert_out_texcoord0, spv.OpLoad(ids.vec.Get(2), ids.vert_in_texcoord0));
spv.OpStore(ids.vert_out_texcoord1, spv.OpLoad(ids.vec.Get(2), ids.vert_in_texcoord1));
spv.OpStore(ids.vert_out_texcoord2, spv.OpLoad(ids.vec.Get(2), ids.vert_in_texcoord2));
spv.OpStore(ids.vert_out_texcoord0_w, spv.OpLoad(ids.f32, ids.vert_in_texcoord0_w));
spv.OpStore(ids.vert_out_normquat, spv.OpLoad(ids.vec.Get(4), ids.vert_in_normquat));
spv.OpStore(ids.vert_out_view, spv.OpLoad(ids.vec.Get(3), ids.vert_in_view));
if (use_clip_planes) {
code.OpStore(code.OpAccessChain(code.TypePointer(spv::StorageClass::Output, ids.f32),
ids.gl_clip_distance, code.Constant(ids.u32, 0)),
spv.OpStore(spv.OpAccessChain(spv.TypePointer(spv::StorageClass::Output, ids.f32),
ids.gl_clip_distance, spv.Constant(ids.u32, 0)),
neg_z);
const Id enable_clip1 = code.OpINotEqual(
ids.bool_, code.OpLoad(ids.u32, ids.ptr_enable_clip1), code.Constant(ids.u32, 0));
const Id enable_clip1 = spv.OpINotEqual(
ids.bool_, spv.OpLoad(ids.u32, ids.ptr_enable_clip1), spv.Constant(ids.u32, 0));
{
const Id true_label = code.OpLabel();
const Id false_label = code.OpLabel();
const Id end_label = code.OpLabel();
const Id true_label = spv.OpLabel();
const Id false_label = spv.OpLabel();
const Id end_label = spv.OpLabel();
code.OpSelectionMerge(end_label, spv::SelectionControlMask::MaskNone);
code.OpBranchConditional(enable_clip1, true_label, false_label);
spv.OpSelectionMerge(end_label, spv::SelectionControlMask::MaskNone);
spv.OpBranchConditional(enable_clip1, true_label, false_label);
{
code.AddLabel(true_label);
spv.AddLabel(true_label);
code.OpStore(
code.OpAccessChain(code.TypePointer(spv::StorageClass::Output, ids.f32),
ids.gl_clip_distance, code.Constant(ids.u32, 1)),
code.OpDot(ids.f32, code.OpLoad(ids.vec.Get(4), ids.ptr_clip_coef),
spv.OpStore(
spv.OpAccessChain(spv.TypePointer(spv::StorageClass::Output, ids.f32),
ids.gl_clip_distance, spv.Constant(ids.u32, 1)),
spv.OpDot(ids.f32, spv.OpLoad(ids.vec.Get(4), ids.ptr_clip_coef),
pos_sanitized));
code.OpBranch(end_label);
spv.OpBranch(end_label);
}
{
code.AddLabel(false_label);
spv.AddLabel(false_label);
code.OpStore(
code.OpAccessChain(code.TypePointer(spv::StorageClass::Output, ids.f32),
ids.gl_clip_distance, code.Constant(ids.u32, 1)),
code.ConstantNull(ids.f32));
spv.OpStore(
spv.OpAccessChain(spv.TypePointer(spv::StorageClass::Output, ids.f32),
ids.gl_clip_distance, spv.Constant(ids.u32, 1)),
spv.ConstantNull(ids.f32));
code.OpBranch(end_label);
spv.OpBranch(end_label);
}
code.AddLabel(end_label);
spv.AddLabel(end_label);
}
}
});
return module.Assemble();
}
std::vector<u32> GenerateVertexShader(const ShaderSetup& setup, const PicaVSConfig& config,
const Profile& profile) {
VertexModule module;
module.Generate(config, profile);
return module.Assemble();
}
} // namespace Pica::Shader::Generator::SPIRV

View File

@ -66,10 +66,11 @@ private:
void DefineEntryPoint();
void DefineInterface();
Id WriteFuncSanitizeVertex();
[[nodiscard]] Id WriteFuncSanitizeVertex();
public:
struct EmitterIDs {
/// Types
Id void_{};
Id bool_{};
Id f32{};
@ -81,7 +82,7 @@ public:
VectorIds uvec{};
VectorIds bvec{};
// Input vertex attributes
/// Input vertex attributes
Id vert_in_position{};
Id vert_in_color{};
Id vert_in_texcoord0{};
@ -91,7 +92,7 @@ public:
Id vert_in_normquat{};
Id vert_in_view{};
// Output vertex attributes
/// Output vertex attributes
Id vert_out_color{};
Id vert_out_texcoord0{};
Id vert_out_texcoord1{};
@ -100,26 +101,23 @@ public:
Id vert_out_normquat{};
Id vert_out_view{};
// Uniforms
/// Uniforms
// vs_data
Id ptr_vs_data;
Id ptr_enable_clip1;
Id ptr_clip_coef;
// Built-ins
/// Built-ins
Id gl_position;
Id gl_clip_distance;
// Functions
/// Functions
Id sanitize_vertex;
} 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);
};
/**
@ -129,12 +127,4 @@ public:
*/
std::vector<u32> GenerateTrivialVertexShader(bool use_clip_planes);
/**
* 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
* configuration (NOTE: Use state in this struct only, not the Pica registers!)
* @returns SPIRV shader assembly; empty on failure
*/
std::vector<u32> GenerateVertexShader(const Pica::ShaderSetup& setup, const PicaVSConfig& config,
const Profile& profile);
} // namespace Pica::Shader::Generator::SPIRV