[Mesa-dev] [PATCH 20/75] st/nine: Initial ProcessVertices support

Axel Davy axel.davy at ens.fr
Thu Oct 6 20:24:54 UTC 2016


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



More information about the mesa-dev mailing list