glsl: skip gl_ViewportIndex write if device does not support it

master
ameerj 2021-06-02 00:48:49 +07:00
parent f4799e8fa1
commit 6577a63d36
5 changed files with 18 additions and 8 deletions

@ -148,23 +148,24 @@ std::string_view OutputPrimitive(OutputTopology topology) {
throw InvalidArgument("Invalid output topology {}", topology); throw InvalidArgument("Invalid output topology {}", topology);
} }
void SetupOutPerVertex(Stage stage, const Info& info, std::string& header) { void SetupOutPerVertex(EmitContext& ctx, std::string& header) {
if (!StoresPerVertexAttributes(stage)) { if (!StoresPerVertexAttributes(ctx.stage)) {
return; return;
} }
header += "out gl_PerVertex{"; header += "out gl_PerVertex{";
header += "vec4 gl_Position;"; header += "vec4 gl_Position;";
if (info.stores_point_size) { if (ctx.info.stores_point_size) {
header += "float gl_PointSize;"; header += "float gl_PointSize;";
} }
if (info.stores_clip_distance) { if (ctx.info.stores_clip_distance) {
header += "float gl_ClipDistance[];"; header += "float gl_ClipDistance[];";
} }
if (info.stores_viewport_index && stage != Stage::Geometry) { if (ctx.info.stores_viewport_index && ctx.supports_viewport_layer &&
ctx.stage != Stage::Geometry) {
header += "int gl_ViewportIndex;"; header += "int gl_ViewportIndex;";
} }
header += "};\n"; header += "};\n";
if (info.stores_viewport_index && stage == Stage::Geometry) { if (ctx.info.stores_viewport_index && ctx.stage == Stage::Geometry) {
header += "out int gl_ViewportIndex;"; header += "out int gl_ViewportIndex;";
} }
} }
@ -173,6 +174,7 @@ void SetupOutPerVertex(Stage stage, const Info& info, std::string& header) {
EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_, EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
const RuntimeInfo& runtime_info_) const RuntimeInfo& runtime_info_)
: info{program.info}, profile{profile_}, runtime_info{runtime_info_} { : info{program.info}, profile{profile_}, runtime_info{runtime_info_} {
supports_viewport_layer = profile.support_gl_vertex_viewport_layer;
SetupExtensions(header); SetupExtensions(header);
stage = program.stage; stage = program.stage;
switch (program.stage) { switch (program.stage) {
@ -206,7 +208,7 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
program.workgroup_size[2]); program.workgroup_size[2]);
break; break;
} }
SetupOutPerVertex(stage, info, header); SetupOutPerVertex(*this, header);
for (size_t index = 0; index < info.input_generics.size(); ++index) { for (size_t index = 0; index < info.input_generics.size(); ++index) {
const auto& generic{info.input_generics[index]}; const auto& generic{info.input_generics[index]};
if (generic.used) { if (generic.used) {
@ -276,7 +278,7 @@ void EmitContext::SetupExtensions(std::string&) {
header += "#extension GL_ARB_gpu_shader_int64 : enable\n"; header += "#extension GL_ARB_gpu_shader_int64 : enable\n";
} }
} }
if (info.stores_viewport_index && stage != Stage::Geometry) { if (info.stores_viewport_index && supports_viewport_layer && stage != Stage::Geometry) {
header += "#extension GL_ARB_shader_viewport_layer_array : enable\n"; header += "#extension GL_ARB_shader_viewport_layer_array : enable\n";
} }
} }

@ -159,6 +159,7 @@ public:
bool uses_y_direction{}; bool uses_y_direction{};
bool uses_cc_carry{}; bool uses_cc_carry{};
bool supports_viewport_layer{};
private: private:
void SetupExtensions(std::string& header); void SetupExtensions(std::string& header);

@ -226,6 +226,11 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val
ctx.Add("gl_Position.{}={};", swizzle, value); ctx.Add("gl_Position.{}={};", swizzle, value);
break; break;
case IR::Attribute::ViewportIndex: case IR::Attribute::ViewportIndex:
if (ctx.stage != Stage::Geometry && !ctx.supports_viewport_layer) {
// LOG_WARNING(..., "Shader stores viewport index but device does not support viewport
// layer extension");
break;
}
ctx.Add("gl_ViewportIndex=floatBitsToInt({});", value); ctx.Add("gl_ViewportIndex=floatBitsToInt({});", value);
break; break;
case IR::Attribute::ClipDistance0: case IR::Attribute::ClipDistance0:

@ -85,6 +85,7 @@ struct Profile {
bool support_derivative_control{}; bool support_derivative_control{};
bool support_gl_nv_gpu_shader_5{}; bool support_gl_nv_gpu_shader_5{};
bool support_gl_amd_gpu_shader_half_float{}; bool support_gl_amd_gpu_shader_half_float{};
bool support_gl_vertex_viewport_layer{};
bool warp_size_potentially_larger_than_guest{}; bool warp_size_potentially_larger_than_guest{};

@ -225,6 +225,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
.support_derivative_control = device.HasDerivativeControl(), .support_derivative_control = device.HasDerivativeControl(),
.support_gl_nv_gpu_shader_5 = device.HasNvGpuShader5(), .support_gl_nv_gpu_shader_5 = device.HasNvGpuShader5(),
.support_gl_amd_gpu_shader_half_float = device.HasAmdShaderHalfFloat(), .support_gl_amd_gpu_shader_half_float = device.HasAmdShaderHalfFloat(),
.support_gl_vertex_viewport_layer = device.HasVertexViewportLayer(),
.warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyLargerThanGuest(), .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyLargerThanGuest(),