diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 2 | ||||
| -rw-r--r-- | src/video_core/engines/shader_header.h | 11 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 66 | 
3 files changed, 58 insertions, 21 deletions
| diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 7e8449bc4..639bedb80 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -82,6 +82,8 @@ union Attribute {          Position = 7,          Attribute_0 = 8,          Attribute_31 = 39, +        ClipDistances0123 = 44, +        ClipDistances4567 = 45,          PointCoord = 46,          // This attribute contains a tuple of (~, ~, InstanceId, VertexId) when inside a vertex          // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval diff --git a/src/video_core/engines/shader_header.h b/src/video_core/engines/shader_header.h index a0e015c4b..99c34649f 100644 --- a/src/video_core/engines/shader_header.h +++ b/src/video_core/engines/shader_header.h @@ -62,7 +62,16 @@ struct Header {              INSERT_PADDING_BYTES(1);  // ImapSystemValuesB              INSERT_PADDING_BYTES(16); // ImapGenericVector[32]              INSERT_PADDING_BYTES(2);  // ImapColor -            INSERT_PADDING_BYTES(2);  // ImapSystemValuesC +            union { +                BitField<0, 8, u16> clip_distances; +                BitField<8, 1, u16> point_sprite_s; +                BitField<9, 1, u16> point_sprite_t; +                BitField<10, 1, u16> fog_coordinate; +                BitField<12, 1, u16> tessellation_eval_point_u; +                BitField<13, 1, u16> tessellation_eval_point_v; +                BitField<14, 1, u16> instance_id; +                BitField<15, 1, u16> vertex_id; +            };              INSERT_PADDING_BYTES(5);  // ImapFixedFncTexture[10]              INSERT_PADDING_BYTES(1);  // ImapReserved              INSERT_PADDING_BYTES(3);  // OmapSystemValuesA diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 97b9028c5..3b7841715 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -500,27 +500,42 @@ public:                                        const Register& buf_reg) {          const std::string dest = GetOutputAttribute(attribute);          const std::string src = GetRegisterAsFloat(val_reg); +        if (dest.empty()) +            return; -        if (!dest.empty()) { -            // Can happen with unknown/unimplemented output attributes, in which case we ignore the -            // instruction for now. -            if (stage == Maxwell3D::Regs::ShaderStage::Geometry) { -                // TODO(Rodrigo): nouveau sets some attributes after setting emitting a geometry -                // shader. These instructions use a dirty register as buffer index, to avoid some -                // drivers from complaining about out of boundary writes, guard them. -                const std::string buf_index{"((" + GetRegisterAsInteger(buf_reg) + ") % " + -                                            std::to_string(MAX_GEOMETRY_BUFFERS) + ')'}; -                shader.AddLine("amem[" + buf_index + "][" + -                               std::to_string(static_cast<u32>(attribute)) + ']' + -                               GetSwizzle(elem) + " = " + src + ';'); -            } else { -                if (attribute == Attribute::Index::PointSize) { -                    fixed_pipeline_output_attributes_used.insert(attribute); -                    shader.AddLine(dest + " = " + src + ';'); -                } else { -                    shader.AddLine(dest + GetSwizzle(elem) + " = " + src + ';'); -                } -            } +        // Can happen with unknown/unimplemented output attributes, in which case we ignore the +        // instruction for now. +        if (stage == Maxwell3D::Regs::ShaderStage::Geometry) { +            // TODO(Rodrigo): nouveau sets some attributes after setting emitting a geometry +            // shader. These instructions use a dirty register as buffer index, to avoid some +            // drivers from complaining about out of boundary writes, guard them. +            const std::string buf_index{"((" + GetRegisterAsInteger(buf_reg) + ") % " + +                                        std::to_string(MAX_GEOMETRY_BUFFERS) + ')'}; +            shader.AddLine("amem[" + buf_index + "][" + +                           std::to_string(static_cast<u32>(attribute)) + ']' + GetSwizzle(elem) + +                           " = " + src + ';'); +            return; +        } + +        switch (attribute) { +        case Attribute::Index::ClipDistances0123: +        case Attribute::Index::ClipDistances4567: { +            const u64 index = attribute == Attribute::Index::ClipDistances4567 ? 4 : 0 + elem; +            UNIMPLEMENTED_IF_MSG( +                ((header.vtg.clip_distances >> index) & 1) == 0, +                "Shader is setting gl_ClipDistance{} without enabling it in the header", index); + +            fixed_pipeline_output_attributes_used.insert(attribute); +            shader.AddLine(dest + '[' + std::to_string(index) + "] = " + src + ';'); +            break; +        } +        case Attribute::Index::PointSize: +            fixed_pipeline_output_attributes_used.insert(attribute); +            shader.AddLine(dest + " = " + src + ';'); +            break; +        default: +            shader.AddLine(dest + GetSwizzle(elem) + " = " + src + ';'); +            break;          }      } @@ -740,12 +755,19 @@ private:      void GenerateVertex() {          if (stage != Maxwell3D::Regs::ShaderStage::Vertex)              return; +        bool clip_distances_declared = false; +          declarations.AddLine("out gl_PerVertex {");          ++declarations.scope;          declarations.AddLine("vec4 gl_Position;");          for (auto& o : fixed_pipeline_output_attributes_used) {              if (o == Attribute::Index::PointSize)                  declarations.AddLine("float gl_PointSize;"); +            if (!clip_distances_declared && (o == Attribute::Index::ClipDistances0123 || +                                             o == Attribute::Index::ClipDistances4567)) { +                declarations.AddLine("float gl_ClipDistance[];"); +                clip_distances_declared = true; +            }          }          --declarations.scope;          declarations.AddLine("};"); @@ -916,6 +938,10 @@ private:              return "gl_PointSize";          case Attribute::Index::Position:              return "position"; +        case Attribute::Index::ClipDistances0123: +        case Attribute::Index::ClipDistances4567: { +            return "gl_ClipDistance"; +        }          default:              const u32 index{static_cast<u32>(attribute) -                              static_cast<u32>(Attribute::Index::Attribute_0)}; | 
