mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
libs/vkd3d-shader: Implement root signature parsing.
This commit is contained in:
@@ -42,6 +42,10 @@ HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
|
|||||||
struct vkd3d_shader_code *spirv, uint32_t compiler_options);
|
struct vkd3d_shader_code *spirv, uint32_t compiler_options);
|
||||||
void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *code);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008-2009 Henri Verbeet for CodeWeavers
|
* 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* 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_SHDR MAKE_TAG('S', 'H', 'D', 'R')
|
||||||
#define TAG_SHEX MAKE_TAG('S', 'H', 'E', 'X')
|
#define TAG_SHEX MAKE_TAG('S', 'H', 'E', 'X')
|
||||||
#define TAG_AON9 MAKE_TAG('A', 'o', 'n', '9')
|
#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)
|
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;
|
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);
|
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
|
#ifndef __VKD3D_SHADER_PRIVATE_H
|
||||||
#define __VKD3D_SHADER_PRIVATE_H
|
#define __VKD3D_SHADER_PRIVATE_H
|
||||||
|
|
||||||
|
#define NONAMELESSUNION
|
||||||
#include "vkd3d_common.h"
|
#include "vkd3d_common.h"
|
||||||
#include "vkd3d_memory.h"
|
#include "vkd3d_memory.h"
|
||||||
#include "vkd3d_shader.h"
|
#include "vkd3d_shader.h"
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#define INITGUID
|
#define INITGUID
|
||||||
#include "vkd3d_private.h"
|
#include "vkd3d_private.h"
|
||||||
|
#include "vkd3d_shader.h"
|
||||||
|
|
||||||
HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
|
HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
|
||||||
REFIID riid, void **device)
|
REFIID riid, void **device)
|
||||||
@@ -100,6 +101,7 @@ static ULONG STDMETHODCALLTYPE d3d12_root_signature_deserializer_Release(ID3D12R
|
|||||||
|
|
||||||
if (!refcount)
|
if (!refcount)
|
||||||
{
|
{
|
||||||
|
vkd3d_shader_free_root_signature(&deserializer->desc);
|
||||||
vkd3d_free(deserializer);
|
vkd3d_free(deserializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,26 +128,41 @@ static const struct ID3D12RootSignatureDeserializerVtbl d3d12_root_signature_des
|
|||||||
d3d12_root_signature_deserializer_GetRootSignatureDesc,
|
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->ID3D12RootSignatureDeserializer_iface.lpVtbl = &d3d12_root_signature_deserializer_vtbl;
|
||||||
deserializer->refcount = 1;
|
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,
|
HRESULT WINAPI D3D12CreateRootSignatureDeserializer(const void *data, SIZE_T data_size,
|
||||||
REFIID riid, void **deserializer)
|
REFIID riid, void **deserializer)
|
||||||
{
|
{
|
||||||
|
struct vkd3d_shader_code dxbc = {data, data_size};
|
||||||
struct d3d12_root_signature_deserializer *object;
|
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);
|
data, data_size, debugstr_guid(riid), deserializer);
|
||||||
|
|
||||||
if (!(object = vkd3d_malloc(sizeof(*object))))
|
if (!(object = vkd3d_malloc(sizeof(*object))))
|
||||||
return E_OUTOFMEMORY;
|
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,
|
return return_interface((IUnknown *)&object->ID3D12RootSignatureDeserializer_iface,
|
||||||
&IID_ID3D12RootSignatureDeserializer, riid, deserializer);
|
&IID_ID3D12RootSignatureDeserializer, riid, deserializer);
|
||||||
|
Reference in New Issue
Block a user