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

Ilia Mirkin imirkin at alum.mit.edu
Thu Oct 6 20:28:15 UTC 2016


On Thu, Oct 6, 2016 at 4:24 PM, Axel Davy <axel.davy at ens.fr> wrote:
> 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 ?

Recently a "next" pointer has been added to pipe_resource which has
been causing a few people grief as it's not always nulled out in the
initial templates. Not sure if it's relevant to this case or not.

  -ilia


More information about the mesa-dev mailing list