d3d10/effect: Support stream output declaration when creating geometry shaders.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Matteo Bruni <mbruni@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
87ac914e82
commit
5071836f3e
|
@ -314,6 +314,32 @@ static const char *debug_d3d10_shader_variable_type(D3D10_SHADER_VARIABLE_TYPE t
|
||||||
|
|
||||||
#undef WINE_D3D10_TO_STR
|
#undef WINE_D3D10_TO_STR
|
||||||
|
|
||||||
|
static BOOL d3d_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size)
|
||||||
|
{
|
||||||
|
SIZE_T max_capacity, new_capacity;
|
||||||
|
void *new_elements;
|
||||||
|
|
||||||
|
if (count <= *capacity)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
max_capacity = ~(SIZE_T)0 / size;
|
||||||
|
if (count > max_capacity)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
new_capacity = max(1, *capacity);
|
||||||
|
while (new_capacity < count && new_capacity <= max_capacity / 2)
|
||||||
|
new_capacity *= 2;
|
||||||
|
if (new_capacity < count)
|
||||||
|
new_capacity = count;
|
||||||
|
|
||||||
|
if (!(new_elements = heap_realloc(*elements, new_capacity * size)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
*elements = new_elements;
|
||||||
|
*capacity = new_capacity;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void read_dword(const char **ptr, DWORD *d)
|
static void read_dword(const char **ptr, DWORD *d)
|
||||||
{
|
{
|
||||||
memcpy(d, *ptr, sizeof(*d));
|
memcpy(d, *ptr, sizeof(*d));
|
||||||
|
@ -566,6 +592,127 @@ static HRESULT get_fx10_shader_resources(struct d3d10_effect_variable *v, const
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct d3d10_effect_so_decl
|
||||||
|
{
|
||||||
|
D3D10_SO_DECLARATION_ENTRY *entries;
|
||||||
|
SIZE_T capacity;
|
||||||
|
SIZE_T count;
|
||||||
|
unsigned int stride;
|
||||||
|
char *decl;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void d3d10_effect_cleanup_so_decl(struct d3d10_effect_so_decl *so_decl)
|
||||||
|
{
|
||||||
|
heap_free(so_decl->entries);
|
||||||
|
heap_free(so_decl->decl);
|
||||||
|
memset(so_decl, 0, sizeof(*so_decl));
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT d3d10_effect_parse_stream_output_declaration(const char *decl,
|
||||||
|
struct d3d10_effect_so_decl *so_decl)
|
||||||
|
{
|
||||||
|
static const char * allmask = "xyzw";
|
||||||
|
char *p, *ptr, *end, *next, *mask, *m, *slot;
|
||||||
|
unsigned int len = strlen(decl);
|
||||||
|
D3D10_SO_DECLARATION_ENTRY e;
|
||||||
|
|
||||||
|
memset(so_decl, 0, sizeof(*so_decl));
|
||||||
|
|
||||||
|
if (!(so_decl->decl = heap_alloc(len + 1)))
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
memcpy(so_decl->decl, decl, len + 1);
|
||||||
|
|
||||||
|
p = so_decl->decl;
|
||||||
|
|
||||||
|
while (p && *p)
|
||||||
|
{
|
||||||
|
memset(&e, 0, sizeof(e));
|
||||||
|
|
||||||
|
end = strchr(p, ';');
|
||||||
|
next = end ? end + 1 : p + strlen(p);
|
||||||
|
|
||||||
|
len = next - p;
|
||||||
|
if (end) len--;
|
||||||
|
|
||||||
|
/* Remove leading and trailing spaces. */
|
||||||
|
while (len && isspace(*p)) { len--; p++; }
|
||||||
|
while (len && isspace(p[len - 1])) len--;
|
||||||
|
|
||||||
|
p[len] = 0;
|
||||||
|
|
||||||
|
/* Output slot */
|
||||||
|
if ((slot = strchr(p, ':')))
|
||||||
|
{
|
||||||
|
*slot = 0;
|
||||||
|
|
||||||
|
ptr = p;
|
||||||
|
while (*ptr)
|
||||||
|
{
|
||||||
|
if (!isdigit(*ptr))
|
||||||
|
{
|
||||||
|
WARN("Invalid output slot %s.\n", debugstr_a(p));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OutputSlot = atoi(p);
|
||||||
|
p = slot + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mask */
|
||||||
|
if ((mask = strchr(p, '.')))
|
||||||
|
{
|
||||||
|
*mask = 0; mask++;
|
||||||
|
|
||||||
|
if (!(m = strstr(allmask, mask)))
|
||||||
|
{
|
||||||
|
WARN("Invalid component mask %s.\n", debugstr_a(mask));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.StartComponent = m - allmask;
|
||||||
|
e.ComponentCount = strlen(mask);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e.StartComponent = 0;
|
||||||
|
e.ComponentCount = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Semantic index and name */
|
||||||
|
len = strlen(p);
|
||||||
|
while (isdigit(p[len - 1]))
|
||||||
|
len--;
|
||||||
|
|
||||||
|
if (p[len])
|
||||||
|
{
|
||||||
|
e.SemanticIndex = atoi(&p[len]);
|
||||||
|
p[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.SemanticName = p;
|
||||||
|
|
||||||
|
if (!d3d_array_reserve((void **)&so_decl->entries, &so_decl->capacity, so_decl->count + 1,
|
||||||
|
sizeof(*so_decl->entries)))
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
so_decl->entries[so_decl->count++] = e;
|
||||||
|
|
||||||
|
if (e.OutputSlot == 0)
|
||||||
|
so_decl->stride += e.ComponentCount * sizeof(float);
|
||||||
|
|
||||||
|
p = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
d3d10_effect_cleanup_so_decl(so_decl);
|
||||||
|
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT parse_fx10_shader(const char *data, size_t data_size, DWORD offset, struct d3d10_effect_variable *v)
|
static HRESULT parse_fx10_shader(const char *data, size_t data_size, DWORD offset, struct d3d10_effect_variable *v)
|
||||||
{
|
{
|
||||||
ID3D10Device *device = v->effect->device;
|
ID3D10Device *device = v->effect->device;
|
||||||
|
@ -628,9 +775,22 @@ static HRESULT parse_fx10_shader(const char *data, size_t data_size, DWORD offse
|
||||||
|
|
||||||
case D3D10_SVT_GEOMETRYSHADER:
|
case D3D10_SVT_GEOMETRYSHADER:
|
||||||
if (v->type->flags & D3D10_EOT_FLAG_GS_SO)
|
if (v->type->flags & D3D10_EOT_FLAG_GS_SO)
|
||||||
FIXME("Create geometry shader with stream output.\n");
|
{
|
||||||
hr = ID3D10Device_CreateGeometryShader(device, ptr, dxbc_size, &v->u.shader.shader.gs);
|
struct d3d10_effect_so_decl so_decl;
|
||||||
if (FAILED(hr)) return hr;
|
|
||||||
|
if (FAILED(hr = d3d10_effect_parse_stream_output_declaration(v->u.shader.stream_output_declaration, &so_decl)))
|
||||||
|
{
|
||||||
|
WARN("Failed to parse stream output declaration, hr %#x.\n", hr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = ID3D10Device_CreateGeometryShaderWithStreamOutput(device, ptr, dxbc_size,
|
||||||
|
so_decl.entries, so_decl.count, so_decl.stride, &v->u.shader.shader.gs);
|
||||||
|
|
||||||
|
d3d10_effect_cleanup_so_decl(&so_decl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hr = ID3D10Device_CreateGeometryShader(device, ptr, dxbc_size, &v->u.shader.shader.gs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1996,9 +2156,6 @@ static HRESULT parse_fx10_local_variable(const char *data, size_t data_size,
|
||||||
read_dword(ptr, &shader_offset);
|
read_dword(ptr, &shader_offset);
|
||||||
TRACE("Shader offset: %#x.\n", shader_offset);
|
TRACE("Shader offset: %#x.\n", shader_offset);
|
||||||
|
|
||||||
if (FAILED(hr = parse_fx10_shader(data, data_size, shader_offset, var)))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
if (v->type->flags & D3D10_EOT_FLAG_GS_SO)
|
if (v->type->flags & D3D10_EOT_FLAG_GS_SO)
|
||||||
{
|
{
|
||||||
read_dword(ptr, &sodecl_offset);
|
read_dword(ptr, &sodecl_offset);
|
||||||
|
@ -2013,6 +2170,9 @@ static HRESULT parse_fx10_local_variable(const char *data, size_t data_size,
|
||||||
|
|
||||||
TRACE("Stream output declaration: %s.\n", debugstr_a(var->u.shader.stream_output_declaration));
|
TRACE("Stream output declaration: %s.\n", debugstr_a(var->u.shader.stream_output_declaration));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr = parse_fx10_shader(data, data_size, shader_offset, var)))
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue