1 /**********************************************************
2 * Copyright 2014 VMware, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
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
24 **********************************************************/
26 #include "util/u_memory.h"
27 #include "util/u_bitmask.h"
30 #include "svga_context.h"
31 #include "svga_resource_buffer.h"
32 #include "svga_shader.h"
33 #include "svga_debug.h"
34 #include "svga_streamout.h"
36 struct svga_stream_output_target
{
37 struct pipe_stream_output_target base
;
41 static inline struct svga_stream_output_target
*
42 svga_stream_output_target(struct pipe_stream_output_target
*s
)
44 return (struct svga_stream_output_target
*)s
;
47 struct svga_stream_output
*
48 svga_create_stream_output(struct svga_context
*svga
,
49 struct svga_shader
*shader
,
50 const struct pipe_stream_output_info
*info
)
52 struct svga_stream_output
*streamout
;
53 SVGA3dStreamOutputDeclarationEntry decls
[SVGA3D_MAX_STREAMOUT_DECLS
];
54 unsigned strides
[SVGA3D_DX_MAX_SOTARGETS
];
59 assert(info
->num_outputs
<= PIPE_MAX_SO_OUTPUTS
);
61 /* Gallium utility creates shaders with stream output.
62 * For non-DX10, just return NULL.
64 if (!svga_have_vgpu10(svga
))
67 assert(info
->num_outputs
<= SVGA3D_MAX_STREAMOUT_DECLS
);
69 /* Allocate an integer ID for the stream output */
70 id
= util_bitmask_add(svga
->stream_output_id_bm
);
71 if (id
== UTIL_BITMASK_INVALID_INDEX
) {
75 /* Allocate the streamout data structure */
76 streamout
= CALLOC_STRUCT(svga_stream_output
);
81 streamout
->info
= *info
;
83 streamout
->pos_out_index
= -1;
85 SVGA_DBG(DEBUG_STREAMOUT
, "%s, num_outputs=%d id=%d\n", __FUNCTION__
,
86 info
->num_outputs
, id
);
88 /* init whole decls and stride arrays to zero to avoid garbage values */
89 memset(decls
, 0, sizeof(decls
));
90 memset(strides
, 0, sizeof(strides
));
92 for (i
= 0; i
< info
->num_outputs
; i
++) {
93 unsigned reg_idx
= info
->output
[i
].register_index
;
94 unsigned buf_idx
= info
->output
[i
].output_buffer
;
95 const unsigned sem_name
= shader
->info
.output_semantic_name
[reg_idx
];
97 assert(buf_idx
<= PIPE_MAX_SO_BUFFERS
);
99 if (sem_name
== TGSI_SEMANTIC_POSITION
) {
101 * Check if streaming out POSITION. If so, replace the
102 * register index with the index for NON_ADJUSTED POSITION.
104 decls
[i
].registerIndex
= shader
->info
.num_outputs
;
106 /* Save this output index, so we can tell later if this stream output
107 * includes an output of a vertex position
109 streamout
->pos_out_index
= i
;
111 else if (sem_name
== TGSI_SEMANTIC_CLIPDIST
) {
113 * Use the shadow copy for clip distance because
114 * CLIPDIST instruction is only emitted for enabled clip planes.
115 * It's valid to write to ClipDistance variable for non-enabled
118 decls
[i
].registerIndex
= shader
->info
.num_outputs
+ 1 +
119 shader
->info
.output_semantic_index
[reg_idx
];
122 decls
[i
].registerIndex
= reg_idx
;
125 decls
[i
].outputSlot
= buf_idx
;
126 decls
[i
].registerMask
=
127 ((1 << info
->output
[i
].num_components
) - 1)
128 << info
->output
[i
].start_component
;
130 SVGA_DBG(DEBUG_STREAMOUT
, "%d slot=%d regIdx=%d regMask=0x%x\n",
131 i
, decls
[i
].outputSlot
, decls
[i
].registerIndex
,
132 decls
[i
].registerMask
);
134 strides
[buf_idx
] = info
->stride
[buf_idx
] * sizeof(float);
137 ret
= SVGA3D_vgpu10_DefineStreamOutput(svga
->swc
, id
,
141 if (ret
!= PIPE_OK
) {
142 svga_context_flush(svga
, NULL
);
143 ret
= SVGA3D_vgpu10_DefineStreamOutput(svga
->swc
, id
,
147 if (ret
!= PIPE_OK
) {
148 util_bitmask_clear(svga
->stream_output_id_bm
, id
);
157 svga_set_stream_output(struct svga_context
*svga
,
158 struct svga_stream_output
*streamout
)
160 enum pipe_error ret
= PIPE_OK
;
161 unsigned id
= streamout
? streamout
->id
: SVGA3D_INVALID_ID
;
163 if (!svga_have_vgpu10(svga
)) {
167 SVGA_DBG(DEBUG_STREAMOUT
, "%s streamout=0x%x id=%d\n", __FUNCTION__
,
170 if (svga
->current_so
!= streamout
) {
171 /* Save current SO state */
172 svga
->current_so
= streamout
;
174 ret
= SVGA3D_vgpu10_SetStreamOutput(svga
->swc
, id
);
175 if (ret
!= PIPE_OK
) {
176 svga_context_flush(svga
, NULL
);
177 ret
= SVGA3D_vgpu10_SetStreamOutput(svga
->swc
, id
);
185 svga_delete_stream_output(struct svga_context
*svga
,
186 struct svga_stream_output
*streamout
)
190 SVGA_DBG(DEBUG_STREAMOUT
, "%s streamout=0x%x\n", __FUNCTION__
, streamout
);
192 assert(svga_have_vgpu10(svga
));
193 assert(streamout
!= NULL
);
195 ret
= SVGA3D_vgpu10_DestroyStreamOutput(svga
->swc
, streamout
->id
);
196 if (ret
!= PIPE_OK
) {
197 svga_context_flush(svga
, NULL
);
198 ret
= SVGA3D_vgpu10_DestroyStreamOutput(svga
->swc
, streamout
->id
);
202 util_bitmask_clear(svga
->stream_output_id_bm
, streamout
->id
);
204 /* Free streamout structure */
208 static struct pipe_stream_output_target
*
209 svga_create_stream_output_target(struct pipe_context
*pipe
,
210 struct pipe_resource
*buffer
,
211 unsigned buffer_offset
,
212 unsigned buffer_size
)
214 struct svga_context
*svga
= svga_context(pipe
);
215 struct svga_stream_output_target
*sot
;
217 SVGA_DBG(DEBUG_STREAMOUT
, "%s offset=%d size=%d\n", __FUNCTION__
,
218 buffer_offset
, buffer_size
);
220 assert(svga_have_vgpu10(svga
));
223 sot
= CALLOC_STRUCT(svga_stream_output_target
);
227 pipe_reference_init(&sot
->base
.reference
, 1);
228 pipe_resource_reference(&sot
->base
.buffer
, buffer
);
229 sot
->base
.context
= pipe
;
230 sot
->base
.buffer
= buffer
;
231 sot
->base
.buffer_offset
= buffer_offset
;
232 sot
->base
.buffer_size
= buffer_size
;
238 svga_destroy_stream_output_target(struct pipe_context
*pipe
,
239 struct pipe_stream_output_target
*target
)
241 struct svga_stream_output_target
*sot
= svga_stream_output_target(target
);
243 SVGA_DBG(DEBUG_STREAMOUT
, "%s\n", __FUNCTION__
);
245 pipe_resource_reference(&sot
->base
.buffer
, NULL
);
250 svga_set_stream_output_targets(struct pipe_context
*pipe
,
251 unsigned num_targets
,
252 struct pipe_stream_output_target
**targets
,
253 const unsigned *offsets
)
255 struct svga_context
*svga
= svga_context(pipe
);
256 struct SVGA3dSoTarget soBindings
[SVGA3D_DX_MAX_SOTARGETS
];
259 unsigned num_so_targets
;
261 SVGA_DBG(DEBUG_STREAMOUT
, "%s num_targets=%d\n", __FUNCTION__
,
264 assert(svga_have_vgpu10(svga
));
266 /* Mark the streamout buffers as dirty so that we'll issue readbacks
269 for (i
= 0; i
< svga
->num_so_targets
; i
++) {
270 struct svga_buffer
*sbuf
= svga_buffer(svga
->so_targets
[i
]->buffer
);
274 assert(num_targets
<= SVGA3D_DX_MAX_SOTARGETS
);
276 for (i
= 0; i
< num_targets
; i
++) {
277 struct svga_stream_output_target
*sot
278 = svga_stream_output_target(targets
[i
]);
279 struct svga_buffer
*sbuf
= svga_buffer(sot
->base
.buffer
);
282 assert(sbuf
->key
.flags
& SVGA3D_SURFACE_BIND_STREAM_OUTPUT
);
285 svga
->so_surfaces
[i
] = svga_buffer_handle(svga
, sot
->base
.buffer
);
286 svga
->so_targets
[i
] = &sot
->base
;
287 soBindings
[i
].offset
= sot
->base
.buffer_offset
;
289 /* The size cannot extend beyond the end of the buffer. Clamp it. */
290 size
= MIN2(sot
->base
.buffer_size
,
291 sot
->base
.buffer
->width0
- sot
->base
.buffer_offset
);
293 soBindings
[i
].sizeInBytes
= size
;
296 /* unbind any previously bound stream output buffers */
297 for (; i
< svga
->num_so_targets
; i
++) {
298 svga
->so_surfaces
[i
] = NULL
;
299 svga
->so_targets
[i
] = NULL
;
302 num_so_targets
= MAX2(svga
->num_so_targets
, num_targets
);
303 ret
= SVGA3D_vgpu10_SetSOTargets(svga
->swc
, num_so_targets
,
304 soBindings
, svga
->so_surfaces
);
305 if (ret
!= PIPE_OK
) {
306 svga_context_flush(svga
, NULL
);
307 ret
= SVGA3D_vgpu10_SetSOTargets(svga
->swc
, num_so_targets
,
308 soBindings
, svga
->so_surfaces
);
311 svga
->num_so_targets
= num_targets
;
315 * Rebind stream output target surfaces
318 svga_rebind_stream_output_targets(struct svga_context
*svga
)
320 struct svga_winsys_context
*swc
= svga
->swc
;
324 for (i
= 0; i
< svga
->num_so_targets
; i
++) {
325 ret
= swc
->resource_rebind(swc
, svga
->so_surfaces
[i
], NULL
, SVGA_RELOC_WRITE
);
334 svga_init_stream_output_functions(struct svga_context
*svga
)
336 svga
->pipe
.create_stream_output_target
= svga_create_stream_output_target
;
337 svga
->pipe
.stream_output_target_destroy
= svga_destroy_stream_output_target
;
338 svga
->pipe
.set_stream_output_targets
= svga_set_stream_output_targets
;