Merge pull request #1783 from ReinUsesLisp/clip-distances
gl_shader_decompiler: Implement clip distances
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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)};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user