attempt to compile msl shaders

This commit is contained in:
Samuliak 2024-05-04 12:00:51 +02:00
parent 5a2c073ebe
commit 16986bf42f
6 changed files with 80 additions and 189 deletions

View file

@ -174,13 +174,6 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) {
} }
} }
std::string MslVersionSpecifier(const EmitContext& ctx) {
if (ctx.uses_y_direction) {
return " compatibility";
}
return "";
}
bool IsPreciseType(MslVarType type) { bool IsPreciseType(MslVarType type) {
switch (type) { switch (type) {
case MslVarType::PrecF32: case MslVarType::PrecF32:
@ -219,8 +212,7 @@ std::string EmitMSL(const Profile& profile, const RuntimeInfo& runtime_info, IR:
EmitContext ctx{program, bindings, profile, runtime_info}; EmitContext ctx{program, bindings, profile, runtime_info};
Precolor(program); Precolor(program);
EmitCode(ctx, program); EmitCode(ctx, program);
const std::string version{fmt::format("#version 460{}\n", MslVersionSpecifier(ctx))}; ctx.header.insert(0, "#include <metal_stdlib>\nusing namespace metal;\n");
ctx.header.insert(0, version);
if (program.shared_memory_size > 0) { if (program.shared_memory_size > 0) {
const auto requested_size{program.shared_memory_size}; const auto requested_size{program.shared_memory_size};
const auto max_size{profile.gl_max_compute_smem_size}; const auto max_size{profile.gl_max_compute_smem_size};
@ -232,7 +224,7 @@ std::string EmitMSL(const Profile& profile, const RuntimeInfo& runtime_info, IR:
const auto smem_size{needs_clamp ? max_size : requested_size}; const auto smem_size{needs_clamp ? max_size : requested_size};
ctx.header += fmt::format("shared uint smem[{}];", Common::DivCeil(smem_size, 4U)); ctx.header += fmt::format("shared uint smem[{}];", Common::DivCeil(smem_size, 4U));
} }
ctx.header += "void main(){\n"; ctx.header += "void main_(){\n";
if (program.local_memory_size > 0) { if (program.local_memory_size > 0) {
ctx.header += fmt::format("uint lmem[{}];", Common::DivCeil(program.local_memory_size, 4U)); ctx.header += fmt::format("uint lmem[{}];", Common::DivCeil(program.local_memory_size, 4U));
} }

View file

@ -40,12 +40,12 @@ std::string CastToIntVec(std::string_view value, const IR::TextureInstInfo& info
case TextureType::ColorArray1D: case TextureType::ColorArray1D:
case TextureType::Color2D: case TextureType::Color2D:
case TextureType::ColorArray2D: case TextureType::ColorArray2D:
return fmt::format("ivec2({})", value); return fmt::format("int2({})", value);
case TextureType::Color3D: case TextureType::Color3D:
case TextureType::ColorCube: case TextureType::ColorCube:
return fmt::format("ivec3({})", value); return fmt::format("int3({})", value);
case TextureType::ColorArrayCube: case TextureType::ColorArrayCube:
return fmt::format("ivec4({})", value); return fmt::format("int4({})", value);
default: default:
throw NotImplementedException("Integer cast for TextureType {}", info.type.Value()); throw NotImplementedException("Integer cast for TextureType {}", info.type.Value());
} }
@ -58,13 +58,13 @@ std::string CoordsCastToInt(std::string_view value, const IR::TextureInstInfo& i
return fmt::format("int({})", value); return fmt::format("int({})", value);
case TextureType::ColorArray1D: case TextureType::ColorArray1D:
case TextureType::Color2D: case TextureType::Color2D:
return fmt::format("ivec2({})", value); return fmt::format("int2({})", value);
case TextureType::ColorArray2D: case TextureType::ColorArray2D:
case TextureType::Color3D: case TextureType::Color3D:
case TextureType::ColorCube: case TextureType::ColorCube:
return fmt::format("ivec3({})", value); return fmt::format("int3({})", value);
case TextureType::ColorArrayCube: case TextureType::ColorArrayCube:
return fmt::format("ivec4({})", value); return fmt::format("int4({})", value);
default: default:
throw NotImplementedException("TexelFetchCast type {}", info.type.Value()); throw NotImplementedException("TexelFetchCast type {}", info.type.Value());
} }
@ -89,12 +89,12 @@ std::string GetOffsetVec(EmitContext& ctx, const IR::Value& offset) {
if (inst->AreAllArgsImmediates()) { if (inst->AreAllArgsImmediates()) {
switch (inst->GetOpcode()) { switch (inst->GetOpcode()) {
case IR::Opcode::CompositeConstructU32x2: case IR::Opcode::CompositeConstructU32x2:
return fmt::format("ivec2({},{})", inst->Arg(0).U32(), inst->Arg(1).U32()); return fmt::format("int2({},{})", inst->Arg(0).U32(), inst->Arg(1).U32());
case IR::Opcode::CompositeConstructU32x3: case IR::Opcode::CompositeConstructU32x3:
return fmt::format("ivec3({},{},{})", inst->Arg(0).U32(), inst->Arg(1).U32(), return fmt::format("int3({},{},{})", inst->Arg(0).U32(), inst->Arg(1).U32(),
inst->Arg(2).U32()); inst->Arg(2).U32());
case IR::Opcode::CompositeConstructU32x4: case IR::Opcode::CompositeConstructU32x4:
return fmt::format("ivec4({},{},{},{})", inst->Arg(0).U32(), inst->Arg(1).U32(), return fmt::format("int4({},{},{},{})", inst->Arg(0).U32(), inst->Arg(1).U32(),
inst->Arg(2).U32(), inst->Arg(3).U32()); inst->Arg(2).U32(), inst->Arg(3).U32());
default: default:
break; break;
@ -109,11 +109,11 @@ std::string GetOffsetVec(EmitContext& ctx, const IR::Value& offset) {
case IR::Type::U32: case IR::Type::U32:
return fmt::format("int({})", offset_str); return fmt::format("int({})", offset_str);
case IR::Type::U32x2: case IR::Type::U32x2:
return fmt::format("ivec2({})", offset_str); return fmt::format("int2({})", offset_str);
case IR::Type::U32x3: case IR::Type::U32x3:
return fmt::format("ivec3({})", offset_str); return fmt::format("int3({})", offset_str);
case IR::Type::U32x4: case IR::Type::U32x4:
return fmt::format("ivec4({})", offset_str); return fmt::format("int4({})", offset_str);
default: default:
throw NotImplementedException("Offset type {}", offset.Type()); throw NotImplementedException("Offset type {}", offset.Type());
} }
@ -123,7 +123,7 @@ std::string PtpOffsets(const IR::Value& offset, const IR::Value& offset2) {
const std::array values{offset.InstRecursive(), offset2.InstRecursive()}; const std::array values{offset.InstRecursive(), offset2.InstRecursive()};
if (!values[0]->AreAllArgsImmediates() || !values[1]->AreAllArgsImmediates()) { if (!values[0]->AreAllArgsImmediates() || !values[1]->AreAllArgsImmediates()) {
LOG_WARNING(Shader_MSL, "Not all arguments in PTP are immediate, STUBBING"); LOG_WARNING(Shader_MSL, "Not all arguments in PTP are immediate, STUBBING");
return "ivec2[](ivec2(0), ivec2(1), ivec2(2), ivec2(3))"; return "int2[](int2(0), int2(1), int2(2), int2(3))";
} }
const IR::Opcode opcode{values[0]->GetOpcode()}; const IR::Opcode opcode{values[0]->GetOpcode()};
if (opcode != values[1]->GetOpcode() || opcode != IR::Opcode::CompositeConstructU32x4) { if (opcode != values[1]->GetOpcode() || opcode != IR::Opcode::CompositeConstructU32x4) {
@ -131,7 +131,7 @@ std::string PtpOffsets(const IR::Value& offset, const IR::Value& offset2) {
} }
auto read{[&](unsigned int a, unsigned int b) { return values[a]->Arg(b).U32(); }}; auto read{[&](unsigned int a, unsigned int b) { return values[a]->Arg(b).U32(); }};
return fmt::format("ivec2[](ivec2({},{}),ivec2({},{}),ivec2({},{}),ivec2({},{}))", read(0, 0), return fmt::format("int2[](int2({},{}),int2({},{}),int2({},{}),int2({},{}))", read(0, 0),
read(0, 1), read(0, 2), read(0, 3), read(1, 0), read(1, 1), read(1, 2), read(0, 1), read(0, 2), read(0, 3), read(1, 0), read(1, 1), read(1, 2),
read(1, 3)); read(1, 3));
} }
@ -149,11 +149,11 @@ std::string ImageGatherSubpixelOffset(const IR::TextureInstInfo& info, std::stri
switch (info.type) { switch (info.type) {
case TextureType::Color2D: case TextureType::Color2D:
case TextureType::Color2DRect: case TextureType::Color2DRect:
return fmt::format("{}+vec2(0.001953125)/vec2(textureSize({}, 0))", coords, texture); return fmt::format("{}+float2(0.001953125)/float2(textureSize({}, 0))", coords, texture);
case TextureType::ColorArray2D: case TextureType::ColorArray2D:
case TextureType::ColorCube: case TextureType::ColorCube:
return fmt::format("vec3({0}.xy+vec2(0.001953125)/vec2(textureSize({1}, 0)),{0}.z)", coords, return fmt::format("float3({0}.xy+float2(0.001953125)/float2(textureSize({1}, 0)),{0}.z)",
texture); coords, texture);
default: default:
return std::string{coords}; return std::string{coords};
} }
@ -512,20 +512,20 @@ void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value&
const auto lod_str{uses_lod ? fmt::format(",int({})", lod) : ""}; const auto lod_str{uses_lod ? fmt::format(",int({})", lod) : ""};
switch (info.type) { switch (info.type) {
case TextureType::Color1D: case TextureType::Color1D:
return ctx.AddU32x4("{}=uvec4(uint(textureSize({}{})),0u,0u,{});", inst, texture, lod_str, return ctx.AddU32x4("{}=uint4(uint(textureSize({}{})),0u,0u,{});", inst, texture, lod_str,
mips); mips);
case TextureType::ColorArray1D: case TextureType::ColorArray1D:
case TextureType::Color2D: case TextureType::Color2D:
case TextureType::ColorCube: case TextureType::ColorCube:
case TextureType::Color2DRect: case TextureType::Color2DRect:
return ctx.AddU32x4("{}=uvec4(uvec2(textureSize({}{})),0u,{});", inst, texture, lod_str, return ctx.AddU32x4("{}=uint4(uint2(textureSize({}{})),0u,{});", inst, texture, lod_str,
mips); mips);
case TextureType::ColorArray2D: case TextureType::ColorArray2D:
case TextureType::Color3D: case TextureType::Color3D:
case TextureType::ColorArrayCube: case TextureType::ColorArrayCube:
return ctx.AddU32x4("{}=uvec4(uvec3(textureSize({}{})),{});", inst, texture, lod_str, mips); return ctx.AddU32x4("{}=uint4(uint3(textureSize({}{})),{});", inst, texture, lod_str, mips);
case TextureType::Buffer: case TextureType::Buffer:
return ctx.AddU32x4("{}=uvec4(uint(textureSize({})),0u,0u,{});", inst, texture, mips); return ctx.AddU32x4("{}=uint4(uint(textureSize({})),0u,0u,{});", inst, texture, mips);
} }
throw LogicError("Unspecified image type {}", info.type.Value()); throw LogicError("Unspecified image type {}", info.type.Value());
} }
@ -534,7 +534,7 @@ void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
std::string_view coords) { std::string_view coords) {
const auto info{inst.Flags<IR::TextureInstInfo>()}; const auto info{inst.Flags<IR::TextureInstInfo>()};
const auto texture{Texture(ctx, info, index)}; const auto texture{Texture(ctx, info, index)};
return ctx.AddF32x4("{}=vec4(textureQueryLod({},{}),0.0,0.0);", inst, texture, coords); return ctx.AddF32x4("{}=float4(textureQueryLod({},{}),0.0,0.0);", inst, texture, coords);
} }
void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
@ -558,11 +558,11 @@ void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
if (multi_component) { if (multi_component) {
if (info.num_derivatives >= 3) { if (info.num_derivatives >= 3) {
const auto offset_vec{ctx.var_alloc.Consume(offset)}; const auto offset_vec{ctx.var_alloc.Consume(offset)};
ctx.Add("{}=textureGrad({},{},vec3({}.xz, {}.x),vec3({}.yw, {}.y));", texel, texture, ctx.Add("{}=textureGrad({},{},float3({}.xz, {}.x),float3({}.yw, {}.y));", texel,
coords, derivatives_vec, offset_vec, derivatives_vec, offset_vec); texture, coords, derivatives_vec, offset_vec, derivatives_vec, offset_vec);
return; return;
} }
ctx.Add("{}=textureGrad({},{},vec2({}.xz),vec2({}.yz));", texel, texture, coords, ctx.Add("{}=textureGrad({},{},float2({}.xz),float2({}.yz));", texel, texture, coords,
derivatives_vec, derivatives_vec); derivatives_vec, derivatives_vec);
} else { } else {
ctx.Add("{}=textureGrad({},{},float({}.x),float({}.y));", texel, texture, coords, ctx.Add("{}=textureGrad({},{},float({}.x),float({}.y));", texel, texture, coords,
@ -578,7 +578,7 @@ void EmitImageRead(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
throw NotImplementedException("EmitImageRead Sparse"); throw NotImplementedException("EmitImageRead Sparse");
} }
const auto image{Image(ctx, info, index)}; const auto image{Image(ctx, info, index)};
ctx.AddU32x4("{}=uvec4(imageLoad({},{}));", inst, image, CoordsCastToInt(coords, info)); ctx.AddU32x4("{}=uint4(imageLoad({},{}));", inst, image, CoordsCastToInt(coords, info));
} }
void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, void EmitImageWrite(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,

View file

@ -50,7 +50,7 @@ void EmitLoadGlobal64(EmitContext& ctx, IR::Inst& inst, std::string_view address
return ctx.AddU32x2("{}=LoadGlobal64({});", inst, address); return ctx.AddU32x2("{}=LoadGlobal64({});", inst, address);
} }
LOG_WARNING(Shader_MSL, "Int64 not supported, ignoring memory operation"); LOG_WARNING(Shader_MSL, "Int64 not supported, ignoring memory operation");
ctx.AddU32x2("{}=uvec2(0);", inst); ctx.AddU32x2("{}=uint2(0);", inst);
} }
void EmitLoadGlobal128(EmitContext& ctx, IR::Inst& inst, std::string_view address) { void EmitLoadGlobal128(EmitContext& ctx, IR::Inst& inst, std::string_view address) {
@ -58,7 +58,7 @@ void EmitLoadGlobal128(EmitContext& ctx, IR::Inst& inst, std::string_view addres
return ctx.AddU32x4("{}=LoadGlobal128({});", inst, address); return ctx.AddU32x4("{}=LoadGlobal128({});", inst, address);
} }
LOG_WARNING(Shader_MSL, "Int64 not supported, ignoring memory operation"); LOG_WARNING(Shader_MSL, "Int64 not supported, ignoring memory operation");
ctx.AddU32x4("{}=uvec4(0);", inst); ctx.AddU32x4("{}=uint4(0);", inst);
} }
void EmitWriteGlobalU8(EmitContext&) { void EmitWriteGlobalU8(EmitContext&) {

View file

@ -87,9 +87,7 @@ void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value&
if (phi_reg == val_reg) { if (phi_reg == val_reg) {
return; return;
} }
const bool needs_workaround{ctx.profile.has_gl_bool_ref_bug && phi_type == IR::Type::U1}; ctx.Add("{}={};", phi_reg, val_reg);
const auto suffix{needs_workaround ? "?true:false" : ""};
ctx.Add("{}={}{};", phi_reg, val_reg, suffix);
} }
void EmitPrologue(EmitContext& ctx) { void EmitPrologue(EmitContext& ctx) {

View file

@ -41,18 +41,6 @@ std::string_view InputArrayDecorator(Stage stage) {
} }
} }
bool StoresPerVertexAttributes(Stage stage) {
switch (stage) {
case Stage::VertexA:
case Stage::VertexB:
case Stage::Geometry:
case Stage::TessellationEval:
return true;
default:
return false;
}
}
std::string OutputDecorator(Stage stage, u32 size) { std::string OutputDecorator(Stage stage, u32 size) {
switch (stage) { switch (stage) {
case Stage::TessellationControl: case Stage::TessellationControl:
@ -62,6 +50,7 @@ std::string OutputDecorator(Stage stage, u32 size) {
} }
} }
// TODO
std::string_view DepthSamplerType(TextureType type) { std::string_view DepthSamplerType(TextureType type) {
switch (type) { switch (type) {
case TextureType::Color1D: case TextureType::Color1D:
@ -81,56 +70,57 @@ std::string_view DepthSamplerType(TextureType type) {
} }
} }
// TODO: emit sampler as well
// TODO: handle multisample
// TODO: handle texture buffer
std::string_view ColorSamplerType(TextureType type, bool is_multisample = false) { std::string_view ColorSamplerType(TextureType type, bool is_multisample = false) {
if (is_multisample) { if (is_multisample) {
ASSERT(type == TextureType::Color2D || type == TextureType::ColorArray2D); ASSERT(type == TextureType::Color2D || type == TextureType::ColorArray2D);
} }
switch (type) { switch (type) {
case TextureType::Color1D: case TextureType::Color1D:
return "sampler1D"; return "texture1d";
case TextureType::ColorArray1D: case TextureType::ColorArray1D:
return "sampler1DArray"; return "texture1d_array";
case TextureType::Color2D: case TextureType::Color2D:
case TextureType::Color2DRect: case TextureType::Color2DRect:
return is_multisample ? "sampler2DMS" : "sampler2D"; return "texture2d";
case TextureType::ColorArray2D: case TextureType::ColorArray2D:
return is_multisample ? "sampler2DMSArray" : "sampler2DArray"; return "texture2d_array";
case TextureType::Color3D: case TextureType::Color3D:
return "sampler3D"; return "texture3d";
case TextureType::ColorCube: case TextureType::ColorCube:
return "samplerCube"; return "texturecube";
case TextureType::ColorArrayCube: case TextureType::ColorArrayCube:
return "samplerCubeArray"; return "texturecube_array";
case TextureType::Buffer:
return "samplerBuffer";
default: default:
throw NotImplementedException("Texture type: {}", type); throw NotImplementedException("Texture type: {}", type);
} }
} }
// TODO: handle texture buffer
std::string_view ImageType(TextureType type) { std::string_view ImageType(TextureType type) {
switch (type) { switch (type) {
case TextureType::Color1D: case TextureType::Color1D:
return "uimage1D"; return "texture1d";
case TextureType::ColorArray1D: case TextureType::ColorArray1D:
return "uimage1DArray"; return "texture1d_array";
case TextureType::Color2D: case TextureType::Color2D:
return "uimage2D"; return "texture2d";
case TextureType::ColorArray2D: case TextureType::ColorArray2D:
return "uimage2DArray"; return "texture2d_array";
case TextureType::Color3D: case TextureType::Color3D:
return "uimage3D"; return "texture3d";
case TextureType::ColorCube: case TextureType::ColorCube:
return "uimageCube"; return "texturecube";
case TextureType::ColorArrayCube: case TextureType::ColorArrayCube:
return "uimageCubeArray"; return "texturecube_array";
case TextureType::Buffer:
return "uimageBuffer";
default: default:
throw NotImplementedException("Image type: {}", type); throw NotImplementedException("Image type: {}", type);
} }
} }
// TODO: is this needed?
std::string_view ImageFormatString(ImageFormat format) { std::string_view ImageFormatString(ImageFormat format) {
switch (format) { switch (format) {
case ImageFormat::Typeless: case ImageFormat::Typeless:
@ -155,15 +145,19 @@ std::string_view ImageFormatString(ImageFormat format) {
} }
std::string_view ImageAccessQualifier(bool is_written, bool is_read) { std::string_view ImageAccessQualifier(bool is_written, bool is_read) {
if (is_written && !is_read) { if (is_written && is_read) {
return "writeonly "; return "access::read, access::write";
} }
if (is_read && !is_written) { if (is_written) {
return "readonly "; return "access::write";
}
if (is_read) {
return "access::read";
} }
return ""; return "";
} }
// TODO
std::string_view GetTessMode(TessPrimitive primitive) { std::string_view GetTessMode(TessPrimitive primitive) {
switch (primitive) { switch (primitive) {
case TessPrimitive::Triangles: case TessPrimitive::Triangles:
@ -176,6 +170,7 @@ std::string_view GetTessMode(TessPrimitive primitive) {
throw InvalidArgument("Invalid tessellation primitive {}", primitive); throw InvalidArgument("Invalid tessellation primitive {}", primitive);
} }
// TODO
std::string_view GetTessSpacing(TessSpacing spacing) { std::string_view GetTessSpacing(TessSpacing spacing) {
switch (spacing) { switch (spacing) {
case TessSpacing::Equal: case TessSpacing::Equal:
@ -188,6 +183,7 @@ std::string_view GetTessSpacing(TessSpacing spacing) {
throw InvalidArgument("Invalid tessellation spacing {}", spacing); throw InvalidArgument("Invalid tessellation spacing {}", spacing);
} }
// TODO
std::string_view InputPrimitive(InputTopology topology) { std::string_view InputPrimitive(InputTopology topology) {
switch (topology) { switch (topology) {
case InputTopology::Points: case InputTopology::Points:
@ -204,6 +200,7 @@ std::string_view InputPrimitive(InputTopology topology) {
throw InvalidArgument("Invalid input topology {}", topology); throw InvalidArgument("Invalid input topology {}", topology);
} }
// TODO
std::string_view OutputPrimitive(OutputTopology topology) { std::string_view OutputPrimitive(OutputTopology topology) {
switch (topology) { switch (topology) {
case OutputTopology::PointList: case OutputTopology::PointList:
@ -215,56 +212,6 @@ std::string_view OutputPrimitive(OutputTopology topology) {
} }
throw InvalidArgument("Invalid output topology {}", topology); throw InvalidArgument("Invalid output topology {}", topology);
} }
void SetupOutPerVertex(EmitContext& ctx, std::string& header) {
if (!StoresPerVertexAttributes(ctx.stage)) {
return;
}
if (ctx.uses_geometry_passthrough) {
return;
}
header += "out gl_PerVertex{vec4 gl_Position;";
if (ctx.info.stores[IR::Attribute::PointSize]) {
header += "float gl_PointSize;";
}
if (ctx.info.stores.ClipDistances()) {
header += "float gl_ClipDistance[];";
}
if (ctx.info.stores[IR::Attribute::ViewportIndex] &&
ctx.profile.support_viewport_index_layer_non_geometry && ctx.stage != Stage::Geometry) {
header += "int gl_ViewportIndex;";
}
header += "};";
if (ctx.info.stores[IR::Attribute::ViewportIndex] && ctx.stage == Stage::Geometry) {
header += "out int gl_ViewportIndex;";
}
}
void SetupInPerVertex(EmitContext& ctx, std::string& header) {
// Currently only required for TessellationControl to adhere to
// ARB_separate_shader_objects requirements
if (ctx.stage != Stage::TessellationControl) {
return;
}
const bool loads_position{ctx.info.loads.AnyComponent(IR::Attribute::PositionX)};
const bool loads_point_size{ctx.info.loads[IR::Attribute::PointSize]};
const bool loads_clip_distance{ctx.info.loads.ClipDistances()};
const bool loads_per_vertex{loads_position || loads_point_size || loads_clip_distance};
if (!loads_per_vertex) {
return;
}
header += "in gl_PerVertex{";
if (loads_position) {
header += "vec4 gl_Position;";
}
if (loads_point_size) {
header += "float gl_PointSize;";
}
if (loads_clip_distance) {
header += "float gl_ClipDistance[];";
}
header += "}gl_in[gl_MaxPatchVertices];";
}
} // Anonymous namespace } // Anonymous namespace
EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
@ -273,9 +220,8 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
uses_geometry_passthrough{program.is_geometry_passthrough && uses_geometry_passthrough{program.is_geometry_passthrough &&
profile.support_geometry_shader_passthrough} { profile.support_geometry_shader_passthrough} {
if (profile.need_fastmath_off) { if (profile.need_fastmath_off) {
header += "#pragma optionNV(fastmath off)\n"; // TODO
} }
SetupExtensions();
switch (program.stage) { switch (program.stage) {
case Stage::VertexA: case Stage::VertexA:
case Stage::VertexB: case Stage::VertexB:
@ -321,8 +267,9 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
local_x, local_y, local_z); local_x, local_y, local_z);
break; break;
} }
SetupOutPerVertex(*this, header); // TODO
SetupInPerVertex(*this, header); // SetupOutPerVertex(*this, header);
// SetupInPerVertex(*this, header);
for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
if (!info.loads.Generic(index) || !runtime_info.previous_stage_stores.Generic(index)) { if (!info.loads.Generic(index) || !runtime_info.previous_stage_stores.Generic(index)) {
@ -369,63 +316,6 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
DefineConstants(); DefineConstants();
} }
void EmitContext::SetupExtensions() {
header += "#extension GL_ARB_separate_shader_objects : enable\n";
if (info.uses_shadow_lod && profile.support_gl_texture_shadow_lod) {
header += "#extension GL_EXT_texture_shadow_lod : enable\n";
}
if (info.uses_int64 && profile.support_int64) {
header += "#extension GL_ARB_gpu_shader_int64 : enable\n";
}
if (info.uses_int64_bit_atomics) {
header += "#extension GL_NV_shader_atomic_int64 : enable\n";
}
if (info.uses_atomic_f32_add) {
header += "#extension GL_NV_shader_atomic_float : enable\n";
}
if (info.uses_atomic_f16x2_add || info.uses_atomic_f16x2_min || info.uses_atomic_f16x2_max) {
header += "#extension GL_NV_shader_atomic_fp16_vector : enable\n";
}
if (info.uses_fp16) {
if (profile.support_gl_nv_gpu_shader_5) {
header += "#extension GL_NV_gpu_shader5 : enable\n";
}
if (profile.support_gl_amd_gpu_shader_half_float) {
header += "#extension GL_AMD_gpu_shader_half_float : enable\n";
}
}
if (info.uses_subgroup_invocation_id || info.uses_subgroup_mask || info.uses_subgroup_vote ||
info.uses_subgroup_shuffles || info.uses_fswzadd) {
header += "#extension GL_ARB_shader_ballot : enable\n"
"#extension GL_ARB_shader_group_vote : enable\n";
if (!info.uses_int64 && profile.support_int64) {
header += "#extension GL_ARB_gpu_shader_int64 : enable\n";
}
if (profile.support_gl_warp_intrinsics) {
header += "#extension GL_NV_shader_thread_shuffle : enable\n";
}
}
if ((info.stores[IR::Attribute::ViewportIndex] || info.stores[IR::Attribute::Layer]) &&
profile.support_viewport_index_layer_non_geometry && stage != Stage::Geometry) {
header += "#extension GL_ARB_shader_viewport_layer_array : enable\n";
}
if (info.uses_sparse_residency && profile.support_gl_sparse_textures) {
header += "#extension GL_ARB_sparse_texture2 : enable\n";
}
if (info.stores[IR::Attribute::ViewportMask] && profile.support_viewport_mask) {
header += "#extension GL_NV_viewport_array2 : enable\n";
}
if (info.uses_typeless_image_reads) {
header += "#extension GL_EXT_shader_image_load_formatted : enable\n";
}
if (info.uses_derivatives && profile.support_gl_derivative_control) {
header += "#extension GL_ARB_derivative_control : enable\n";
}
if (uses_geometry_passthrough) {
header += "#extension GL_NV_geometry_shader_passthrough : enable\n";
}
}
void EmitContext::DefineConstantBuffers(Bindings& bindings) { void EmitContext::DefineConstantBuffers(Bindings& bindings) {
if (info.constant_buffer_descriptors.empty()) { if (info.constant_buffer_descriptors.empty()) {
return; return;

View file

@ -269,8 +269,19 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
const std::string code{EmitMSL(profile, runtime_info, program, binding)}; const std::string code{EmitMSL(profile, runtime_info, program, binding)};
// HACK // HACK
std::cout << code << std::endl; std::cout << code << std::endl;
// TODO: create MTL::Function MTL::CompileOptions* compile_options = MTL::CompileOptions::alloc()->init();
// functions[stage_index] = ; NS::Error* error = nullptr;
MTL::Library* library = device.GetDevice()->newLibrary(
NS::String::string(code.c_str(), NS::ASCIIStringEncoding), compile_options, &error);
if (error) {
LOG_ERROR(Render_Metal, "failed to create library: {}",
error->description()->cString(NS::ASCIIStringEncoding));
// HACK
throw;
}
functions[index] =
library->newFunction(NS::String::string("main_", NS::ASCIIStringEncoding));
previous_stage = &program; previous_stage = &program;
} }
@ -309,7 +320,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
NS::ASCIIStringEncoding), NS::ASCIIStringEncoding),
compile_options, &error); compile_options, &error);
if (error) { if (error) {
LOG_ERROR(Render_Metal, "failed to create blit library: {}", LOG_ERROR(Render_Metal, "failed to create library: {}",
error->description()->cString(NS::ASCIIStringEncoding)); error->description()->cString(NS::ASCIIStringEncoding));
} }