emit vertex attributes

This commit is contained in:
Samuliak 2024-10-05 19:28:27 +02:00
parent 5ace31b471
commit 0b12e22331
No known key found for this signature in database
3 changed files with 137 additions and 16 deletions

View file

@ -49,6 +49,7 @@ std::string_view InputArrayDecorator(Stage stage) {
*/
// TODO
/*
std::string OutputDecorator(Stage stage, u32 size) {
switch (stage) {
case Stage::TessellationControl:
@ -57,6 +58,7 @@ std::string OutputDecorator(Stage stage, u32 size) {
return "";
}
}
*/
/*
// TODO
@ -240,13 +242,13 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
stage_name = "vertex";
break;
case Stage::TessellationControl:
stage_name = "kernel";
stage_name = "INVALID";
break;
case Stage::TessellationEval:
stage_name = "vertex";
stage_name = "INVALID";
break;
case Stage::Geometry:
stage_name = "vertex";
stage_name = "INVALID";
break;
case Stage::Fragment:
stage_name = "fragment";
@ -275,7 +277,11 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
if (!info.loads.Generic(index) || !runtime_info.previous_stage_stores.Generic(index)) {
continue;
}
DefineStageInOut(index, program.invocations, true);
const std::string qualifier{(stage == Stage::VertexA || stage == Stage::VertexB) ? "attribute(" : "user(locn"};
// TODO: uncomment
header += fmt::format("float4 attr{} [[{}{})]];\n"/*,
InterpDecorator(info.interpolation[index])*/, index/*,
InputArrayDecorator(stage)*/, qualifier, index);
has_stage_input = true;
}
for (size_t index = 0; index < info.uses_patches.size(); ++index) {
@ -319,7 +325,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
}
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
if (info.stores.Generic(index)) {
DefineStageInOut(index, program.invocations, false);
DefineStageOut(index, program.invocations);
}
}
header += "};\n";
@ -437,14 +443,13 @@ void EmitContext::DefineInputs(Bindings& bindings) {
}
// TODO
void EmitContext::DefineStageInOut(size_t index, u32 invocations, bool is_input) {
const auto type{fmt::format("float{}", 4)};
void EmitContext::DefineStageOut(size_t index, u32 invocations) {
std::string name{fmt::format("attr{}", index)};
header += fmt::format("{} {}{} [[user(locn{})]];\n", type, name,
OutputDecorator(stage, invocations), index);
header += fmt::format("float4 {} [[user(locn{})]];\n", name/*,
OutputDecorator(stage, invocations)*/, index);
const GenericElementInfo element_info{
.name = (is_input ? "__in." : "__out.") + name,
.name = "__out." + name,
.first_element = 0,
.num_components = 4,
};
@ -452,6 +457,7 @@ void EmitContext::DefineStageInOut(size_t index, u32 invocations, bool is_input)
}
void EmitContext::DefineHelperFunctions() {
// TODO: use MSL's extract_bits instead
header +=
"uint bitfieldExtract(uint value, int offset, int bits) {\nreturn (value >> offset) & "
"((1 << bits) - 1);\n}\n";

View file

@ -162,7 +162,7 @@ public:
private:
// TODO: break down into smaller functions
void DefineInputs(Bindings& bindings);
void DefineStageInOut(size_t index, u32 invocations, bool is_input);
void DefineStageOut(size_t index, u32 invocations);
void DefineHelperFunctions();
void DefineConstants();
std::string DefineGlobalMemoryFunctions();

View file

@ -56,9 +56,124 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
const GraphicsPipelineCacheKey& key,
const Shader::IR::Program& program,
const Shader::IR::Program* previous_program) {
Shader::RuntimeInfo info{};
// TODO: fill in the runtime info
Shader::RuntimeInfo info;
if (previous_program) {
info.previous_stage_stores = previous_program->info.stores;
info.previous_stage_legacy_stores_mapping = previous_program->info.legacy_stores_mapping;
if (previous_program->is_geometry_passthrough) {
info.previous_stage_stores.mask |= previous_program->info.passthrough.mask;
}
} else {
info.previous_stage_stores.mask.set();
}
// TODO: uncomment
/*
const Shader::Stage stage{program.stage};
const bool has_geometry{key.unique_hashes[4] != 0 && !programs[4].is_geometry_passthrough};
const bool gl_ndc{key.state.ndc_minus_one_to_one != 0};
const float point_size{Common::BitCast<float>(key.state.point_size)};
switch (stage) {
case Shader::Stage::VertexB:
if (!has_geometry) {
if (key.state.topology == Maxwell::PrimitiveTopology::Points) {
info.fixed_state_point_size = point_size;
}
if (key.state.xfb_enabled) {
auto [varyings, count] =
VideoCommon::MakeTransformFeedbackVaryings(key.state.xfb_state);
info.xfb_varyings = varyings;
info.xfb_count = count;
}
info.convert_depth_mode = gl_ndc;
}
if (key.state.dynamic_vertex_input) {
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
info.generic_input_types[index] = AttributeType(key.state, index);
}
} else {
std::ranges::transform(key.state.attributes, info.generic_input_types.begin(),
&CastAttributeType);
}
break;
case Shader::Stage::TessellationEval:
info.tess_clockwise = key.state.tessellation_clockwise != 0;
info.tess_primitive = [&key] {
const u32 raw{key.state.tessellation_primitive.Value()};
switch (static_cast<Maxwell::Tessellation::DomainType>(raw)) {
case Maxwell::Tessellation::DomainType::Isolines:
return Shader::TessPrimitive::Isolines;
case Maxwell::Tessellation::DomainType::Triangles:
return Shader::TessPrimitive::Triangles;
case Maxwell::Tessellation::DomainType::Quads:
return Shader::TessPrimitive::Quads;
}
ASSERT(false);
return Shader::TessPrimitive::Triangles;
}();
info.tess_spacing = [&] {
const u32 raw{key.state.tessellation_spacing};
switch (static_cast<Maxwell::Tessellation::Spacing>(raw)) {
case Maxwell::Tessellation::Spacing::Integer:
return Shader::TessSpacing::Equal;
case Maxwell::Tessellation::Spacing::FractionalOdd:
return Shader::TessSpacing::FractionalOdd;
case Maxwell::Tessellation::Spacing::FractionalEven:
return Shader::TessSpacing::FractionalEven;
}
ASSERT(false);
return Shader::TessSpacing::Equal;
}();
break;
case Shader::Stage::Geometry:
if (program.output_topology == Shader::OutputTopology::PointList) {
info.fixed_state_point_size = point_size;
}
if (key.state.xfb_enabled != 0) {
auto [varyings, count] =
VideoCommon::MakeTransformFeedbackVaryings(key.state.xfb_state);
info.xfb_varyings = varyings;
info.xfb_count = count;
}
info.convert_depth_mode = gl_ndc;
break;
case Shader::Stage::Fragment:
info.alpha_test_func = MaxwellToCompareFunction(
key.state.UnpackComparisonOp(key.state.alpha_test_func.Value()));
info.alpha_test_reference = Common::BitCast<float>(key.state.alpha_test_ref);
break;
default:
break;
}
switch (key.state.topology) {
case Maxwell::PrimitiveTopology::Points:
info.input_topology = Shader::InputTopology::Points;
break;
case Maxwell::PrimitiveTopology::Lines:
case Maxwell::PrimitiveTopology::LineLoop:
case Maxwell::PrimitiveTopology::LineStrip:
info.input_topology = Shader::InputTopology::Lines;
break;
case Maxwell::PrimitiveTopology::Triangles:
case Maxwell::PrimitiveTopology::TriangleStrip:
case Maxwell::PrimitiveTopology::TriangleFan:
case Maxwell::PrimitiveTopology::Quads:
case Maxwell::PrimitiveTopology::QuadStrip:
case Maxwell::PrimitiveTopology::Polygon:
case Maxwell::PrimitiveTopology::Patches:
info.input_topology = Shader::InputTopology::Triangles;
break;
case Maxwell::PrimitiveTopology::LinesAdjacency:
case Maxwell::PrimitiveTopology::LineStripAdjacency:
info.input_topology = Shader::InputTopology::LinesAdjacency;
break;
case Maxwell::PrimitiveTopology::TrianglesAdjacency:
case Maxwell::PrimitiveTopology::TriangleStripAdjacency:
info.input_topology = Shader::InputTopology::TrianglesAdjacency;
break;
}
info.force_early_z = key.state.early_z != 0;
info.y_negate = key.state.y_negate != 0;
*/
return info;
}
@ -231,7 +346,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
auto hash = key.Hash();
LOG_INFO(Render_Metal, "0x{:016x}", hash);
// Translate shaders to spirv
// Translate shaders
size_t env_index{0};
std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs;
@ -268,7 +383,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
ConvertLegacyToGeneric(program, runtime_info);
const std::string code{EmitMSL(profile, runtime_info, program, binding)};
// HACK
std::cout << "SHADER INDEX: " << index - 1 << std::endl;
std::cout << "SHADER INDEX: " << stage_index << std::endl;
std::cout << code << std::endl;
MTL::CompileOptions* compile_options = MTL::CompileOptions::alloc()->init();
NS::Error* error = nullptr;