gallium: change pipe_sampler_view::first_element/last_element -> offset/size
[mesa.git] / src / gallium / drivers / svga / svga_state_sampler.c
1 /*
2 * Copyright 2013 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25
26 /**
27 * VGPU10 sampler and sampler view functions.
28 */
29
30
31 #include "pipe/p_defines.h"
32 #include "util/u_bitmask.h"
33 #include "util/u_format.h"
34 #include "util/u_inlines.h"
35 #include "util/u_math.h"
36 #include "util/u_memory.h"
37
38 #include "svga_cmd.h"
39 #include "svga_context.h"
40 #include "svga_format.h"
41 #include "svga_resource_buffer.h"
42 #include "svga_resource_texture.h"
43 #include "svga_shader.h"
44 #include "svga_state.h"
45 #include "svga_sampler_view.h"
46
47
48 /** Get resource handle for a texture or buffer */
49 static inline struct svga_winsys_surface *
50 svga_resource_handle(struct pipe_resource *res)
51 {
52 if (res->target == PIPE_BUFFER) {
53 return svga_buffer(res)->handle;
54 }
55 else {
56 return svga_texture(res)->handle;
57 }
58 }
59
60
61 /**
62 * This helper function returns TRUE if the specified resource collides with
63 * any of the resources bound to any of the currently bound sampler views.
64 */
65 boolean
66 svga_check_sampler_view_resource_collision(struct svga_context *svga,
67 struct svga_winsys_surface *res,
68 unsigned shader)
69 {
70 struct pipe_screen *screen = svga->pipe.screen;
71 unsigned i;
72
73 if (svga_screen(screen)->debug.no_surface_view) {
74 return FALSE;
75 }
76
77 for (i = 0; i < svga->curr.num_sampler_views[shader]; i++) {
78 struct svga_pipe_sampler_view *sv =
79 svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]);
80
81 if (sv && res == svga_resource_handle(sv->base.texture)) {
82 return TRUE;
83 }
84 }
85
86 return FALSE;
87 }
88
89
90 /**
91 * Create a DX ShaderResourceSamplerView for the given pipe_sampler_view,
92 * if needed.
93 */
94 enum pipe_error
95 svga_validate_pipe_sampler_view(struct svga_context *svga,
96 struct svga_pipe_sampler_view *sv)
97 {
98 enum pipe_error ret = PIPE_OK;
99
100 if (sv->id == SVGA3D_INVALID_ID) {
101 struct svga_screen *ss = svga_screen(svga->pipe.screen);
102 struct pipe_resource *texture = sv->base.texture;
103 struct svga_winsys_surface *surface = svga_resource_handle(texture);
104 SVGA3dSurfaceFormat format;
105 SVGA3dResourceType resourceDim;
106 SVGA3dShaderResourceViewDesc viewDesc;
107 enum pipe_format pformat = sv->base.format;
108
109 /* vgpu10 cannot create a BGRX view for a BGRA resource, so force it to
110 * create a BGRA view (and vice versa).
111 */
112 if (pformat == PIPE_FORMAT_B8G8R8X8_UNORM &&
113 sv->base.texture->format == PIPE_FORMAT_B8G8R8A8_UNORM) {
114 pformat = PIPE_FORMAT_B8G8R8A8_UNORM;
115 }
116 else if (pformat == PIPE_FORMAT_B8G8R8A8_UNORM &&
117 sv->base.texture->format == PIPE_FORMAT_B8G8R8X8_UNORM) {
118 pformat = PIPE_FORMAT_B8G8R8X8_UNORM;
119 }
120
121 format = svga_translate_format(ss, pformat,
122 PIPE_BIND_SAMPLER_VIEW);
123 assert(format != SVGA3D_FORMAT_INVALID);
124
125 /* Convert the format to a sampler-friendly format, if needed */
126 format = svga_sampler_format(format);
127
128 if (texture->target == PIPE_BUFFER) {
129 unsigned elem_size = util_format_get_blocksize(sv->base.format);
130
131 viewDesc.buffer.firstElement = sv->base.u.buf.offset / elem_size;
132 viewDesc.buffer.numElements = sv->base.u.buf.size / elem_size;
133 }
134 else {
135 viewDesc.tex.mostDetailedMip = sv->base.u.tex.first_level;
136 viewDesc.tex.firstArraySlice = sv->base.u.tex.first_layer;
137 viewDesc.tex.mipLevels = (sv->base.u.tex.last_level -
138 sv->base.u.tex.first_level + 1);
139 }
140
141 /* arraySize in viewDesc specifies the number of array slices in a
142 * texture array. For 3D texture, last_layer in
143 * pipe_sampler_view specifies the last slice of the texture
144 * which is different from the last slice in a texture array,
145 * hence we need to set arraySize to 1 explicitly.
146 */
147 viewDesc.tex.arraySize =
148 (texture->target == PIPE_TEXTURE_3D ||
149 texture->target == PIPE_BUFFER) ? 1 :
150 (sv->base.u.tex.last_layer - sv->base.u.tex.first_layer + 1);
151
152 switch (texture->target) {
153 case PIPE_BUFFER:
154 resourceDim = SVGA3D_RESOURCE_BUFFER;
155 break;
156 case PIPE_TEXTURE_1D:
157 case PIPE_TEXTURE_1D_ARRAY:
158 resourceDim = SVGA3D_RESOURCE_TEXTURE1D;
159 break;
160 case PIPE_TEXTURE_RECT:
161 case PIPE_TEXTURE_2D:
162 case PIPE_TEXTURE_2D_ARRAY:
163 resourceDim = SVGA3D_RESOURCE_TEXTURE2D;
164 break;
165 case PIPE_TEXTURE_3D:
166 resourceDim = SVGA3D_RESOURCE_TEXTURE3D;
167 break;
168 case PIPE_TEXTURE_CUBE:
169 case PIPE_TEXTURE_CUBE_ARRAY:
170 resourceDim = SVGA3D_RESOURCE_TEXTURECUBE;
171 break;
172
173 default:
174 assert(!"Unexpected texture type");
175 resourceDim = SVGA3D_RESOURCE_TEXTURE2D;
176 }
177
178 sv->id = util_bitmask_add(svga->sampler_view_id_bm);
179
180 ret = SVGA3D_vgpu10_DefineShaderResourceView(svga->swc,
181 sv->id,
182 surface,
183 format,
184 resourceDim,
185 &viewDesc);
186 if (ret != PIPE_OK) {
187 util_bitmask_clear(svga->sampler_view_id_bm, sv->id);
188 sv->id = SVGA3D_INVALID_ID;
189 }
190 }
191
192 return ret;
193 }
194
195
196 static enum pipe_error
197 update_sampler_resources(struct svga_context *svga, unsigned dirty)
198 {
199 enum pipe_error ret = PIPE_OK;
200 unsigned shader;
201
202 if (!svga_have_vgpu10(svga))
203 return PIPE_OK;
204
205 for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
206 SVGA3dShaderResourceViewId ids[PIPE_MAX_SAMPLERS];
207 struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS];
208 unsigned count;
209 unsigned nviews;
210 unsigned i;
211
212 count = svga->curr.num_sampler_views[shader];
213 for (i = 0; i < count; i++) {
214 struct svga_pipe_sampler_view *sv =
215 svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]);
216 struct svga_winsys_surface *surface;
217
218 if (sv) {
219 surface = svga_resource_handle(sv->base.texture);
220
221 ret = svga_validate_pipe_sampler_view(svga, sv);
222 if (ret != PIPE_OK)
223 return ret;
224
225 assert(sv->id != SVGA3D_INVALID_ID);
226 ids[i] = sv->id;
227 }
228 else {
229 surface = NULL;
230 ids[i] = SVGA3D_INVALID_ID;
231 }
232 surfaces[i] = surface;
233 }
234
235 for (; i < ARRAY_SIZE(ids); i++) {
236 ids[i] = SVGA3D_INVALID_ID;
237 surfaces[i] = NULL;
238 }
239
240 if (shader == PIPE_SHADER_FRAGMENT) {
241 /* Handle polygon stipple sampler view */
242 if (svga->curr.rast->templ.poly_stipple_enable) {
243 const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
244 struct svga_pipe_sampler_view *sv =
245 svga->polygon_stipple.sampler_view;
246
247 assert(sv);
248 if (!sv) {
249 return PIPE_OK; /* probably out of memory */
250 }
251
252 ret = svga_validate_pipe_sampler_view(svga, sv);
253 if (ret != PIPE_OK)
254 return ret;
255
256 ids[unit] = sv->id;
257 surfaces[unit] = svga_resource_handle(sv->base.texture);
258 count = MAX2(count, unit+1);
259 }
260 }
261
262 /* Number of ShaderResources that need to be modified. This includes
263 * the one that need to be unbound.
264 */
265 nviews = MAX2(svga->state.hw_draw.num_sampler_views[shader], count);
266 if (nviews > 0) {
267 ret = SVGA3D_vgpu10_SetShaderResources(svga->swc,
268 svga_shader_type(shader),
269 0, /* startView */
270 nviews,
271 ids,
272 surfaces);
273 if (ret != PIPE_OK)
274 return ret;
275 }
276
277 /* Number of sampler views enabled in the device */
278 svga->state.hw_draw.num_sampler_views[shader] = count;
279 }
280
281 return ret;
282 }
283
284
285 struct svga_tracked_state svga_hw_sampler_bindings = {
286 "shader resources emit",
287 SVGA_NEW_STIPPLE |
288 SVGA_NEW_TEXTURE_BINDING,
289 update_sampler_resources
290 };
291
292
293
294 static enum pipe_error
295 update_samplers(struct svga_context *svga, unsigned dirty )
296 {
297 enum pipe_error ret = PIPE_OK;
298 unsigned shader;
299
300 if (!svga_have_vgpu10(svga))
301 return PIPE_OK;
302
303 for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
304 const unsigned count = svga->curr.num_samplers[shader];
305 SVGA3dSamplerId ids[PIPE_MAX_SAMPLERS];
306 unsigned i;
307
308 for (i = 0; i < count; i++) {
309 if (svga->curr.sampler[shader][i]) {
310 ids[i] = svga->curr.sampler[shader][i]->id;
311 assert(ids[i] != SVGA3D_INVALID_ID);
312 }
313 else {
314 ids[i] = SVGA3D_INVALID_ID;
315 }
316 }
317
318 if (count > 0) {
319 if (count != svga->state.hw_draw.num_samplers[shader] ||
320 memcmp(ids, svga->state.hw_draw.samplers[shader],
321 count * sizeof(ids[0])) != 0) {
322 /* HW state is really changing */
323 ret = SVGA3D_vgpu10_SetSamplers(svga->swc,
324 count,
325 0, /* start */
326 svga_shader_type(shader), /* type */
327 ids);
328 if (ret != PIPE_OK)
329 return ret;
330 memcpy(svga->state.hw_draw.samplers[shader], ids,
331 count * sizeof(ids[0]));
332 svga->state.hw_draw.num_samplers[shader] = count;
333 }
334 }
335 }
336
337 /* Handle polygon stipple sampler texture */
338 if (svga->curr.rast->templ.poly_stipple_enable) {
339 const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
340 struct svga_sampler_state *sampler = svga->polygon_stipple.sampler;
341
342 assert(sampler);
343 if (!sampler) {
344 return PIPE_OK; /* probably out of memory */
345 }
346
347 ret = SVGA3D_vgpu10_SetSamplers(svga->swc,
348 1, /* count */
349 unit, /* start */
350 SVGA3D_SHADERTYPE_PS,
351 &sampler->id);
352 }
353
354 return ret;
355 }
356
357
358 struct svga_tracked_state svga_hw_sampler = {
359 "texture sampler emit",
360 (SVGA_NEW_SAMPLER |
361 SVGA_NEW_STIPPLE |
362 SVGA_NEW_TEXTURE_FLAGS),
363 update_samplers
364 };