mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-25 16:22:47 +01:00
emit vertex attributes
This commit is contained in:
parent
5ace31b471
commit
0b12e22331
3 changed files with 137 additions and 16 deletions
|
@ -49,6 +49,7 @@ std::string_view InputArrayDecorator(Stage stage) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
/*
|
||||||
std::string OutputDecorator(Stage stage, u32 size) {
|
std::string OutputDecorator(Stage stage, u32 size) {
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case Stage::TessellationControl:
|
case Stage::TessellationControl:
|
||||||
|
@ -57,6 +58,7 @@ std::string OutputDecorator(Stage stage, u32 size) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -240,13 +242,13 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
|
||||||
stage_name = "vertex";
|
stage_name = "vertex";
|
||||||
break;
|
break;
|
||||||
case Stage::TessellationControl:
|
case Stage::TessellationControl:
|
||||||
stage_name = "kernel";
|
stage_name = "INVALID";
|
||||||
break;
|
break;
|
||||||
case Stage::TessellationEval:
|
case Stage::TessellationEval:
|
||||||
stage_name = "vertex";
|
stage_name = "INVALID";
|
||||||
break;
|
break;
|
||||||
case Stage::Geometry:
|
case Stage::Geometry:
|
||||||
stage_name = "vertex";
|
stage_name = "INVALID";
|
||||||
break;
|
break;
|
||||||
case Stage::Fragment:
|
case Stage::Fragment:
|
||||||
stage_name = "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)) {
|
if (!info.loads.Generic(index) || !runtime_info.previous_stage_stores.Generic(index)) {
|
||||||
continue;
|
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;
|
has_stage_input = true;
|
||||||
}
|
}
|
||||||
for (size_t index = 0; index < info.uses_patches.size(); ++index) {
|
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) {
|
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
|
||||||
if (info.stores.Generic(index)) {
|
if (info.stores.Generic(index)) {
|
||||||
DefineStageInOut(index, program.invocations, false);
|
DefineStageOut(index, program.invocations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
header += "};\n";
|
header += "};\n";
|
||||||
|
@ -437,14 +443,13 @@ void EmitContext::DefineInputs(Bindings& bindings) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
void EmitContext::DefineStageInOut(size_t index, u32 invocations, bool is_input) {
|
void EmitContext::DefineStageOut(size_t index, u32 invocations) {
|
||||||
const auto type{fmt::format("float{}", 4)};
|
|
||||||
std::string name{fmt::format("attr{}", index)};
|
std::string name{fmt::format("attr{}", index)};
|
||||||
header += fmt::format("{} {}{} [[user(locn{})]];\n", type, name,
|
header += fmt::format("float4 {} [[user(locn{})]];\n", name/*,
|
||||||
OutputDecorator(stage, invocations), index);
|
OutputDecorator(stage, invocations)*/, index);
|
||||||
|
|
||||||
const GenericElementInfo element_info{
|
const GenericElementInfo element_info{
|
||||||
.name = (is_input ? "__in." : "__out.") + name,
|
.name = "__out." + name,
|
||||||
.first_element = 0,
|
.first_element = 0,
|
||||||
.num_components = 4,
|
.num_components = 4,
|
||||||
};
|
};
|
||||||
|
@ -452,6 +457,7 @@ void EmitContext::DefineStageInOut(size_t index, u32 invocations, bool is_input)
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitContext::DefineHelperFunctions() {
|
void EmitContext::DefineHelperFunctions() {
|
||||||
|
// TODO: use MSL's extract_bits instead
|
||||||
header +=
|
header +=
|
||||||
"uint bitfieldExtract(uint value, int offset, int bits) {\nreturn (value >> offset) & "
|
"uint bitfieldExtract(uint value, int offset, int bits) {\nreturn (value >> offset) & "
|
||||||
"((1 << bits) - 1);\n}\n";
|
"((1 << bits) - 1);\n}\n";
|
||||||
|
|
|
@ -162,7 +162,7 @@ public:
|
||||||
private:
|
private:
|
||||||
// TODO: break down into smaller functions
|
// TODO: break down into smaller functions
|
||||||
void DefineInputs(Bindings& bindings);
|
void DefineInputs(Bindings& bindings);
|
||||||
void DefineStageInOut(size_t index, u32 invocations, bool is_input);
|
void DefineStageOut(size_t index, u32 invocations);
|
||||||
void DefineHelperFunctions();
|
void DefineHelperFunctions();
|
||||||
void DefineConstants();
|
void DefineConstants();
|
||||||
std::string DefineGlobalMemoryFunctions();
|
std::string DefineGlobalMemoryFunctions();
|
||||||
|
|
|
@ -56,9 +56,124 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
|
||||||
const GraphicsPipelineCacheKey& key,
|
const GraphicsPipelineCacheKey& key,
|
||||||
const Shader::IR::Program& program,
|
const Shader::IR::Program& program,
|
||||||
const Shader::IR::Program* previous_program) {
|
const Shader::IR::Program* previous_program) {
|
||||||
Shader::RuntimeInfo info{};
|
Shader::RuntimeInfo info;
|
||||||
|
if (previous_program) {
|
||||||
// TODO: fill in the runtime info
|
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;
|
return info;
|
||||||
}
|
}
|
||||||
|
@ -231,7 +346,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
|
||||||
auto hash = key.Hash();
|
auto hash = key.Hash();
|
||||||
LOG_INFO(Render_Metal, "0x{:016x}", hash);
|
LOG_INFO(Render_Metal, "0x{:016x}", hash);
|
||||||
|
|
||||||
// Translate shaders to spirv
|
// Translate shaders
|
||||||
size_t env_index{0};
|
size_t env_index{0};
|
||||||
std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs;
|
std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs;
|
||||||
|
|
||||||
|
@ -268,7 +383,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
|
||||||
ConvertLegacyToGeneric(program, runtime_info);
|
ConvertLegacyToGeneric(program, runtime_info);
|
||||||
const std::string code{EmitMSL(profile, runtime_info, program, binding)};
|
const std::string code{EmitMSL(profile, runtime_info, program, binding)};
|
||||||
// HACK
|
// HACK
|
||||||
std::cout << "SHADER INDEX: " << index - 1 << std::endl;
|
std::cout << "SHADER INDEX: " << stage_index << std::endl;
|
||||||
std::cout << code << std::endl;
|
std::cout << code << std::endl;
|
||||||
MTL::CompileOptions* compile_options = MTL::CompileOptions::alloc()->init();
|
MTL::CompileOptions* compile_options = MTL::CompileOptions::alloc()->init();
|
||||||
NS::Error* error = nullptr;
|
NS::Error* error = nullptr;
|
||||||
|
|
Loading…
Reference in a new issue