On 05/10/2016 22:08, Axel Davy wrote:
  HRESULT NINE_WINAPI
  NineDevice9_ProcessVertices( struct NineDevice9 *This,
                               UINT SrcStartIndex,
@@ -3174,33 +3188,69 @@ NineDevice9_ProcessVertices( struct NineDevice9 *This,
                               IDirect3DVertexDeclaration9 *pVertexDecl,
                               DWORD Flags )
  {
-    struct pipe_screen *screen = This->screen;
+    struct pipe_screen *screen_sw = This->screen_sw;
+    struct pipe_context *pipe_sw = This->pipe_sw;
      struct NineVertexDeclaration9 *vdecl = 
NineVertexDeclaration9(pVertexDecl);
+    struct NineVertexBuffer9 *dst = NineVertexBuffer9(pDestBuffer);
      struct NineVertexShader9 *vs;
      struct pipe_resource *resource;
+    struct pipe_transfer *transfer = NULL;
+    struct pipe_stream_output_info so;
      struct pipe_stream_output_target *target;
      struct pipe_draw_info draw;
+    struct pipe_box box;
+    unsigned offsets[1] = {0};
      HRESULT hr;
-    unsigned buffer_offset, buffer_size;
+    unsigned buffer_size;
+    void *map;
DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u "
          "pDestBuffer=%p pVertexDecl=%p Flags=%d\n",
          This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer,
          pVertexDecl, Flags);
- if (!screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS))
-        STUB(D3DERR_INVALIDCALL);
+    if (!screen_sw->get_param(screen_sw, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS)) {
+        DBG("ProcessVertices not supported\n");
+        return D3DERR_INVALIDCALL;
+    }
- nine_update_state(This); - /* TODO: Create shader with stream output. */
-    STUB(D3DERR_INVALIDCALL);
-    struct NineVertexBuffer9 *dst = NineVertexBuffer9(pDestBuffer);
+    vs = This->state.programmable_vs ? This->state.vs : This->ff.vs;
+    /* Note: version is 0 for ff */
+    user_assert(vdecl || (vs->byte_code.version < 0x30 && dst->desc.FVF),
+                D3DERR_INVALIDCALL);
+    if (!vdecl) {
+        DWORD FVF = dst->desc.FVF;
+        vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF);
+        if (!vdecl) {
+            hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl);
+            if (FAILED(hr))
+                return hr;
+            vdecl->fvf = FVF;
+            util_hash_table_set(This->ff.ht_fvf, &vdecl->fvf, vdecl);
+            NineUnknown_ConvertRefToBind(NineUnknown(vdecl));
+        }
+    }
- vs = This->state.vs ? This->state.vs : This->ff.vs;
+    /* Flags: Can be 0 or D3DPV_DONOTCOPYDATA, and/or lock flags
+     * D3DPV_DONOTCOPYDATA -> Has effect only for ff. In particular
+     * if not set, everything from src will be used, and dst
+     * must match exactly the ff vs outputs.
+     * TODO: Handle all the checks, etc for ff */
+    user_assert(vdecl->position_t || This->state.programmable_vs,
+                D3DERR_INVALIDCALL);
+
+    /* TODO: Support vs < 3 and ff */
+    user_assert(vs->byte_code.version == 0x30,
+                D3DERR_INVALIDCALL);
+    /* TODO: Not hardcode the constant buffers for swvp */
+    user_assert(This->may_swvp,
+                D3DERR_INVALIDCALL);
+
+    nine_state_prepare_draw_sw(This, vdecl, SrcStartIndex, VertexCount, &so);
- buffer_size = VertexCount * vs->so->stride[0];
-    if (1) {
+    buffer_size = VertexCount * so.stride[0] * 4;
+    {
          struct pipe_resource templ;
templ.target = PIPE_BUFFER;
@@ -3212,49 +3262,50 @@ NineDevice9_ProcessVertices( struct NineDevice9 *This,
          templ.height0 = templ.depth0 = templ.array_size = 1;
          templ.last_level = templ.nr_samples = 0;
- resource = This->screen->resource_create(This->screen, &templ);
+        resource = screen_sw->resource_create(screen_sw, &templ);
          if (!resource)
              return E_OUTOFMEMORY;
-        buffer_offset = 0;
-    } else {
-        /* SO matches vertex declaration */
-        resource = NineVertexBuffer9_GetResource(dst);
-        buffer_offset = DestIndex * vs->so->stride[0];
      }
-    target = This->pipe->create_stream_output_target(This->pipe, resource,
-                                                     buffer_offset,
-                                                     buffer_size);
+    target = pipe_sw->create_stream_output_target(pipe_sw, resource,
+                                                  0, buffer_size);
      if (!target) {
          pipe_resource_reference(&resource, NULL);
          return D3DERR_DRIVERINTERNALERROR;
      }
- if (!vdecl) {
-        hr = NineVertexDeclaration9_new_from_fvf(This, dst->desc.FVF, &vdecl);
-        if (FAILED(hr))
-            goto out;
-    }
-
      init_draw_info(&draw, This, D3DPT_POINTLIST, VertexCount);
      draw.instance_count = 1;
      draw.indexed = FALSE;
-    draw.start = SrcStartIndex;
+    draw.start = 0;
      draw.index_bias = 0;
-    draw.min_index = SrcStartIndex;
-    draw.max_index = SrcStartIndex + VertexCount - 1;
+    draw.min_index = 0;
+    draw.max_index = VertexCount - 1;
+
+
+    pipe_sw->set_stream_output_targets(pipe_sw, 1, &target, offsets);
- This->pipe->set_stream_output_targets(This->pipe, 1, &target, 0);
-    This->pipe->draw_vbo(This->pipe, &draw);
-    This->pipe->set_stream_output_targets(This->pipe, 0, NULL, 0);
-    This->pipe->stream_output_target_destroy(This->pipe, target);
+    pipe_sw->draw_vbo(pipe_sw, &draw);
+
+    pipe_sw->set_stream_output_targets(pipe_sw, 0, NULL, 0);
+    pipe_sw->stream_output_target_destroy(pipe_sw, target);
+
+    u_box_1d(0, VertexCount * so.stride[0] * 4, &box);
+    map = pipe_sw->transfer_map(pipe_sw, resource, 0, PIPE_TRANSFER_READ, &box,
+                                &transfer);
+    if (!map) {
+        hr = D3DERR_DRIVERINTERNALERROR;
+        goto out;
+    }
hr = NineVertexDeclaration9_ConvertStreamOutput(vdecl,
                                                      dst, DestIndex, 
VertexCount,
-                                                    resource, vs->so);
+                                                    map, &so);
+    if (transfer)
+        pipe_sw->transfer_unmap(pipe_sw, transfer);
+
  out:
+    nine_state_after_draw_sw(This);
      pipe_resource_reference(&resource, NULL);
-    if (!pVertexDecl)
-        NineUnknown_Release(NineUnknown(vdecl));
      return hr;
  }
Hi,

For some reason, this is not working well anymore on both llvmpipe and softpipe (but If I force screen_sw to take hal, that is radeonsi, the function works).

It crashes at the last

pipe_resource_reference(&resource, NULL);


However the resource refcount is 1, so I don't see the problem....
The patch used to work, but perhaps I broke it when modifying a few other stuffs.
Any idea why this would crash ?

Axel

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to