From patchwork Thu Jul 19 20:00:23 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier Galibert X-Patchwork-Id: 1218361 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id E42AA3FD48 for ; Thu, 19 Jul 2012 20:16:30 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C51449EFCD for ; Thu, 19 Jul 2012 13:16:30 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from sasl.smtp.pobox.com (a-pb-sasl-sd.pobox.com [74.115.168.62]) by gabe.freedesktop.org (Postfix) with ESMTP id 08009A0FCC; Thu, 19 Jul 2012 13:00:23 -0700 (PDT) Received: from sasl.smtp.pobox.com (unknown [127.0.0.1]) by b-pb-sasl-sd.pobox.com (Postfix) with ESMTP id 5C7C7B8F4; Thu, 19 Jul 2012 16:00:22 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=pobox.com; h=from:to:cc :subject:date:message-id:in-reply-to:references; s=sasl; bh=L23I 9VdDxmlDN75O3/6axih/OO8=; b=awkeY+JH2iH+SQMMDXZuy6NlTYUyqz6EiSkz FeIuJrX5NHgvIdzhJwPA26eyu5CsT+dk/au5LdEP5tlVyiOilZqfv5LHrN6eontT RggAiSfetIx6rpP/v9DSmISG30nBC4915cCn1rUJkqfm0t2IHrunniDu6807MPS4 A+/B3Pw= DomainKey-Signature: a=rsa-sha1; c=nofws; d=pobox.com; h=from:to:cc :subject:date:message-id:in-reply-to:references; q=dns; s=sasl; b= jlpbRmv2qDbq8mdC7eRbET5jZ5FH4SuX7Le2qDJzwzdgmrqPR5ESOQ4DaDRTpb6H k8WLwGTGr3thMZ+tEwGwrp7vP5KA3jCgvOiTa4hfLpJbXcrAfHjD/IBB85lI5f5F +DYKGyT5ZaTt2HjHf6JRAeaW3/4B5GpwS9bLzcUoS44= Received: from b-pb-sasl-sd. (unknown [127.0.0.1]) by b-pb-sasl-sd.pobox.com (Postfix) with ESMTP id 4DD15B8F3; Thu, 19 Jul 2012 16:00:22 -0400 (EDT) Received: from localhost.localdomain (unknown [82.234.121.82]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by b-pb-sasl-sd.pobox.com (Postfix) with ESMTPSA id C69E4B8EE; Thu, 19 Jul 2012 16:00:18 -0400 (EDT) From: Olivier Galibert To: intel-gfx@lists.freedesktop.org, mesa-dev@lists.freedesktop.org Date: Thu, 19 Jul 2012 22:00:23 +0200 Message-Id: <1342728024-15055-9-git-send-email-galibert@pobox.com> X-Mailer: git-send-email 1.7.10.280.gaa39 In-Reply-To: <1342728024-15055-1-git-send-email-galibert@pobox.com> References: <1342728024-15055-1-git-send-email-galibert@pobox.com> X-Pobox-Relay-ID: 5E5FF13C-D1DC-11E1-8B5C-126B87E41631-92059326!b-pb-sasl-sd.pobox.com Cc: Olivier Galibert Subject: [Intel-gfx] [PATCH 8/9] intel gen4-5: Make noperspective clipping work. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org At this point all interpolation tests with fixed clipping work. Signed-off-by: Olivier Galibert Reviewed-by: Paul Berry --- src/mesa/drivers/dri/i965/brw_clip.c | 9 ++ src/mesa/drivers/dri/i965/brw_clip.h | 1 + src/mesa/drivers/dri/i965/brw_clip_util.c | 147 ++++++++++++++++++++++++++--- 3 files changed, 146 insertions(+), 11 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_clip.c b/src/mesa/drivers/dri/i965/brw_clip.c index 8512172..eca2844 100644 --- a/src/mesa/drivers/dri/i965/brw_clip.c +++ b/src/mesa/drivers/dri/i965/brw_clip.c @@ -239,6 +239,15 @@ brw_upload_clip_prog(struct brw_context *brw) break; } } + key.has_noperspective_shading = 0; + for (i = 0; i < BRW_VERT_RESULT_MAX; i++) { + if (brw->interpolation_mode[i] == INTERP_QUALIFIER_NOPERSPECTIVE && + brw->vs.prog_data->vue_map.slot_to_vert_result[i] != VERT_RESULT_HPOS) { + key.has_noperspective_shading = 1; + break; + } + } + key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION); memcpy(key.interpolation_mode, brw->interpolation_mode, BRW_VERT_RESULT_MAX); diff --git a/src/mesa/drivers/dri/i965/brw_clip.h b/src/mesa/drivers/dri/i965/brw_clip.h index 3ad2e13..66dd928 100644 --- a/src/mesa/drivers/dri/i965/brw_clip.h +++ b/src/mesa/drivers/dri/i965/brw_clip.h @@ -47,6 +47,7 @@ struct brw_clip_prog_key { GLuint primitive:4; GLuint nr_userclip:4; GLuint has_flat_shading:1; + GLuint has_noperspective_shading:1; GLuint pv_first:1; GLuint do_unfilled:1; GLuint fill_cw:2; /* includes cull information */ diff --git a/src/mesa/drivers/dri/i965/brw_clip_util.c b/src/mesa/drivers/dri/i965/brw_clip_util.c index 692573e..b06ad1d 100644 --- a/src/mesa/drivers/dri/i965/brw_clip_util.c +++ b/src/mesa/drivers/dri/i965/brw_clip_util.c @@ -129,6 +129,8 @@ static void brw_clip_project_vertex( struct brw_clip_compile *c, /* Interpolate between two vertices and put the result into a0.0. * Increment a0.0 accordingly. + * + * Beware that dest_ptr can be equal to v0_ptr. */ void brw_clip_interp_vertex( struct brw_clip_compile *c, struct brw_indirect dest_ptr, @@ -138,7 +140,8 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c, bool force_edgeflag) { struct brw_compile *p = &c->func; - struct brw_reg tmp = get_tmp(c); + struct brw_context *brw = p->brw; + struct brw_reg t_nopersp, v0_ndc_copy; GLuint slot; /* Just copy the vertex header: @@ -148,13 +151,130 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c, * back on Ironlake, so needn't change it */ brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1); - - /* Iterate over each attribute (could be done in pairs?) + + /* + * First handle the 3D and NDC positioning, in case we need + * noperspective interpolation. Doing it early has no performance + * impact in any case. + */ + + /* Start by picking up the v0 NDC coordinates, because that vertex + * may be shared with the destination. + */ + if (c->key.has_noperspective_shading) { + GLuint offset = brw_vert_result_to_offset(&c->vue_map, + BRW_VERT_RESULT_NDC); + v0_ndc_copy = get_tmp(c); + brw_MOV(p, v0_ndc_copy, deref_4f(v0_ptr, offset)); + } + + /* + * Compute the new 3D position + * + * dest_hpos = v0_hpos * (1 - t0) + v1_hpos * t0 + */ + { + GLuint delta = brw_vert_result_to_offset(&c->vue_map, VERT_RESULT_HPOS); + struct brw_reg tmp = get_tmp(c); + brw_MUL(p, + vec4(brw_null_reg()), + deref_4f(v1_ptr, delta), + t0); + + brw_MAC(p, + tmp, + negate(deref_4f(v0_ptr, delta)), + t0); + + brw_ADD(p, + deref_4f(dest_ptr, delta), + deref_4f(v0_ptr, delta), + tmp); + release_tmp(c, tmp); + } + + /* Then recreate the projected (NDC) coordinate in the new vertex + * header + */ + brw_clip_project_vertex(c, dest_ptr); + + /* + * If we have noperspective attributes, we now need to compute the + * screen-space t. + */ + if (c->key.has_noperspective_shading) { + GLuint delta = brw_vert_result_to_offset(&c->vue_map, BRW_VERT_RESULT_NDC); + struct brw_reg tmp = get_tmp(c); + t_nopersp = get_tmp(c); + + /* Build a register with coordinates from the second and new vertices + * + * t_nopersp = vec4(v1.xy, dest.xy) + */ + brw_MOV(p, t_nopersp, deref_4f(v1_ptr, delta)); + brw_MOV(p, tmp, deref_4f(dest_ptr, delta)); + brw_set_access_mode(p, BRW_ALIGN_16); + brw_MOV(p, + brw_writemask(t_nopersp, WRITEMASK_ZW), + brw_swizzle(tmp, 0,1,0,1)); + + /* Subtract the coordinates of the first vertex + * + * t_nopersp = vec4(v1.xy, dest.xy) - v0.xyxy + */ + brw_ADD(p, t_nopersp, t_nopersp, negate(brw_swizzle(v0_ndc_copy, 0,1,0,1))); + + /* Add the absolute value of the X and Y deltas so that if the + * points aren't in the same place on the screen we get non-zero + * values to divide. + * + * After that we have vert1-vert0 in t_nopersp.x and vertnew-vert0 in t_nopersp.y. + * + * t_nopersp = vec2(|v1.x -v0.x| + |v1.y -v0.y|, + * |dest.x-v0.x| + |dest.y-v0.y|) + */ + brw_ADD(p, + brw_writemask(t_nopersp, WRITEMASK_XY), + brw_abs(brw_swizzle(t_nopersp, 0,2,0,0)), + brw_abs(brw_swizzle(t_nopersp, 1,3,0,0))); + brw_set_access_mode(p, BRW_ALIGN_1); + + /* If the points are in the same place (vert1-vert0 == 0), just + * substitute a value that will ensure that we don't divide by + * 0. + */ + brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, + vec1(t_nopersp), + brw_imm_f(0)); + brw_IF(p, BRW_EXECUTE_1); + brw_MOV(p, t_nopersp, brw_imm_vf4(VF_ONE, VF_ZERO, VF_ZERO, VF_ZERO)); + brw_ENDIF(p); + + /* Now compute t_nopersp = t_nopersp.y/t_nopersp.x and broadcast it */ + brw_math_invert(p, get_element(t_nopersp, 0), get_element(t_nopersp, 0)); + brw_MUL(p, + vec1(t_nopersp), + vec1(t_nopersp), + vec1(suboffset(t_nopersp, 1))); + brw_set_access_mode(p, BRW_ALIGN_16); + brw_MOV(p, t_nopersp, brw_swizzle(t_nopersp, 0,0,0,0)); + brw_set_access_mode(p, BRW_ALIGN_1); + + release_tmp(c, tmp); + release_tmp(c, v0_ndc_copy); + } + + /* Now we can iterate over each attribute + * (could be done in pairs?) */ for (slot = 0; slot < c->vue_map.num_slots; slot++) { int vert_result = c->vue_map.slot_to_vert_result[slot]; GLuint delta = brw_vue_slot_to_offset(slot); + /* HPOS is already handled */ + if(vert_result == VERT_RESULT_HPOS) + continue; + if (vert_result == VERT_RESULT_EDGE) { if (force_edgeflag) brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1)); @@ -174,20 +294,29 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c, * * New = attr0 + t*attr1 - t*attr0 */ + + struct brw_reg tmp = get_tmp(c); + + struct brw_reg t = + brw->interpolation_mode[slot] == INTERP_QUALIFIER_NOPERSPECTIVE ? + t_nopersp : t0; + brw_MUL(p, vec4(brw_null_reg()), deref_4f(v1_ptr, delta), - t0); + t); brw_MAC(p, tmp, negate(deref_4f(v0_ptr, delta)), - t0); + t); brw_ADD(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta), tmp); + + release_tmp(c, tmp); } } @@ -197,12 +326,8 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c, brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0)); } - release_tmp(c, tmp); - - /* Recreate the projected (NDC) coordinate in the new vertex - * header: - */ - brw_clip_project_vertex(c, dest_ptr ); + if (c->key.has_noperspective_shading) + release_tmp(c, t_nopersp); } void brw_clip_emit_vue(struct brw_clip_compile *c,