mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-01-28 13:05:02 -08:00
libs/vkd3d-shader: Implement root signature parsing.
This commit is contained in:
parent
d220ae4bfb
commit
3f03cd1ec8
@ -42,6 +42,10 @@ HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
|
||||
struct vkd3d_shader_code *spirv, uint32_t compiler_options);
|
||||
void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *code);
|
||||
|
||||
HRESULT vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
|
||||
D3D12_ROOT_SIGNATURE_DESC *root_signature);
|
||||
void vkd3d_shader_free_root_signature(D3D12_ROOT_SIGNATURE_DESC *root_signature);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2008-2009 Henri Verbeet for CodeWeavers
|
||||
* Copyright 2017 Józef Kucia for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -1738,6 +1739,7 @@ BOOL shader_sm4_is_end(void *data, const DWORD **ptr)
|
||||
#define TAG_SHDR MAKE_TAG('S', 'H', 'D', 'R')
|
||||
#define TAG_SHEX MAKE_TAG('S', 'H', 'E', 'X')
|
||||
#define TAG_AON9 MAKE_TAG('A', 'o', 'n', '9')
|
||||
#define TAG_RTS0 MAKE_TAG('R', 'T', 'S', '0')
|
||||
|
||||
static BOOL require_space(size_t offset, size_t count, size_t size, size_t data_size)
|
||||
{
|
||||
@ -2019,3 +2021,243 @@ HRESULT shader_extract_from_dxbc(const void *dxbc, SIZE_T dxbc_length,
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT shader_parse_descriptor_ranges(const char *data, DWORD data_size,
|
||||
DWORD offset, DWORD count, D3D12_DESCRIPTOR_RANGE *ranges)
|
||||
{
|
||||
DWORD type, descriptor_count, reg_idx, space_idx, table_offset;
|
||||
const char *ptr;
|
||||
unsigned int i;
|
||||
|
||||
if (!require_space(offset, 5 * count, sizeof(DWORD), data_size))
|
||||
{
|
||||
WARN("Invalid data size %#x (offset %u, count %u).\n", data_size, offset, count);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
ptr = &data[offset];
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
read_dword(&ptr, &type);
|
||||
read_dword(&ptr, &descriptor_count);
|
||||
read_dword(&ptr, ®_idx);
|
||||
read_dword(&ptr, &space_idx);
|
||||
read_dword(&ptr, &table_offset);
|
||||
|
||||
TRACE("Type %#x, descriptor count %u, base shader register %u, "
|
||||
"register space %u, offset %u.\n",
|
||||
type, descriptor_count, reg_idx, space_idx, table_offset);
|
||||
|
||||
ranges[i].RangeType = type;
|
||||
ranges[i].NumDescriptors = descriptor_count;
|
||||
ranges[i].BaseShaderRegister = reg_idx;
|
||||
ranges[i].RegisterSpace = space_idx;
|
||||
ranges[i].OffsetInDescriptorsFromTableStart = table_offset;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT shader_parse_descriptor_table(const char *data, DWORD data_size,
|
||||
DWORD offset, D3D12_ROOT_DESCRIPTOR_TABLE *table)
|
||||
{
|
||||
D3D12_DESCRIPTOR_RANGE *ranges;
|
||||
const char *ptr;
|
||||
DWORD count;
|
||||
|
||||
if (!require_space(offset, 2, sizeof(DWORD), data_size))
|
||||
{
|
||||
WARN("Invalid data size %#x (offset %u).\n", data_size, offset);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
ptr = &data[offset];
|
||||
|
||||
read_dword(&ptr, &count);
|
||||
read_dword(&ptr, &offset);
|
||||
|
||||
TRACE("Descriptor range count %u.\n", count);
|
||||
|
||||
table->NumDescriptorRanges = count;
|
||||
|
||||
if (!(ranges = vkd3d_calloc(count, sizeof(*ranges))))
|
||||
return E_OUTOFMEMORY;
|
||||
table->pDescriptorRanges = ranges;
|
||||
return shader_parse_descriptor_ranges(data, data_size, offset, count, ranges);
|
||||
}
|
||||
|
||||
static HRESULT shader_parse_root_constants(const char *data, DWORD data_size,
|
||||
DWORD offset, D3D12_ROOT_CONSTANTS *constants)
|
||||
{
|
||||
DWORD reg_idx, space_idx, value_count;
|
||||
const char *ptr;
|
||||
|
||||
if (!require_space(offset, 3, sizeof(DWORD), data_size))
|
||||
{
|
||||
WARN("Invalid data size %#x (offset %u).\n", data_size, offset);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
ptr = &data[offset];
|
||||
|
||||
read_dword(&ptr, ®_idx);
|
||||
read_dword(&ptr, &space_idx);
|
||||
read_dword(&ptr, &value_count);
|
||||
|
||||
TRACE("Shader register %u, register space %u, 32-bit value count %u.\n",
|
||||
reg_idx, space_idx, value_count);
|
||||
|
||||
constants->ShaderRegister = reg_idx;
|
||||
constants->RegisterSpace = space_idx;
|
||||
constants->Num32BitValues = value_count;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT shader_parse_root_descriptor(const char *data, DWORD data_size,
|
||||
DWORD offset, D3D12_ROOT_DESCRIPTOR *descriptor)
|
||||
{
|
||||
DWORD reg_idx, space_idx;
|
||||
const char *ptr;
|
||||
|
||||
if (!require_space(offset, 2, sizeof(DWORD), data_size))
|
||||
{
|
||||
WARN("Invalid data size %#x (offset %u).\n", data_size, offset);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
ptr = &data[offset];
|
||||
|
||||
read_dword(&ptr, ®_idx);
|
||||
read_dword(&ptr, &space_idx);
|
||||
|
||||
TRACE("Shader register %u, register space %u.\n", reg_idx, space_idx);
|
||||
|
||||
descriptor->ShaderRegister = reg_idx;
|
||||
descriptor->RegisterSpace = space_idx;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT shader_parse_root_parameters(const char *data, DWORD data_size,
|
||||
DWORD offset, DWORD count, D3D12_ROOT_PARAMETER *parameters)
|
||||
{
|
||||
DWORD type, shader_visibility;
|
||||
const char *ptr;
|
||||
unsigned int i;
|
||||
HRESULT hr;
|
||||
|
||||
if (!require_space(offset, 3 * count, sizeof(DWORD), data_size))
|
||||
{
|
||||
WARN("Invalid data size %#x (offset %u, count %u).\n", data_size, offset, count);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
ptr = &data[offset];
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
read_dword(&ptr, &type);
|
||||
read_dword(&ptr, &shader_visibility);
|
||||
read_dword(&ptr, &offset);
|
||||
|
||||
TRACE("Type %#x, shader visibility %#x.\n", type, shader_visibility);
|
||||
|
||||
parameters[i].ParameterType = type;
|
||||
parameters[i].ShaderVisibility = shader_visibility;
|
||||
|
||||
if (type == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
|
||||
{
|
||||
if (FAILED(hr = shader_parse_descriptor_table(data, data_size,
|
||||
offset, ¶meters[i].u.DescriptorTable)))
|
||||
return hr;
|
||||
}
|
||||
else if (type == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS)
|
||||
{
|
||||
if (FAILED(hr = shader_parse_root_constants(data, data_size,
|
||||
offset, ¶meters[i].u.Constants)))
|
||||
return hr;
|
||||
}
|
||||
else if (type <= D3D12_ROOT_PARAMETER_TYPE_UAV)
|
||||
{
|
||||
if (FAILED(hr = shader_parse_root_descriptor(data, data_size,
|
||||
offset, ¶meters[i].u.Descriptor)))
|
||||
return hr;
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized type %#x.\n", type);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT shader_parse_root_signature(const char *data, DWORD data_size,
|
||||
D3D12_ROOT_SIGNATURE_DESC *desc)
|
||||
{
|
||||
DWORD count, offset, flags;
|
||||
const char *ptr = data;
|
||||
HRESULT hr;
|
||||
|
||||
if (!require_space(0, 6, sizeof(DWORD), data_size))
|
||||
{
|
||||
WARN("Invalid data size %#x.\n", data_size);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
skip_dword_unknown(&ptr, 1); /* It seems to always be 0x00000001. */
|
||||
|
||||
read_dword(&ptr, &count);
|
||||
read_dword(&ptr, &offset);
|
||||
TRACE("Parameter count %u, offset %u.\n", count, offset);
|
||||
|
||||
desc->NumParameters = count;
|
||||
|
||||
if (desc->NumParameters)
|
||||
{
|
||||
D3D12_ROOT_PARAMETER *parameters;
|
||||
if (!(parameters = vkd3d_calloc(desc->NumParameters, sizeof(*parameters))))
|
||||
return E_OUTOFMEMORY;
|
||||
desc->pParameters = parameters;
|
||||
if (FAILED(hr = shader_parse_root_parameters(data, data_size, offset, count, parameters)))
|
||||
return hr;
|
||||
}
|
||||
|
||||
read_dword(&ptr, &count);
|
||||
read_dword(&ptr, &offset);
|
||||
TRACE("Static sampler count %u, offset %u.\n", count, offset);
|
||||
|
||||
if (count)
|
||||
FIXME("Static samplers not supported yet.\n");
|
||||
|
||||
read_dword(&ptr, &flags);
|
||||
TRACE("Flags %#x.\n", flags);
|
||||
desc->Flags = flags;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT rts0_handler(const char *data, DWORD data_size, DWORD tag, void *context)
|
||||
{
|
||||
D3D12_ROOT_SIGNATURE_DESC *desc = context;
|
||||
|
||||
if (tag != TAG_RTS0)
|
||||
return S_OK;
|
||||
|
||||
return shader_parse_root_signature(data, data_size, desc);
|
||||
}
|
||||
|
||||
HRESULT vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
|
||||
D3D12_ROOT_SIGNATURE_DESC *root_signature)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("dxbc {%p, %zu}, root_signature %p.\n", dxbc->code, dxbc->size, root_signature);
|
||||
|
||||
memset(root_signature, 0, sizeof(*root_signature));
|
||||
if (FAILED(hr = parse_dxbc(dxbc->code, dxbc->size, rts0_handler, root_signature)))
|
||||
{
|
||||
vkd3d_shader_free_root_signature(root_signature);
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -88,3 +88,20 @@ void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *shader_code)
|
||||
|
||||
vkd3d_free((void *)shader_code->code);
|
||||
}
|
||||
|
||||
void vkd3d_shader_free_root_signature(D3D12_ROOT_SIGNATURE_DESC *root_signature)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < root_signature->NumParameters; ++i)
|
||||
{
|
||||
const D3D12_ROOT_PARAMETER *parameter = &root_signature->pParameters[i];
|
||||
|
||||
if (parameter->ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
|
||||
vkd3d_free((void *)parameter->u.DescriptorTable.pDescriptorRanges);
|
||||
}
|
||||
vkd3d_free((void *)root_signature->pParameters);
|
||||
vkd3d_free((void *)root_signature->pStaticSamplers);
|
||||
|
||||
memset(root_signature, 0, sizeof(*root_signature));
|
||||
}
|
||||
|
@ -45,6 +45,7 @@
|
||||
#ifndef __VKD3D_SHADER_PRIVATE_H
|
||||
#define __VKD3D_SHADER_PRIVATE_H
|
||||
|
||||
#define NONAMELESSUNION
|
||||
#include "vkd3d_common.h"
|
||||
#include "vkd3d_memory.h"
|
||||
#include "vkd3d_shader.h"
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#define INITGUID
|
||||
#include "vkd3d_private.h"
|
||||
#include "vkd3d_shader.h"
|
||||
|
||||
HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
|
||||
REFIID riid, void **device)
|
||||
@ -100,6 +101,7 @@ static ULONG STDMETHODCALLTYPE d3d12_root_signature_deserializer_Release(ID3D12R
|
||||
|
||||
if (!refcount)
|
||||
{
|
||||
vkd3d_shader_free_root_signature(&deserializer->desc);
|
||||
vkd3d_free(deserializer);
|
||||
}
|
||||
|
||||
@ -126,26 +128,41 @@ static const struct ID3D12RootSignatureDeserializerVtbl d3d12_root_signature_des
|
||||
d3d12_root_signature_deserializer_GetRootSignatureDesc,
|
||||
};
|
||||
|
||||
static void d3d12_root_signature_deserializer_init(struct d3d12_root_signature_deserializer *deserializer)
|
||||
static HRESULT d3d12_root_signature_deserializer_init(struct d3d12_root_signature_deserializer *deserializer,
|
||||
const struct vkd3d_shader_code *dxbc)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
deserializer->ID3D12RootSignatureDeserializer_iface.lpVtbl = &d3d12_root_signature_deserializer_vtbl;
|
||||
deserializer->refcount = 1;
|
||||
|
||||
memset(&deserializer->desc, 0, sizeof(deserializer->desc));
|
||||
if (FAILED(hr = vkd3d_shader_parse_root_signature(dxbc, &deserializer->desc)))
|
||||
{
|
||||
WARN("Failed to parse root signature, hr %#x.\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI D3D12CreateRootSignatureDeserializer(const void *data, SIZE_T data_size,
|
||||
REFIID riid, void **deserializer)
|
||||
{
|
||||
struct vkd3d_shader_code dxbc = {data, data_size};
|
||||
struct d3d12_root_signature_deserializer *object;
|
||||
HRESULT hr;
|
||||
|
||||
FIXME("data %p, data_size %lu, riid %s, deserializer %p partial-stub!\n",
|
||||
TRACE("data %p, data_size %lu, riid %s, deserializer %p.\n",
|
||||
data, data_size, debugstr_guid(riid), deserializer);
|
||||
|
||||
if (!(object = vkd3d_malloc(sizeof(*object))))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
d3d12_root_signature_deserializer_init(object);
|
||||
if (FAILED(hr = d3d12_root_signature_deserializer_init(object, &dxbc)))
|
||||
{
|
||||
vkd3d_free(object);
|
||||
return hr;
|
||||
}
|
||||
|
||||
return return_interface((IUnknown *)&object->ID3D12RootSignatureDeserializer_iface,
|
||||
&IID_ID3D12RootSignatureDeserializer, riid, deserializer);
|
||||
|
Loading…
x
Reference in New Issue
Block a user