NineUnknown_ConvertRefToBind(NineUnknown(This->state.rt[i]));
}
+ /* Initialize a dummy VBO to be used when a a vertex declaration does not
+ * specify all the inputs needed by vertex shader, on win default behavior
+ * is to pass 0,0,0,0 to the shader */
+ {
+ struct pipe_transfer *transfer;
+ struct pipe_resource tmpl;
+ struct pipe_box box;
+ unsigned char *data;
+
+ tmpl.target = PIPE_BUFFER;
+ tmpl.format = PIPE_FORMAT_R8_UNORM;
+ tmpl.width0 = 16; /* 4 floats */
+ tmpl.height0 = 1;
+ tmpl.depth0 = 1;
+ tmpl.array_size = 1;
+ tmpl.last_level = 0;
+ tmpl.nr_samples = 0;
+ tmpl.usage = PIPE_USAGE_DEFAULT;
+ tmpl.bind = PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_TRANSFER_WRITE;
+ tmpl.flags = 0;
+ This->dummy_vbo = pScreen->resource_create(pScreen, &tmpl);
+
+ if (!This->dummy_vbo)
+ return D3DERR_OUTOFVIDEOMEMORY;
+
+ u_box_1d(0, 16, &box);
+ data = This->pipe->transfer_map(This->pipe, This->dummy_vbo, 0,
+ PIPE_TRANSFER_WRITE |
+ PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
+ &box, &transfer);
+ assert(data);
+ assert(transfer);
+ memset(data, 0, 16);
+ This->pipe->transfer_unmap(This->pipe, transfer);
+ }
+
This->cursor.software = FALSE;
This->cursor.hotspot.x = -1;
This->cursor.hotspot.y = -1;
pipe_resource_reference(&This->dummy_texture, NULL);
pipe_resource_reference(&This->constbuf_vs, NULL);
pipe_resource_reference(&This->constbuf_ps, NULL);
+ pipe_resource_reference(&This->dummy_vbo, NULL);
FREE(This->state.vs_const_f);
FREE(This->state.ps_const_f);
FREE(This->state.vs_lconstf_temp);
const struct NineVertexShader9 *vs;
unsigned n, b, i;
int index;
+ char vdecl_index_map[16]; /* vs->num_inputs <= 16 */
+ char used_streams[device->caps.MaxStreams];
+ int dummy_vbo_stream = -1;
+ BOOL need_dummy_vbo = FALSE;
struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
state->stream_usage_mask = 0;
-
+ memset(vdecl_index_map, -1, 16);
+ memset(used_streams, 0, device->caps.MaxStreams);
vs = device->state.vs ? device->state.vs : device->ff.vs;
if (!vdecl) /* no inputs */
return;
- for (n = 0; n < vs->num_inputs; ++n) {
- DBG("looking up input %u (usage %u) from vdecl(%p)\n",
- n, vs->input_map[n].ndecl, vdecl);
- index = -1;
- for (i = 0; i < vdecl->nelems; i++) {
- if (vdecl->usage_map[i] == vs->input_map[n].ndecl) {
- index = i;
+ if (vdecl) {
+ for (n = 0; n < vs->num_inputs; ++n) {
+ DBG("looking up input %u (usage %u) from vdecl(%p)\n",
+ n, vs->input_map[n].ndecl, vdecl);
+
+ for (i = 0; i < vdecl->nelems; i++) {
+ if (vdecl->usage_map[i] == vs->input_map[n].ndecl) {
+ vdecl_index_map[n] = i;
+ used_streams[vdecl->elems[i].vertex_buffer_index] = 1;
+ break;
+ }
+ }
+ if (vdecl_index_map[n] < 0)
+ need_dummy_vbo = TRUE;
+ }
+ } else {
+ /* No vertex declaration. Likely will never happen in practice,
+ * but we need not crash on this */
+ need_dummy_vbo = TRUE;
+ }
+
+ if (need_dummy_vbo) {
+ for (i = 0; i < device->caps.MaxStreams; i++ ) {
+ if (!used_streams[i]) {
+ dummy_vbo_stream = i;
break;
}
}
+ }
+ /* there are less vertex shader inputs than stream slots,
+ * so if we need a slot for the dummy vbo, we should have found one */
+ assert (!need_dummy_vbo || dummy_vbo_stream != -1);
+ for (n = 0; n < vs->num_inputs; ++n) {
+ index = vdecl_index_map[n];
if (index >= 0) {
ve[n] = vdecl->elems[index];
b = ve[n].vertex_buffer_index;
if (state->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA)
ve[n].instance_divisor = state->stream_freq[b] & 0x7FFFFF;
} else {
- /* TODO: msdn doesn't specify what should happen when the vertex
- * declaration doesn't match the vertex shader inputs.
- * Some websites say the code will pass but nothing will get rendered.
- * We should check and implement the correct behaviour. */
- /* Put PIPE_FORMAT_NONE.
- * Some drivers (r300) are very unhappy with that */
- ve[n].src_format = PIPE_FORMAT_NONE;
+ /* if the vertex declaration is incomplete compared to what the
+ * vertex shader needs, we bind a dummy vbo with 0 0 0 0.
+ * This is not precised by the spec, but is the behaviour
+ * tested on win */
+ ve[n].vertex_buffer_index = dummy_vbo_stream;
+ ve[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
ve[n].src_offset = 0;
ve[n].instance_divisor = 0;
- ve[n].vertex_buffer_index = 0;
}
}
+
+ if (state->dummy_vbo_bound_at != dummy_vbo_stream) {
+ if (state->dummy_vbo_bound_at >= 0)
+ state->changed.vtxbuf |= 1 << state->dummy_vbo_bound_at;
+ if (dummy_vbo_stream >= 0) {
+ state->changed.vtxbuf |= 1 << dummy_vbo_stream;
+ state->vbo_bound_done = FALSE;
+ }
+ state->dummy_vbo_bound_at = dummy_vbo_stream;
+ }
+
cso_set_vertex_elements(device->cso, vs->num_inputs, ve);
state->changed.stream_freq = 0;
{
struct pipe_context *pipe = device->pipe;
struct nine_state *state = &device->state;
+ struct pipe_vertex_buffer dummy_vtxbuf;
uint32_t mask = state->changed.vtxbuf;
unsigned i;
unsigned start;
DBG("mask=%x\n", mask);
+ if (state->dummy_vbo_bound_at >= 0) {
+ if (!state->vbo_bound_done) {
+ dummy_vtxbuf.buffer = device->dummy_vbo;
+ dummy_vtxbuf.stride = 0;
+ dummy_vtxbuf.user_buffer = NULL;
+ dummy_vtxbuf.buffer_offset = 0;
+ pipe->set_vertex_buffers(pipe, state->dummy_vbo_bound_at,
+ 1, &dummy_vtxbuf);
+ state->vbo_bound_done = TRUE;
+ }
+ mask &= ~(1 << state->dummy_vbo_bound_at);
+ }
+
for (i = 0; mask; mask >>= 1, ++i) {
if (mask & 1) {
if (!count)
++count;
} else {
if (count)
- pipe->set_vertex_buffers(pipe,
- start, count, &state->vtxbuf[start]);
+ pipe->set_vertex_buffers(pipe, start, count,
+ &state->vtxbuf[start]);
count = 0;
}
}
for (s = 0; s < Elements(state->changed.sampler); ++s)
state->changed.sampler[s] = ~0;
+
+ if (!is_reset) {
+ state->dummy_vbo_bound_at = -1;
+ state->vbo_bound_done = FALSE;
+ }
}
void