lp_bld_depth.c revision 1fc41002252419f4688c24ea8c3814553b3d76ad
1/**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28/**
29 * @file
30 * Depth/stencil testing to LLVM IR translation.
31 *
32 * To be done accurately/efficiently the depth/stencil test must be done with
33 * the same type/format of the depth/stencil buffer, which implies massaging
34 * the incoming depths to fit into place. Using a more straightforward
35 * type/format for depth/stencil values internally and only convert when
36 * flushing would avoid this, but it would most likely result in depth fighting
37 * artifacts.
38 *
39 * We are free to use a different pixel layout though. Since our basic
40 * processing unit is a quad (2x2 pixel block) we store the depth/stencil
41 * values tiled, a quad at time. That is, a depth buffer containing
42 *
43 *  Z11 Z12 Z13 Z14 ...
44 *  Z21 Z22 Z23 Z24 ...
45 *  Z31 Z32 Z33 Z34 ...
46 *  Z41 Z42 Z43 Z44 ...
47 *  ... ... ... ... ...
48 *
49 * will actually be stored in memory as
50 *
51 *  Z11 Z12 Z21 Z22 Z13 Z14 Z23 Z24 ...
52 *  Z31 Z32 Z41 Z42 Z33 Z34 Z43 Z44 ...
53 *  ... ... ... ... ... ... ... ... ...
54 *
55 * FIXME: Code generate stencil test
56 *
57 * @author Jose Fonseca <jfonseca@vmware.com>
58 */
59
60#include "pipe/p_state.h"
61#include "util/u_format.h"
62
63#include "lp_bld_type.h"
64#include "lp_bld_const.h"
65#include "lp_bld_logic.h"
66#include "lp_bld_flow.h"
67#include "lp_bld_debug.h"
68#include "lp_bld_depth.h"
69
70
71/**
72 * Return a type appropriate for depth/stencil testing.
73 */
74union lp_type
75lp_depth_type(const struct util_format_description *format_desc,
76              unsigned length)
77{
78   union lp_type type;
79   unsigned swizzle;
80
81   assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS);
82   assert(format_desc->block.width == 1);
83   assert(format_desc->block.height == 1);
84
85   swizzle = format_desc->swizzle[0];
86   assert(swizzle < 4);
87
88   type.value = 0;
89   type.width = format_desc->block.bits;
90
91   if(format_desc->channel[swizzle].type == UTIL_FORMAT_TYPE_FLOAT) {
92      type.floating = TRUE;
93      assert(swizzle = 0);
94      assert(format_desc->channel[swizzle].size == format_desc->block.bits);
95   }
96   else if(format_desc->channel[swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED) {
97      assert(format_desc->block.bits <= 32);
98      if(format_desc->channel[swizzle].normalized)
99         type.norm = TRUE;
100   }
101   else
102      assert(0);
103
104   assert(type.width <= length);
105   type.length = length / type.width;
106
107   return type;
108}
109
110
111/**
112 * Depth test.
113 */
114void
115lp_build_depth_test(LLVMBuilderRef builder,
116                    const struct pipe_depth_state *state,
117                    union lp_type type,
118                    const struct util_format_description *format_desc,
119                    struct lp_build_mask_context *mask,
120                    LLVMValueRef src,
121                    LLVMValueRef dst_ptr)
122{
123   struct lp_build_context bld;
124   unsigned z_swizzle;
125   LLVMValueRef dst;
126   LLVMValueRef z_bitmask = NULL;
127   LLVMValueRef test;
128
129   if(!state->enabled)
130      return;
131
132   assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS);
133   assert(format_desc->block.width == 1);
134   assert(format_desc->block.height == 1);
135
136   z_swizzle = format_desc->swizzle[0];
137   if(z_swizzle == UTIL_FORMAT_SWIZZLE_NONE)
138      return;
139
140   /* Sanity checking */
141   assert(z_swizzle < 4);
142   assert(format_desc->block.bits == type.width);
143   if(type.floating) {
144      assert(z_swizzle == 0);
145      assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_FLOAT);
146      assert(format_desc->channel[z_swizzle].size == format_desc->block.bits);
147   }
148   else {
149      assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED);
150      assert(format_desc->channel[z_swizzle].normalized);
151      assert(!type.fixed);
152      assert(!type.sign);
153      assert(type.norm);
154   }
155
156   /* Setup build context */
157   lp_build_context_init(&bld, builder, type);
158
159   dst = LLVMBuildLoad(builder, dst_ptr, "");
160
161   lp_build_name(dst, "zsbuf");
162
163   /* Align the source depth bits with the destination's, and mask out any
164    * stencil or padding bits from both */
165   if(format_desc->channel[z_swizzle].size == format_desc->block.bits) {
166      assert(z_swizzle == 0);
167      /* nothing to do */
168   }
169   else {
170      unsigned padding_left;
171      unsigned padding_right;
172      unsigned chan;
173
174      assert(format_desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
175      assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED);
176      assert(format_desc->channel[z_swizzle].size <= format_desc->block.bits);
177      assert(format_desc->channel[z_swizzle].normalized);
178
179      padding_right = 0;
180      for(chan = 0; chan < z_swizzle; ++chan)
181         padding_right += format_desc->channel[chan].size;
182      padding_left = format_desc->block.bits -
183                     (padding_right + format_desc->channel[z_swizzle].size);
184
185      if(padding_left || padding_right) {
186         const unsigned long long mask_left = ((unsigned long long)1 << (format_desc->block.bits - padding_left)) - 1;
187         const unsigned long long mask_right = ((unsigned long long)1 << (padding_right)) - 1;
188         z_bitmask = lp_build_int_const_scalar(type, mask_left ^ mask_right);
189      }
190
191      if(padding_left)
192         src = LLVMBuildLShr(builder, src, lp_build_int_const_scalar(type, padding_left), "");
193      if(padding_right)
194         src = LLVMBuildAnd(builder, src, z_bitmask, "");
195      if(padding_left || padding_right)
196         dst = LLVMBuildAnd(builder, dst, z_bitmask, "");
197   }
198
199   lp_build_name(dst, "zsbuf.z");
200
201   test = lp_build_cmp(&bld, state->func, src, dst);
202   lp_build_mask_update(mask, test);
203
204   if(state->writemask) {
205      if(z_bitmask)
206         z_bitmask = LLVMBuildAnd(builder, mask->value, z_bitmask, "");
207      else
208         z_bitmask = mask->value;
209
210      dst = lp_build_select(&bld, z_bitmask, src, dst);
211      LLVMBuildStore(builder, dst, dst_ptr);
212   }
213
214   /* FIXME */
215   assert(!state->occlusion_count);
216}
217