vkd3d: Import upstream release 1.7.

This commit is contained in:
Alexandre Julliard 2023-03-24 12:55:34 +01:00
parent 3149d27220
commit 75ab843114
28 changed files with 4506 additions and 1807 deletions

View file

@ -2240,6 +2240,7 @@ interface ID3D12CommandQueue : ID3D12Pageable
void UpdateTileMappings(ID3D12Resource *resource, UINT region_count,
const D3D12_TILED_RESOURCE_COORDINATE *region_start_coordinates,
const D3D12_TILE_REGION_SIZE *region_sizes,
ID3D12Heap *heap,
UINT range_count,
const D3D12_TILE_RANGE_FLAGS *range_flags,
UINT *heap_range_offsets,

View file

@ -186,6 +186,30 @@ static inline void list_move_tail( struct list *dst, struct list *src )
list_move_before( dst, src );
}
/* move the slice of elements from begin to end inclusive to the head of dst */
static inline void list_move_slice_head( struct list *dst, struct list *begin, struct list *end )
{
struct list *dst_next = dst->next;
begin->prev->next = end->next;
end->next->prev = begin->prev;
dst->next = begin;
dst_next->prev = end;
begin->prev = dst;
end->next = dst_next;
}
/* move the slice of elements from begin to end inclusive to the tail of dst */
static inline void list_move_slice_tail( struct list *dst, struct list *begin, struct list *end )
{
struct list *dst_prev = dst->prev;
begin->prev->next = end->next;
end->next->prev = begin->prev;
dst_prev->next = begin;
dst->prev = end;
begin->prev = dst_prev;
end->next = dst;
}
/* iterate through the list */
#define LIST_FOR_EACH(cursor,list) \
for ((cursor) = (list)->next; (cursor) != (list); (cursor) = (cursor)->next)

View file

@ -8,6 +8,7 @@ Chip Davis
Conor McCarthy
David Gow
Derek Lesho
Fabian Maurer
Francisco Casas
Francois Gouget
Giovanni Mascellani

View file

@ -1,4 +1,4 @@
Copyright 2016-2022 the Vkd3d project authors (see the file AUTHORS for a
Copyright 2016-2023 the Vkd3d project authors (see the file AUTHORS for a
complete list)
Vkd3d is free software; you can redistribute it and/or modify it under

View file

@ -34,6 +34,18 @@
extern "C" {
#endif /* __cplusplus */
/**
* \file vkd3d.h
*
* This file contains definitions for the vkd3d library.
*
* The vkd3d library is a 3D graphics library built on top of
* Vulkan. It has an API very similar, but not identical, to
* Direct3D 12.
*
* \since 1.0
*/
enum vkd3d_structure_type
{
/* 1.0 */
@ -63,6 +75,7 @@ enum vkd3d_api_version
VKD3D_API_VERSION_1_4,
VKD3D_API_VERSION_1_5,
VKD3D_API_VERSION_1_6,
VKD3D_API_VERSION_1_7,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_API_VERSION),
};

View file

@ -30,12 +30,12 @@ extern "C" {
/**
* \file vkd3d_shader.h
*
* \since 1.2
*
* This file contains definitions for the vkd3d-shader library.
*
* The vkd3d-shader library provides multiple utilities related to the
* compilation, transformation, and reflection of GPU shaders.
*
* \since 1.2
*/
/** \since 1.3 */
@ -48,6 +48,7 @@ enum vkd3d_shader_api_version
VKD3D_SHADER_API_VERSION_1_4,
VKD3D_SHADER_API_VERSION_1_5,
VKD3D_SHADER_API_VERSION_1_6,
VKD3D_SHADER_API_VERSION_1_7,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_API_VERSION),
};
@ -150,6 +151,18 @@ enum vkd3d_shader_compile_option_name
VKD3D_SHADER_COMPILE_OPTION_API_VERSION = 0x00000004,
/** \a value is a member of enum vkd3d_shader_compile_option_typed_uav. \since 1.5 */
VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV = 0x00000005,
/**
* If \a value is nonzero, write the point size for Vulkan tessellation and
* geometry shaders. This option should be enabled if and only if the
* shaderTessellationAndGeometryPointSize feature is enabled. The default
* value is nonzero, i.e. write the point size.
*
* This option is supported by vkd3d_shader_compile() for the SPIR-V target
* type and Vulkan targets; it should not be enabled otherwise.
*
* \since 1.7
*/
VKD3D_SHADER_COMPILE_OPTION_WRITE_TESS_GEOM_POINT_SIZE = 0x00000006,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME),
};
@ -1460,6 +1473,46 @@ enum vkd3d_shader_swizzle_component
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SWIZZLE_COMPONENT),
};
/**
* A description of a DXBC section.
*
* \since 1.7
*/
struct vkd3d_shader_dxbc_section_desc
{
/** The section tag. */
uint32_t tag;
/** The contents of the section. */
struct vkd3d_shader_code data;
};
/**
* A description of a DXBC blob, as returned by vkd3d_shader_parse_dxbc().
*
* \since 1.7
*/
struct vkd3d_shader_dxbc_desc
{
/**
* The DXBC tag. This will always be "DXBC" in structures returned by
* this version of vkd3d-shader.
*/
uint32_t tag;
/** A checksum of the DXBC contents. */
uint32_t checksum[4];
/**
* The DXBC version. This will always be 1 in structures returned by this
* version of vkd3d-shader.
*/
unsigned int version;
/** The total size of the DXBC blob. */
size_t size;
/** The number of sections contained in the DXBC. */
size_t section_count;
/** Descriptions of the sections contained in the DXBC. */
struct vkd3d_shader_dxbc_section_desc *sections;
};
/**
* A mask selecting one component from a vkd3d-shader swizzle. The component has
* type \ref vkd3d_shader_swizzle_component.
@ -1596,7 +1649,7 @@ VKD3D_SHADER_API const enum vkd3d_shader_target_type *vkd3d_shader_get_supported
* vkd3d_shader_compile_info. Regardless of the requested level, if this
* parameter is NULL, no compilation messages will be returned.
* \n
* If no compilation messages are produced by the compiler, this parameter may
* If no messages are produced by the compiler, this parameter may
* receive NULL instead of a valid string pointer.
*
* \return A member of \ref vkd3d_result.
@ -1645,10 +1698,15 @@ VKD3D_SHADER_API void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *co
* needed.
*
* \param messages Optional output location for error or informational messages
* produced by the compiler.
* produced by the parser.
* \n
* This parameter behaves identically to the \a messages parameter of
* vkd3d_shader_compile().
* This string is null-terminated and UTF-8 encoded.
* \n
* The messages are allocated by vkd3d-shader and should be freed with
* vkd3d_shader_free_messages() when no longer needed.
* \n
* If no messages are produced by the parser, this parameter may
* receive NULL instead of a valid string pointer.
*
* \return A member of \ref vkd3d_result.
*/
@ -1683,10 +1741,15 @@ VKD3D_SHADER_API void vkd3d_shader_free_root_signature(
* vkd3d_shader_free_shader_code() when no longer needed.
*
* \param messages Optional output location for error or informational messages
* produced by the compiler.
* produced by the serializer.
* \n
* This parameter behaves identically to the \a messages parameter of
* vkd3d_shader_compile().
* This string is null-terminated and UTF-8 encoded.
* \n
* The messages are allocated by vkd3d-shader and should be freed with
* vkd3d_shader_free_messages() when no longer needed.
* \n
* If no messages are produced by the serializer, this parameter may
* receive NULL instead of a valid string pointer.
*
* \return A member of \ref vkd3d_result.
*/
@ -1733,10 +1796,19 @@ VKD3D_SHADER_API int vkd3d_shader_convert_root_signature(struct vkd3d_shader_ver
* depending on their structure type.
*
* \param messages Optional output location for error or informational messages
* produced by the compiler.
* produced by the parser.
* \n
* This parameter behaves identically to the \a messages parameter of
* vkd3d_shader_compile().
* This string is null-terminated and UTF-8 encoded.
* \n
* The messages are allocated by vkd3d-shader and should be freed with
* vkd3d_shader_free_messages() when no longer needed.
* \n
* The messages returned can be regulated with the \a log_level member of struct
* vkd3d_shader_compile_info. Regardless of the requested level, if this
* parameter is NULL, no compilation messages will be returned.
* \n
* If no messages are produced by the parser, this parameter may
* receive NULL instead of a valid string pointer.
*
* \return A member of \ref vkd3d_result.
*/
@ -1768,12 +1840,20 @@ VKD3D_SHADER_API void vkd3d_shader_free_scan_descriptor_info(
* Members of \a signature may be allocated by vkd3d-shader. The signature
* should be freed with vkd3d_shader_free_shader_signature() when no longer
* needed.
* \n
* The signature may contain pointers into the input shader, and should only be
* accessed while the input shader remains valid.
*
* \param messages Optional output location for error or informational messages
* produced by the compiler.
* produced by the parser.
* \n
* This parameter behaves identically to the \a messages parameter of
* vkd3d_shader_compile().
* This string is null-terminated and UTF-8 encoded.
* \n
* The messages are allocated by vkd3d-shader and should be freed with
* vkd3d_shader_free_messages() when no longer needed.
* \n
* If no messages are produced by the parser, this parameter may
* receive NULL instead of a valid string pointer.
*
* \return A member of \ref vkd3d_result.
*/
@ -1829,10 +1909,19 @@ VKD3D_SHADER_API void vkd3d_shader_free_shader_signature(struct vkd3d_shader_sig
* vkd3d_shader_free_shader_code() when no longer needed.
*
* \param messages Optional output location for error or informational messages
* produced by the compiler.
* produced by the preprocessor.
* \n
* This parameter behaves identically to the \a messages parameter of
* vkd3d_shader_compile().
* This string is null-terminated and UTF-8 encoded.
* \n
* The messages are allocated by vkd3d-shader and should be freed with
* vkd3d_shader_free_messages() when no longer needed.
* \n
* The messages returned can be regulated with the \a log_level member of struct
* vkd3d_shader_compile_info. Regardless of the requested level, if this
* parameter is NULL, no compilation messages will be returned.
* \n
* If no messages are produced by the preprocessor, this parameter may
* receive NULL instead of a valid string pointer.
*
* \return A member of \ref vkd3d_result.
*
@ -1853,6 +1942,85 @@ VKD3D_SHADER_API int vkd3d_shader_preprocess(const struct vkd3d_shader_compile_i
*/
VKD3D_SHADER_API void vkd3d_shader_set_log_callback(PFN_vkd3d_log callback);
/**
* Free the contents of a vkd3d_shader_dxbc_desc structure allocated by
* another vkd3d-shader function, such as vkd3d_shader_parse_dxbc().
*
* This function may free the \ref vkd3d_shader_dxbc_desc.sections member, but
* does not free the structure itself.
*
* \param dxbc The vkd3d_shader_dxbc_desc structure to free.
*
* \since 1.7
*/
VKD3D_SHADER_API void vkd3d_shader_free_dxbc(struct vkd3d_shader_dxbc_desc *dxbc);
/**
* Parse a DXBC blob contained in a vkd3d_shader_code structure.
*
* \param dxbc A vkd3d_shader_code structure containing the DXBC blob to parse.
*
* \param flags A set of flags modifying the behaviour of the function. No
* flags are defined for this version of vkd3d-shader, and this parameter
* should be set to 0.
*
* \param desc A vkd3d_shader_dxbc_desc structure describing the contents of
* the DXBC blob. Its vkd3d_shader_dxbc_section_desc structures will contain
* pointers into the input blob; its contents are only valid while the input
* blob is valid. The contents of this structure should be freed with
* vkd3d_shader_free_dxbc() when no longer needed.
*
* \param messages Optional output location for error or informational messages
* produced by the parser.
* \n
* This string is null-terminated and UTF-8 encoded.
* \n
* The messages are allocated by vkd3d-shader and should be freed with
* vkd3d_shader_free_messages() when no longer needed.
* \n
* If no messages are produced by the parser, this parameter may
* receive NULL instead of a valid string pointer.
*
* \return A member of \ref vkd3d_result.
*
* \since 1.7
*/
VKD3D_SHADER_API int vkd3d_shader_parse_dxbc(const struct vkd3d_shader_code *dxbc,
uint32_t flags, struct vkd3d_shader_dxbc_desc *desc, char **messages);
/**
* Serialize a DXBC description into a blob stored in a vkd3d_shader_code
* structure.
*
* \param section_count The number of DXBC sections to serialize.
*
* \param sections An array of vkd3d_shader_dxbc_section_desc structures
* to serialize.
*
* \param dxbc A pointer to a vkd3d_shader_code structure in which the
* serialized blob will be stored.
* \n
* The output blob is allocated by vkd3d-shader and should be freed with
* vkd3d_shader_free_shader_code() when no longer needed.
*
* \param messages Optional output location for error or informational messages
* produced by the serializer.
* \n
* This string is null-terminated and UTF-8 encoded.
* \n
* The messages are allocated by vkd3d-shader and should be freed with
* vkd3d_shader_free_messages() when no longer needed.
* \n
* If no messages are produced by the serializer, this parameter may
* receive NULL instead of a valid string pointer.
*
* \return A member of \ref vkd3d_result.
*
* \since 1.7
*/
VKD3D_SHADER_API int vkd3d_shader_serialize_dxbc(size_t section_count,
const struct vkd3d_shader_dxbc_section_desc *sections, struct vkd3d_shader_code *dxbc, char **messages);
#endif /* VKD3D_SHADER_NO_PROTOTYPES */
/** Type of vkd3d_shader_get_version(). */
@ -1909,6 +2077,15 @@ typedef void (*PFN_vkd3d_shader_preprocess)(struct vkd3d_shader_compile_info *co
/** Type of vkd3d_shader_set_log_callback(). \since 1.4 */
typedef void (*PFN_vkd3d_shader_set_log_callback)(PFN_vkd3d_log callback);
/** Type of vkd3d_shader_free_dxbc(). \since 1.7 */
typedef void (*PFN_vkd3d_shader_free_dxbc)(struct vkd3d_shader_dxbc_desc *dxbc);
/** Type of vkd3d_shader_parse_dxbc(). \since 1.7 */
typedef int (*PFN_vkd3d_shader_parse_dxbc)(const struct vkd3d_shader_code *dxbc,
uint32_t flags, struct vkd3d_shader_dxbc_desc *desc, char **messages);
/** Type of vkd3d_shader_serialize_dxbc(). \since 1.7 */
typedef int (*PFN_vkd3d_shader_serialize_dxbc)(size_t section_count,
const struct vkd3d_shader_dxbc_section_desc *sections, struct vkd3d_shader_code *dxbc, char **messages);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View file

@ -210,13 +210,6 @@ struct vkd3d_shader_sm1_parser
const uint32_t *start, *end;
bool abort;
struct vkd3d_shader_src_param src_rel_addr[4];
struct vkd3d_shader_src_param pred_rel_addr;
struct vkd3d_shader_src_param dst_rel_addr;
struct vkd3d_shader_src_param src_param[4];
struct vkd3d_shader_src_param pred_param;
struct vkd3d_shader_dst_param dst_param;
struct vkd3d_shader_parser p;
};
@ -556,33 +549,50 @@ static void shader_sm1_destroy(struct vkd3d_shader_parser *parser)
{
struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser);
shader_instruction_array_destroy(&parser->instructions);
free_shader_desc(&sm1->p.shader_desc);
vkd3d_free(sm1);
}
static void shader_sm1_read_src_param(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr,
struct vkd3d_shader_src_param *src_param, struct vkd3d_shader_src_param *src_rel_addr)
struct vkd3d_shader_src_param *src_param)
{
struct vkd3d_shader_src_param *src_rel_addr = NULL;
uint32_t token, addr_token;
shader_sm1_read_param(sm1, ptr, &token, &addr_token);
if (has_relative_address(token))
{
if (!(src_rel_addr = shader_parser_get_src_params(&sm1->p, 1)))
{
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY,
"Out of memory.");
sm1->abort = true;
return;
}
shader_sm1_parse_src_param(addr_token, NULL, src_rel_addr);
else
src_rel_addr = NULL;
}
shader_sm1_parse_src_param(token, src_rel_addr, src_param);
}
static void shader_sm1_read_dst_param(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr,
struct vkd3d_shader_dst_param *dst_param, struct vkd3d_shader_src_param *dst_rel_addr)
struct vkd3d_shader_dst_param *dst_param)
{
struct vkd3d_shader_src_param *dst_rel_addr = NULL;
uint32_t token, addr_token;
shader_sm1_read_param(sm1, ptr, &token, &addr_token);
if (has_relative_address(token))
{
if (!(dst_rel_addr = shader_parser_get_src_params(&sm1->p, 1)))
{
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY,
"Out of memory.");
sm1->abort = true;
return;
}
shader_sm1_parse_src_param(addr_token, NULL, dst_rel_addr);
else
dst_rel_addr = NULL;
}
shader_sm1_parse_dst_param(token, dst_rel_addr, dst_param);
}
@ -731,10 +741,13 @@ static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1,
static void shader_sm1_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins)
{
struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser);
struct vkd3d_shader_src_param *src_params, *predicate;
const struct vkd3d_sm1_opcode_info *opcode_info;
struct vkd3d_shader_dst_param *dst_param;
const uint32_t **ptr = &parser->ptr;
uint32_t opcode_token;
const uint32_t *p;
bool predicated;
unsigned int i;
shader_sm1_read_comment(sm1);
@ -761,11 +774,18 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_parser *parser, stru
ins->coissue = opcode_token & VKD3D_SM1_COISSUE;
ins->raw = false;
ins->structured = false;
ins->predicate = opcode_token & VKD3D_SM1_INSTRUCTION_PREDICATED ? &sm1->pred_param : NULL;
predicated = !!(opcode_token & VKD3D_SM1_INSTRUCTION_PREDICATED);
ins->predicate = predicate = predicated ? shader_parser_get_src_params(parser, 1) : NULL;
ins->dst_count = opcode_info->dst_count;
ins->dst = &sm1->dst_param;
ins->dst = dst_param = shader_parser_get_dst_params(parser, ins->dst_count);
ins->src_count = opcode_info->src_count;
ins->src = sm1->src_param;
ins->src = src_params = shader_parser_get_src_params(parser, ins->src_count);
if ((!predicate && predicated) || (!src_params && ins->src_count) || (!dst_param && ins->dst_count))
{
vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, "Out of memory.");
goto fail;
}
ins->resource_type = VKD3D_SHADER_RESOURCE_NONE;
ins->resource_stride = 0;
ins->resource_data_type[0] = VKD3D_DATA_FLOAT;
@ -790,32 +810,32 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_parser *parser, stru
}
else if (ins->handler_idx == VKD3DSIH_DEF)
{
shader_sm1_read_dst_param(sm1, &p, &sm1->dst_param, &sm1->dst_rel_addr);
shader_sm1_read_immconst(sm1, &p, &sm1->src_param[0], VKD3D_IMMCONST_VEC4, VKD3D_DATA_FLOAT);
shader_sm1_read_dst_param(sm1, &p, dst_param);
shader_sm1_read_immconst(sm1, &p, &src_params[0], VKD3D_IMMCONST_VEC4, VKD3D_DATA_FLOAT);
}
else if (ins->handler_idx == VKD3DSIH_DEFB)
{
shader_sm1_read_dst_param(sm1, &p, &sm1->dst_param, &sm1->dst_rel_addr);
shader_sm1_read_immconst(sm1, &p, &sm1->src_param[0], VKD3D_IMMCONST_SCALAR, VKD3D_DATA_UINT);
shader_sm1_read_dst_param(sm1, &p, dst_param);
shader_sm1_read_immconst(sm1, &p, &src_params[0], VKD3D_IMMCONST_SCALAR, VKD3D_DATA_UINT);
}
else if (ins->handler_idx == VKD3DSIH_DEFI)
{
shader_sm1_read_dst_param(sm1, &p, &sm1->dst_param, &sm1->dst_rel_addr);
shader_sm1_read_immconst(sm1, &p, &sm1->src_param[0], VKD3D_IMMCONST_VEC4, VKD3D_DATA_INT);
shader_sm1_read_dst_param(sm1, &p, dst_param);
shader_sm1_read_immconst(sm1, &p, &src_params[0], VKD3D_IMMCONST_VEC4, VKD3D_DATA_INT);
}
else
{
/* Destination token */
if (ins->dst_count)
shader_sm1_read_dst_param(sm1, &p, &sm1->dst_param, &sm1->dst_rel_addr);
shader_sm1_read_dst_param(sm1, &p, dst_param);
/* Predication token */
if (ins->predicate)
shader_sm1_read_src_param(sm1, &p, &sm1->pred_param, &sm1->pred_rel_addr);
shader_sm1_read_src_param(sm1, &p, predicate);
/* Other source tokens */
for (i = 0; i < ins->src_count; ++i)
shader_sm1_read_src_param(sm1, &p, &sm1->src_param[i], &sm1->src_rel_addr[i]);
shader_sm1_read_src_param(sm1, &p, &src_params[i]);
}
if (sm1->abort)
@ -851,20 +871,9 @@ static bool shader_sm1_is_end(struct vkd3d_shader_parser *parser)
return false;
}
static void shader_sm1_reset(struct vkd3d_shader_parser *parser)
{
struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser);
parser->ptr = sm1->start;
parser->failed = false;
}
const struct vkd3d_shader_parser_ops shader_sm1_parser_ops =
{
.parser_reset = shader_sm1_reset,
.parser_destroy = shader_sm1_destroy,
.parser_read_instruction = shader_sm1_read_instruction,
.parser_is_end = shader_sm1_is_end,
};
static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1,
@ -922,7 +931,10 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1,
sm1->start = &code[1];
sm1->end = &code[token_count];
vkd3d_shader_parser_init(&sm1->p, message_context, compile_info->source_name, &version, &shader_sm1_parser_ops);
/* Estimate instruction count to avoid reallocation in most shaders. */
if (!vkd3d_shader_parser_init(&sm1->p, message_context, compile_info->source_name, &version, &shader_sm1_parser_ops,
code_size != ~(size_t)0 ? token_count / 4u + 4 : 16))
return VKD3D_ERROR_OUT_OF_MEMORY;
shader_desc = &sm1->p.shader_desc;
shader_desc->byte_code = code;
shader_desc->byte_code_size = code_size;
@ -934,6 +946,8 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1,
int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser)
{
struct vkd3d_shader_instruction_array *instructions;
struct vkd3d_shader_instruction *ins;
struct vkd3d_shader_sm1_parser *sm1;
int ret;
@ -950,6 +964,28 @@ int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compi
return ret;
}
instructions = &sm1->p.instructions;
while (!shader_sm1_is_end(&sm1->p))
{
if (!shader_instruction_array_reserve(instructions, instructions->count + 1))
{
ERR("Failed to allocate instructions.\n");
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, "Out of memory.");
shader_sm1_destroy(&sm1->p);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
ins = &instructions->elements[instructions->count];
shader_sm1_read_instruction(&sm1->p, ins);
if (ins->handler_idx == VKD3DSIH_INVALID)
{
WARN("Encountered unrecognized or invalid instruction.\n");
shader_sm1_destroy(&sm1->p);
return VKD3D_ERROR_INVALID_SHADER;
}
++instructions->count;
}
*parser = &sm1->p;
return VKD3D_OK;

View file

@ -33,22 +33,28 @@ void dxbc_writer_init(struct dxbc_writer *dxbc)
void dxbc_writer_add_section(struct dxbc_writer *dxbc, uint32_t tag, const void *data, size_t size)
{
struct dxbc_writer_section *section;
struct vkd3d_shader_dxbc_section_desc *section;
assert(dxbc->section_count < ARRAY_SIZE(dxbc->sections));
section = &dxbc->sections[dxbc->section_count++];
section->tag = tag;
section->data = data;
section->size = size;
section->data.code = data;
section->data.size = size;
}
int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
int vkd3d_shader_serialize_dxbc(size_t section_count, const struct vkd3d_shader_dxbc_section_desc *sections,
struct vkd3d_shader_code *dxbc, char **messages)
{
size_t size_position, offsets_position, checksum_position, i;
struct vkd3d_bytecode_buffer buffer = {0};
uint32_t checksum[4];
TRACE("section_count %zu, sections %p, dxbc %p, messages %p.\n", section_count, sections, dxbc, messages);
if (messages)
*messages = NULL;
put_u32(&buffer, TAG_DXBC);
checksum_position = bytecode_get_size(&buffer);
@ -57,18 +63,18 @@ int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
put_u32(&buffer, 1); /* version */
size_position = put_u32(&buffer, 0);
put_u32(&buffer, dxbc->section_count);
put_u32(&buffer, section_count);
offsets_position = bytecode_get_size(&buffer);
for (i = 0; i < dxbc->section_count; ++i)
for (i = 0; i < section_count; ++i)
put_u32(&buffer, 0);
for (i = 0; i < dxbc->section_count; ++i)
for (i = 0; i < section_count; ++i)
{
set_u32(&buffer, offsets_position + i * sizeof(uint32_t), bytecode_get_size(&buffer));
put_u32(&buffer, dxbc->sections[i].tag);
put_u32(&buffer, dxbc->sections[i].size);
bytecode_put_bytes(&buffer, dxbc->sections[i].data, dxbc->sections[i].size);
put_u32(&buffer, sections[i].tag);
put_u32(&buffer, sections[i].data.size);
bytecode_put_bytes(&buffer, sections[i].data.code, sections[i].data.size);
}
set_u32(&buffer, size_position, bytecode_get_size(&buffer));
@ -78,12 +84,17 @@ int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
if (!buffer.status)
{
out->code = buffer.data;
out->size = buffer.size;
dxbc->code = buffer.data;
dxbc->size = buffer.size;
}
return buffer.status;
}
int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
{
return vkd3d_shader_serialize_dxbc(dxbc->section_count, dxbc->sections, out, NULL);
}
struct vkd3d_shader_src_param_entry
{
struct list entry;
@ -96,12 +107,6 @@ struct vkd3d_shader_sm4_parser
unsigned int output_map[MAX_REG_OUTPUT];
struct vkd3d_shader_src_param src_param[SM4_MAX_SRC_COUNT];
struct vkd3d_shader_dst_param dst_param[SM4_MAX_DST_COUNT];
struct list src_free;
struct list src;
struct vkd3d_shader_immediate_constant_buffer icb;
struct vkd3d_shader_parser p;
};
@ -206,7 +211,8 @@ static bool shader_sm4_read_register_space(struct vkd3d_shader_sm4_parser *priv,
static void shader_sm4_read_conditional_op(struct vkd3d_shader_instruction *ins, uint32_t opcode,
uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
{
shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, &priv->src_param[0]);
shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT,
(struct vkd3d_shader_src_param *)&ins->src[0]);
ins->flags = (opcode_token & VKD3D_SM4_CONDITIONAL_NZ) ?
VKD3D_SHADER_CONDITIONAL_OP_NZ : VKD3D_SHADER_CONDITIONAL_OP_Z;
}
@ -214,6 +220,7 @@ static void shader_sm4_read_conditional_op(struct vkd3d_shader_instruction *ins,
static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token,
const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
{
struct vkd3d_shader_immediate_constant_buffer *icb;
enum vkd3d_sm4_shader_data_type type;
unsigned int icb_size;
@ -227,16 +234,24 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui
++tokens;
icb_size = token_count - 1;
if (icb_size % 4 || icb_size > MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE)
if (icb_size % 4)
{
FIXME("Unexpected immediate constant buffer size %u.\n", icb_size);
ins->handler_idx = VKD3DSIH_INVALID;
return;
}
priv->icb.vec4_count = icb_size / 4;
memcpy(priv->icb.data, tokens, sizeof(*tokens) * icb_size);
ins->declaration.icb = &priv->icb;
if (!(icb = vkd3d_malloc(offsetof(struct vkd3d_shader_immediate_constant_buffer, data[icb_size]))))
{
ERR("Failed to allocate immediate constant buffer, size %u.\n", icb_size);
vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory.");
ins->handler_idx = VKD3DSIH_INVALID;
return;
}
icb->vec4_count = icb_size / 4;
memcpy(icb->data, tokens, sizeof(*tokens) * icb_size);
shader_instruction_array_add_icb(&priv->p.instructions, icb);
ins->declaration.icb = icb;
}
static void shader_sm4_set_descriptor_register_range(struct vkd3d_shader_sm4_parser *sm4,
@ -273,6 +288,13 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, u
{
semantic->resource_type = resource_type_table[resource_type];
}
if (semantic->resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS
|| semantic->resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY)
{
semantic->sample_count = (opcode_token & VKD3D_SM4_RESOURCE_SAMPLE_COUNT_MASK) >> VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT;
}
reg_data_type = opcode == VKD3D_SM4_OP_DCL_RESOURCE ? VKD3D_DATA_RESOURCE : VKD3D_DATA_UAV;
shader_sm4_read_dst_param(priv, &tokens, end, reg_data_type, &semantic->resource.reg);
shader_sm4_set_descriptor_register_range(priv, &semantic->resource.reg.reg, &semantic->resource.range);
@ -438,8 +460,9 @@ static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *in
static void shader_sm5_read_fcall(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token,
const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
{
priv->src_param[0].reg.u.fp_body_idx = *tokens++;
shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &priv->src_param[0]);
struct vkd3d_shader_src_param *src_params = (struct vkd3d_shader_src_param *)ins->src;
src_params[0].reg.u.fp_body_idx = *tokens++;
shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &src_params[0]);
}
static void shader_sm5_read_dcl_function_body(struct vkd3d_shader_instruction *ins, uint32_t opcode,
@ -687,7 +710,7 @@ static const struct vkd3d_sm4_opcode_info opcode_table[] =
{VKD3D_SM4_OP_USHR, VKD3DSIH_USHR, "u", "uu"},
{VKD3D_SM4_OP_UTOF, VKD3DSIH_UTOF, "f", "u"},
{VKD3D_SM4_OP_XOR, VKD3DSIH_XOR, "u", "uu"},
{VKD3D_SM4_OP_DCL_RESOURCE, VKD3DSIH_DCL, "R", "",
{VKD3D_SM4_OP_DCL_RESOURCE, VKD3DSIH_DCL, "", "",
shader_sm4_read_dcl_resource},
{VKD3D_SM4_OP_DCL_CONSTANT_BUFFER, VKD3DSIH_DCL_CONSTANT_BUFFER, "", "",
shader_sm4_read_dcl_constant_buffer},
@ -987,45 +1010,18 @@ static enum vkd3d_data_type map_data_type(char t)
static void shader_sm4_destroy(struct vkd3d_shader_parser *parser)
{
struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser);
struct vkd3d_shader_src_param_entry *e1, *e2;
list_move_head(&sm4->src_free, &sm4->src);
LIST_FOR_EACH_ENTRY_SAFE(e1, e2, &sm4->src_free, struct vkd3d_shader_src_param_entry, entry)
{
vkd3d_free(e1);
}
shader_instruction_array_destroy(&parser->instructions);
free_shader_desc(&parser->shader_desc);
vkd3d_free(sm4);
}
static struct vkd3d_shader_src_param *get_src_param(struct vkd3d_shader_sm4_parser *priv)
{
struct vkd3d_shader_src_param_entry *e;
struct list *elem;
if (!list_empty(&priv->src_free))
{
elem = list_head(&priv->src_free);
list_remove(elem);
}
else
{
if (!(e = vkd3d_malloc(sizeof(*e))))
return NULL;
elem = &e->entry;
}
list_add_tail(&priv->src, elem);
e = LIST_ENTRY(elem, struct vkd3d_shader_src_param_entry, entry);
return &e->param;
}
static bool shader_sm4_read_reg_idx(struct vkd3d_shader_sm4_parser *priv, const uint32_t **ptr,
const uint32_t *end, uint32_t addressing, struct vkd3d_shader_register_index *reg_idx)
{
if (addressing & VKD3D_SM4_ADDRESSING_RELATIVE)
{
struct vkd3d_shader_src_param *rel_addr = get_src_param(priv);
struct vkd3d_shader_src_param *rel_addr = shader_parser_get_src_params(&priv->p, 1);
if (!(reg_idx->rel_addr = rel_addr))
{
@ -1468,14 +1464,14 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, stru
struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser);
const struct vkd3d_sm4_opcode_info *opcode_info;
uint32_t opcode_token, opcode, previous_token;
struct vkd3d_shader_dst_param *dst_params;
struct vkd3d_shader_src_param *src_params;
const uint32_t **ptr = &parser->ptr;
unsigned int i, len;
size_t remaining;
const uint32_t *p;
DWORD precise;
list_move_head(&sm4->src_free, &sm4->src);
if (*ptr >= sm4->end)
{
WARN("End of byte-code, failed to read opcode.\n");
@ -1520,11 +1516,15 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, stru
ins->structured = false;
ins->predicate = NULL;
ins->dst_count = strnlen(opcode_info->dst_info, SM4_MAX_DST_COUNT);
ins->dst = sm4->dst_param;
ins->src_count = strnlen(opcode_info->src_info, SM4_MAX_SRC_COUNT);
ins->src = sm4->src_param;
assert(ins->dst_count <= ARRAY_SIZE(sm4->dst_param));
assert(ins->src_count <= ARRAY_SIZE(sm4->src_param));
ins->src = src_params = shader_parser_get_src_params(parser, ins->src_count);
if (!src_params && ins->src_count)
{
ERR("Failed to allocate src parameters.\n");
vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory.");
ins->handler_idx = VKD3DSIH_INVALID;
return;
}
ins->resource_type = VKD3D_SHADER_RESOURCE_NONE;
ins->resource_stride = 0;
ins->resource_data_type[0] = VKD3D_DATA_FLOAT;
@ -1538,6 +1538,8 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, stru
if (opcode_info->read_opcode_func)
{
ins->dst = NULL;
ins->dst_count = 0;
opcode_info->read_opcode_func(ins, opcode, opcode_token, p, len, sm4);
}
else
@ -1557,21 +1559,29 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, stru
precise = (opcode_token & VKD3D_SM5_PRECISE_MASK) >> VKD3D_SM5_PRECISE_SHIFT;
ins->flags |= precise << VKD3DSI_PRECISE_SHIFT;
ins->dst = dst_params = shader_parser_get_dst_params(parser, ins->dst_count);
if (!dst_params && ins->dst_count)
{
ERR("Failed to allocate dst parameters.\n");
vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory.");
ins->handler_idx = VKD3DSIH_INVALID;
return;
}
for (i = 0; i < ins->dst_count; ++i)
{
if (!(shader_sm4_read_dst_param(sm4, &p, *ptr, map_data_type(opcode_info->dst_info[i]),
&sm4->dst_param[i])))
&dst_params[i])))
{
ins->handler_idx = VKD3DSIH_INVALID;
return;
}
sm4->dst_param[i].modifiers |= instruction_dst_modifier;
dst_params[i].modifiers |= instruction_dst_modifier;
}
for (i = 0; i < ins->src_count; ++i)
{
if (!(shader_sm4_read_src_param(sm4, &p, *ptr, map_data_type(opcode_info->src_info[i]),
&sm4->src_param[i])))
&src_params[i])))
{
ins->handler_idx = VKD3DSIH_INVALID;
return;
@ -1594,20 +1604,9 @@ static bool shader_sm4_is_end(struct vkd3d_shader_parser *parser)
return parser->ptr == sm4->end;
}
static void shader_sm4_reset(struct vkd3d_shader_parser *parser)
{
struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser);
parser->ptr = sm4->start;
parser->failed = false;
}
static const struct vkd3d_shader_parser_ops shader_sm4_parser_ops =
{
.parser_reset = shader_sm4_reset,
.parser_destroy = shader_sm4_destroy,
.parser_read_instruction = shader_sm4_read_instruction,
.parser_is_end = shader_sm4_is_end,
};
static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t *byte_code,
@ -1670,7 +1669,10 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t
version.major = VKD3D_SM4_VERSION_MAJOR(version_token);
version.minor = VKD3D_SM4_VERSION_MINOR(version_token);
vkd3d_shader_parser_init(&sm4->p, message_context, source_name, &version, &shader_sm4_parser_ops);
/* Estimate instruction count to avoid reallocation in most shaders. */
if (!vkd3d_shader_parser_init(&sm4->p, message_context, source_name, &version, &shader_sm4_parser_ops,
token_count / 7u + 20))
return false;
sm4->p.ptr = sm4->start;
memset(sm4->output_map, 0xff, sizeof(sm4->output_map));
@ -1690,9 +1692,6 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t
sm4->output_map[e->register_index] = e->semantic_index;
}
list_init(&sm4->src_free);
list_init(&sm4->src);
return true;
}
@ -1718,6 +1717,9 @@ static void skip_dword_unknown(const char **ptr, unsigned int count)
unsigned int i;
uint32_t d;
if (!count)
return;
WARN("Skipping %u unknown DWORDs:\n", count);
for (i = 0; i < count; ++i)
{
@ -1745,18 +1747,19 @@ static const char *shader_get_string(const char *data, size_t data_size, DWORD o
return data + offset;
}
static int parse_dxbc(const char *data, size_t data_size,
struct vkd3d_shader_message_context *message_context, const char *source_name,
int (*chunk_handler)(const char *data, DWORD data_size, DWORD tag, void *ctx), void *ctx)
static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context,
const char *source_name, struct vkd3d_shader_dxbc_desc *desc)
{
const struct vkd3d_shader_location location = {.source_name = source_name};
struct vkd3d_shader_dxbc_section_desc *sections, *section;
uint32_t checksum[4], calculated_checksum[4];
const char *data = dxbc->code;
size_t data_size = dxbc->size;
const char *ptr = data;
int ret = VKD3D_OK;
uint32_t chunk_count;
uint32_t total_size;
unsigned int i;
uint32_t version;
unsigned int i;
uint32_t tag;
if (data_size < VKD3D_DXBC_HEADER_SIZE)
@ -1810,6 +1813,12 @@ static int parse_dxbc(const char *data, size_t data_size,
read_dword(&ptr, &chunk_count);
TRACE("chunk count: %#x\n", chunk_count);
if (!(sections = vkd3d_calloc(chunk_count, sizeof(*sections))))
{
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_OUT_OF_MEMORY, "Out of memory.");
return VKD3D_ERROR_OUT_OF_MEMORY;
}
for (i = 0; i < chunk_count; ++i)
{
uint32_t chunk_tag, chunk_size;
@ -1824,6 +1833,7 @@ static int parse_dxbc(const char *data, size_t data_size,
WARN("Invalid chunk offset %#x (data size %zu).\n", chunk_offset, data_size);
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET,
"DXBC chunk %u has invalid offset %#x (data size %#zx).", i, chunk_offset, data_size);
vkd3d_free(sections);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
@ -1839,39 +1849,120 @@ static int parse_dxbc(const char *data, size_t data_size,
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE,
"DXBC chunk %u has invalid size %#x (data size %#zx, chunk offset %#x).",
i, chunk_offset, data_size, chunk_offset);
vkd3d_free(sections);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
if ((ret = chunk_handler(chunk_ptr, chunk_size, chunk_tag, ctx)) < 0)
section = &sections[i];
section->tag = chunk_tag;
section->data.code = chunk_ptr;
section->data.size = chunk_size;
}
desc->tag = tag;
memcpy(desc->checksum, checksum, sizeof(checksum));
desc->version = version;
desc->size = total_size;
desc->section_count = chunk_count;
desc->sections = sections;
return VKD3D_OK;
}
void vkd3d_shader_free_dxbc(struct vkd3d_shader_dxbc_desc *dxbc)
{
TRACE("dxbc %p.\n", dxbc);
vkd3d_free(dxbc->sections);
}
static int for_each_dxbc_section(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_message_context *message_context, const char *source_name,
int (*section_handler)(const struct vkd3d_shader_dxbc_section_desc *section,
struct vkd3d_shader_message_context *message_context, void *ctx), void *ctx)
{
struct vkd3d_shader_dxbc_desc desc;
unsigned int i;
int ret;
if ((ret = parse_dxbc(dxbc, message_context, source_name, &desc)) < 0)
return ret;
for (i = 0; i < desc.section_count; ++i)
{
if ((ret = section_handler(&desc.sections[i], message_context, ctx)) < 0)
break;
}
vkd3d_shader_free_dxbc(&desc);
return ret;
}
static int shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
struct vkd3d_shader_signature *s)
int vkd3d_shader_parse_dxbc(const struct vkd3d_shader_code *dxbc,
uint32_t flags, struct vkd3d_shader_dxbc_desc *desc, char **messages)
{
struct vkd3d_shader_message_context message_context;
int ret;
TRACE("dxbc {%p, %zu}, flags %#x, desc %p, messages %p.\n", dxbc->code, dxbc->size, flags, desc, messages);
if (messages)
*messages = NULL;
vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO);
ret = parse_dxbc(dxbc, &message_context, NULL, desc);
vkd3d_shader_message_context_trace_messages(&message_context);
if (!vkd3d_shader_message_context_copy_messages(&message_context, messages) && ret >= 0)
{
vkd3d_shader_free_dxbc(desc);
ret = VKD3D_ERROR_OUT_OF_MEMORY;
}
vkd3d_shader_message_context_cleanup(&message_context);
if (ret < 0)
memset(desc, 0, sizeof(*desc));
return ret;
}
static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *section,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_signature *s)
{
bool has_stream_index, has_min_precision;
struct vkd3d_shader_signature_element *e;
const char *data = section->data.code;
uint32_t count, header_size;
const char *ptr = data;
unsigned int i;
uint32_t count;
if (!require_space(0, 2, sizeof(DWORD), data_size))
if (!require_space(0, 2, sizeof(uint32_t), section->data.size))
{
WARN("Invalid data size %#x.\n", data_size);
WARN("Invalid data size %#zx.\n", section->data.size);
vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_SIGNATURE,
"Section size %zu is smaller than the minimum signature header size.\n", section->data.size);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
read_dword(&ptr, &count);
TRACE("%u elements.\n", count);
skip_dword_unknown(&ptr, 1); /* It seems to always be 0x00000008. */
if (!require_space(ptr - data, count, 6 * sizeof(DWORD), data_size))
read_dword(&ptr, &header_size);
i = header_size / sizeof(uint32_t);
if (align(header_size, sizeof(uint32_t)) != header_size || i < 2
|| !require_space(2, i - 2, sizeof(uint32_t), section->data.size))
{
WARN("Invalid count %#x (data size %#x).\n", count, data_size);
WARN("Invalid header size %#x.\n", header_size);
vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_SIGNATURE,
"Signature header size %#x is invalid.\n", header_size);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
skip_dword_unknown(&ptr, i - 2);
if (!require_space(ptr - data, count, 6 * sizeof(uint32_t), section->data.size))
{
WARN("Invalid count %#x (data size %#zx).\n", count, section->data.size);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
@ -1881,8 +1972,8 @@ static int shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
return VKD3D_ERROR_OUT_OF_MEMORY;
}
has_min_precision = tag == TAG_OSG1 || tag == TAG_PSG1 || tag == TAG_ISG1;
has_stream_index = tag == TAG_OSG5 || has_min_precision;
has_min_precision = section->tag == TAG_OSG1 || section->tag == TAG_PSG1 || section->tag == TAG_ISG1;
has_stream_index = section->tag == TAG_OSG5 || has_min_precision;
for (i = 0; i < count; ++i)
{
@ -1894,9 +1985,9 @@ static int shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
e[i].stream_index = 0;
read_dword(&ptr, &name_offset);
if (!(e[i].semantic_name = shader_get_string(data, data_size, name_offset)))
if (!(e[i].semantic_name = shader_get_string(data, section->data.size, name_offset)))
{
WARN("Invalid name offset %#x (data size %#x).\n", name_offset, data_size);
WARN("Invalid name offset %#x (data size %#zx).\n", name_offset, section->data.size);
vkd3d_free(e);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
@ -1907,7 +1998,7 @@ static int shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
read_dword(&ptr, &mask);
e[i].mask = mask & 0xff;
e[i].used_mask = (mask >> 8) & 0xff;
switch (tag)
switch (section->tag)
{
case TAG_OSGN:
case TAG_OSG1:
@ -1935,11 +2026,12 @@ static int shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
return VKD3D_OK;
}
static int isgn_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
static int isgn_handler(const struct vkd3d_shader_dxbc_section_desc *section,
struct vkd3d_shader_message_context *message_context, void *ctx)
{
struct vkd3d_shader_signature *is = ctx;
if (tag != TAG_ISGN)
if (section->tag != TAG_ISGN)
return VKD3D_OK;
if (is->elements)
@ -1947,27 +2039,28 @@ static int isgn_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
FIXME("Multiple input signatures.\n");
vkd3d_shader_free_shader_signature(is);
}
return shader_parse_signature(tag, data, data_size, is);
return shader_parse_signature(section, message_context, is);
}
int shader_parse_input_signature(const void *dxbc, size_t dxbc_length,
int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_signature *signature)
{
int ret;
memset(signature, 0, sizeof(*signature));
if ((ret = parse_dxbc(dxbc, dxbc_length, message_context, NULL, isgn_handler, signature)) < 0)
if ((ret = for_each_dxbc_section(dxbc, message_context, NULL, isgn_handler, signature)) < 0)
ERR("Failed to parse input signature.\n");
return ret;
}
static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *context)
static int shdr_handler(const struct vkd3d_shader_dxbc_section_desc *section,
struct vkd3d_shader_message_context *message_context, void *context)
{
struct vkd3d_shader_desc *desc = context;
int ret;
switch (tag)
switch (section->tag)
{
case TAG_ISGN:
case TAG_ISG1:
@ -1976,7 +2069,7 @@ static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *cont
FIXME("Multiple input signatures.\n");
break;
}
if ((ret = shader_parse_signature(tag, data, data_size, &desc->input_signature)) < 0)
if ((ret = shader_parse_signature(section, message_context, &desc->input_signature)) < 0)
return ret;
break;
@ -1988,7 +2081,7 @@ static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *cont
FIXME("Multiple output signatures.\n");
break;
}
if ((ret = shader_parse_signature(tag, data, data_size, &desc->output_signature)) < 0)
if ((ret = shader_parse_signature(section, message_context, &desc->output_signature)) < 0)
return ret;
break;
@ -1999,7 +2092,7 @@ static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *cont
FIXME("Multiple patch constant signatures.\n");
break;
}
if ((ret = shader_parse_signature(tag, data, data_size, &desc->patch_constant_signature)) < 0)
if ((ret = shader_parse_signature(section, message_context, &desc->patch_constant_signature)) < 0)
return ret;
break;
@ -2007,8 +2100,8 @@ static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *cont
case TAG_SHEX:
if (desc->byte_code)
FIXME("Multiple shader code chunks.\n");
desc->byte_code = (const uint32_t *)data;
desc->byte_code_size = data_size;
desc->byte_code = section->data.code;
desc->byte_code_size = section->data.size;
break;
case TAG_AON9:
@ -2020,7 +2113,7 @@ static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *cont
break;
default:
TRACE("Skipping chunk %#x.\n", tag);
TRACE("Skipping chunk %#x.\n", section->tag);
break;
}
@ -2034,7 +2127,7 @@ void free_shader_desc(struct vkd3d_shader_desc *desc)
vkd3d_shader_free_shader_signature(&desc->patch_constant_signature);
}
static int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length,
static int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_message_context *message_context, const char *source_name, struct vkd3d_shader_desc *desc)
{
int ret;
@ -2045,7 +2138,7 @@ static int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length,
memset(&desc->output_signature, 0, sizeof(desc->output_signature));
memset(&desc->patch_constant_signature, 0, sizeof(desc->patch_constant_signature));
ret = parse_dxbc(dxbc, dxbc_length, message_context, source_name, shdr_handler, desc);
ret = for_each_dxbc_section(dxbc, message_context, source_name, shdr_handler, desc);
if (!desc->byte_code)
ret = VKD3D_ERROR_INVALID_ARGUMENT;
@ -2061,7 +2154,9 @@ static int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length,
int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser)
{
struct vkd3d_shader_instruction_array *instructions;
struct vkd3d_shader_desc *shader_desc;
struct vkd3d_shader_instruction *ins;
struct vkd3d_shader_sm4_parser *sm4;
int ret;
@ -2072,7 +2167,7 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
}
shader_desc = &sm4->p.shader_desc;
if ((ret = shader_extract_from_dxbc(compile_info->source.code, compile_info->source.size,
if ((ret = shader_extract_from_dxbc(&compile_info->source,
message_context, compile_info->source_name, shader_desc)) < 0)
{
WARN("Failed to extract shader, vkd3d result %d.\n", ret);
@ -2089,6 +2184,28 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
return VKD3D_ERROR_INVALID_ARGUMENT;
}
instructions = &sm4->p.instructions;
while (!shader_sm4_is_end(&sm4->p))
{
if (!shader_instruction_array_reserve(instructions, instructions->count + 1))
{
ERR("Failed to allocate instructions.\n");
vkd3d_shader_parser_error(&sm4->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory.");
shader_sm4_destroy(&sm4->p);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
ins = &instructions->elements[instructions->count];
shader_sm4_read_instruction(&sm4->p, ins);
if (ins->handler_idx == VKD3DSIH_INVALID)
{
WARN("Encountered unrecognized or invalid instruction.\n");
shader_sm4_destroy(&sm4->p);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
++instructions->count;
}
*parser = &sm4->p;
return VKD3D_OK;
@ -2444,21 +2561,21 @@ static int shader_parse_static_samplers(struct root_signature_parser_context *co
return VKD3D_OK;
}
static int shader_parse_root_signature(const char *data, unsigned int data_size,
static int shader_parse_root_signature(const struct vkd3d_shader_code *data,
struct vkd3d_shader_versioned_root_signature_desc *desc)
{
struct vkd3d_shader_root_signature_desc *v_1_0 = &desc->u.v_1_0;
struct root_signature_parser_context context;
unsigned int count, offset, version;
const char *ptr = data;
const char *ptr = data->code;
int ret;
context.data = data;
context.data_size = data_size;
context.data = data->code;
context.data_size = data->size;
if (!require_space(0, 6, sizeof(DWORD), data_size))
if (!require_space(0, 6, sizeof(uint32_t), data->size))
{
WARN("Invalid data size %#x.\n", data_size);
WARN("Invalid data size %#zx.\n", data->size);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
@ -2527,14 +2644,15 @@ static int shader_parse_root_signature(const char *data, unsigned int data_size,
return VKD3D_OK;
}
static int rts0_handler(const char *data, DWORD data_size, DWORD tag, void *context)
static int rts0_handler(const struct vkd3d_shader_dxbc_section_desc *section,
struct vkd3d_shader_message_context *message_context, void *context)
{
struct vkd3d_shader_versioned_root_signature_desc *desc = context;
if (tag != TAG_RTS0)
if (section->tag != TAG_RTS0)
return VKD3D_OK;
return shader_parse_root_signature(data, data_size, desc);
return shader_parse_root_signature(&section->data, desc);
}
int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
@ -2550,7 +2668,7 @@ int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
*messages = NULL;
vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO);
ret = parse_dxbc(dxbc->code, dxbc->size, &message_context, NULL, rts0_handler, root_signature);
ret = for_each_dxbc_section(dxbc, &message_context, NULL, rts0_handler, root_signature);
vkd3d_shader_message_context_trace_messages(&message_context);
if (!vkd3d_shader_message_context_copy_messages(&message_context, messages))
ret = VKD3D_ERROR_OUT_OF_MEMORY;

View file

@ -22,7 +22,7 @@ struct vkd3d_glsl_generator
{
struct vkd3d_shader_version version;
struct vkd3d_string_buffer buffer;
const struct vkd3d_shader_location *location;
struct vkd3d_shader_location location;
struct vkd3d_shader_message_context *message_context;
bool failed;
};
@ -38,7 +38,7 @@ struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shad
memset(generator, 0, sizeof(*generator));
generator->version = *version;
vkd3d_string_buffer_init(&generator->buffer);
generator->location = location;
generator->location = *location;
generator->message_context = message_context;
return generator;
}
@ -50,7 +50,7 @@ static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error(
va_list args;
va_start(args, fmt);
vkd3d_shader_verror(generator->message_context, generator->location, error, fmt, args);
vkd3d_shader_verror(generator->message_context, &generator->location, error, fmt, args);
va_end(args);
generator->failed = true;
}
@ -93,28 +93,20 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator
int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator,
struct vkd3d_shader_parser *parser, struct vkd3d_shader_code *out)
{
unsigned int i;
void *code;
struct vkd3d_shader_instruction ins;
vkd3d_string_buffer_printf(&generator->buffer, "#version 440\n\n");
vkd3d_string_buffer_printf(&generator->buffer, "void main()\n{\n");
while (!vkd3d_shader_parser_is_end(parser))
generator->location.column = 0;
for (i = 0; i < parser->instructions.count; ++i)
{
vkd3d_shader_parser_read_instruction(parser, &ins);
if (ins.handler_idx == VKD3DSIH_INVALID)
{
vkd3d_glsl_compiler_error(generator,
VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Encountered unrecognized or invalid instruction.");
break;
}
vkd3d_glsl_handle_instruction(generator, &ins);
generator->location.line = i + 1;
vkd3d_glsl_handle_instruction(generator, &parser->instructions.elements[i]);
}
if (parser->failed || generator->failed)
if (generator->failed)
return VKD3D_ERROR_INVALID_SHADER;
vkd3d_string_buffer_printf(&generator->buffer, "}\n");

File diff suppressed because it is too large Load diff

View file

@ -63,6 +63,14 @@
| ((HLSL_SWIZZLE_ ## z) << 4) \
| ((HLSL_SWIZZLE_ ## w) << 6))
#define HLSL_SWIZZLE_MASK (0x3u)
#define HLSL_SWIZZLE_SHIFT(idx) (2u * (idx))
static inline unsigned int hlsl_swizzle_get_component(unsigned int swizzle, unsigned int idx)
{
return (swizzle >> HLSL_SWIZZLE_SHIFT(idx)) & HLSL_SWIZZLE_MASK;
}
enum hlsl_type_class
{
HLSL_CLASS_SCALAR,
@ -108,69 +116,141 @@ enum hlsl_sampler_dim
HLSL_SAMPLER_DIM_MAX = HLSL_SAMPLER_DIM_CUBEARRAY,
};
enum hlsl_matrix_majority
enum hlsl_regset
{
HLSL_COLUMN_MAJOR,
HLSL_ROW_MAJOR
HLSL_REGSET_SAMPLERS,
HLSL_REGSET_TEXTURES,
HLSL_REGSET_UAVS,
HLSL_REGSET_LAST_OBJECT = HLSL_REGSET_UAVS,
HLSL_REGSET_NUMERIC,
HLSL_REGSET_LAST = HLSL_REGSET_NUMERIC,
};
/* An HLSL source-level data type, including anonymous structs and typedefs. */
struct hlsl_type
{
/* Item entry in hlsl_ctx->types. */
struct list entry;
/* Item entry in hlsl_scope->types. hlsl_type->name is used as key (if not NULL). */
struct rb_entry scope_entry;
enum hlsl_type_class type;
/* If type is <= HLSL_CLASS_LAST_NUMERIC, then base_type is <= HLSL_TYPE_LAST_SCALAR.
* If type is HLSL_CLASS_OBJECT, then base_type is > HLSL_TYPE_LAST_SCALAR.
* Otherwise, base_type is not used. */
enum hlsl_base_type base_type;
/* If base_type is HLSL_TYPE_SAMPLER, then sampler_dim is <= HLSL_SAMPLER_DIM_LAST_SAMPLER.
* If base_type is HLSL_TYPE_TEXTURE, then sampler_dim can have any value of the enum.
* If base_type is HLSL_TYPE_UAV, them sampler_dim must be one of HLSL_SAMPLER_DIM_1D,
* HLSL_SAMPLER_DIM_2D, HLSL_SAMPLER_DIM_3D, HLSL_SAMPLER_DIM_1DARRAY, or HLSL_SAMPLER_DIM_2DARRAY.
* Otherwise, sampler_dim is not used */
enum hlsl_sampler_dim sampler_dim;
/* Name, in case the type is a named struct or a typedef. */
const char *name;
/* Bitfield for storing type modifiers, subset of HLSL_TYPE_MODIFIERS_MASK.
* Modifiers that don't fall inside this mask are to be stored in the variable in
* hlsl_ir_var.modifiers, or in the struct field in hlsl_ir_field.modifiers. */
unsigned int modifiers;
/* Size of the type values on each dimension. For non-numeric types, they are set for the
* convenience of the sm1/sm4 backends.
* If type is HLSL_CLASS_SCALAR, then both dimx = 1 and dimy = 1.
* If type is HLSL_CLASS_VECTOR, then dimx is the size of the vector, and dimy = 1.
* If type is HLSL_CLASS_MATRIX, then dimx is the number of columns, and dimy the number of rows.
* If type is HLSL_CLASS_ARRAY, then dimx and dimy have the same value as in the type of the array elements.
* If type is HLSL_CLASS_STRUCT, then dimx is the sum of (dimx * dimy) of every component, and dimy = 1.
* If type is HLSL_CLASS_OBJECT, dimx and dimy depend on the base_type:
* If base_type is HLSL_TYPE_SAMPLER, then both dimx = 1 and dimy = 1.
* If base_type is HLSL_TYPE_TEXTURE, then dimx = 4 and dimy = 1.
* If base_type is HLSL_TYPE_UAV, then dimx is the dimx of e.resource_format, and dimy = 1.
* Otherwise both dimx = 1 and dimy = 1. */
unsigned int dimx;
unsigned int dimy;
/* Sample count for HLSL_SAMPLER_DIM_2DMS or HLSL_SAMPLER_DIM_2DMSARRAY. */
unsigned int sample_count;
union
{
/* Additional information if type is HLSL_CLASS_STRUCT. */
struct
{
struct hlsl_struct_field *fields;
size_t field_count;
} record;
/* Additional information if type is HLSL_CLASS_ARRAY. */
struct
{
struct hlsl_type *type;
/* Array length, or HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT if it is not known yet at parse time. */
unsigned int elements_count;
} array;
/* Format of the data contained within the type if the base_type is HLSL_TYPE_TEXTURE or
* HLSL_TYPE_UAV. */
struct hlsl_type *resource_format;
} e;
unsigned int reg_size;
/* Number of numeric register components used by one value of this type, for each regset.
* For HLSL_REGSET_NUMERIC, 4 components make 1 register, while for other regsets 1 component makes
* 1 register.
* If type is HLSL_CLASS_STRUCT or HLSL_CLASS_ARRAY, the reg_size of their elements and padding
* (which varies according to the backend) is also included. */
unsigned int reg_size[HLSL_REGSET_LAST + 1];
/* Offset where the type's description starts in the output bytecode, in bytes. */
size_t bytecode_offset;
uint32_t is_minimum_precision : 1;
};
/* In HLSL, a semantic is a string linked to a variable (or a field) to be recognized across
* different shader stages in the graphics pipeline. */
struct hlsl_semantic
{
const char *name;
uint32_t index;
};
/* A field within a struct type declaration, used in hlsl_type.e.fields. */
struct hlsl_struct_field
{
struct vkd3d_shader_location loc;
struct hlsl_type *type;
const char *name;
struct hlsl_semantic semantic;
unsigned int modifiers;
unsigned int reg_offset;
/* Bitfield for storing modifiers that are not in HLSL_TYPE_MODIFIERS_MASK (these are stored in
* type->modifiers instead) and that also are specific to the field and not the whole variable.
* In particular, interpolation modifiers. */
unsigned int storage_modifiers;
/* Offset of the field within the type it belongs to, in register components, for each regset. */
unsigned int reg_offset[HLSL_REGSET_LAST + 1];
/* Offset where the field name starts in the output bytecode, in bytes. */
size_t name_bytecode_offset;
};
/* Information of the register allocated for an instruction node or variable.
* These values are initialized at the end of hlsl_emit_bytecode(), after the compilation passes,
* just before writing the bytecode.
* For numeric registers, a writemask can be provided to indicate the reservation of only some of the
* 4 components.
* The type of register (register class) is implied from its use, so it is not stored in this
* struct. */
struct hlsl_reg
{
uint32_t id;
unsigned int writemask;
/* Whether the register has been allocated. */
bool allocated;
};
/* Types of instruction nodes for the IR.
* Each type of instruction node is associated to a struct with the same name in lower case.
* e.g. for HLSL_IR_CONSTANT there exists struct hlsl_ir_constant.
* Each one of these structs start with a struct hlsl_ir_node field, so pointers to values of these
* types can be casted seamlessly to (struct hlsl_ir_node *) and vice-versa. */
enum hlsl_ir_node_type
{
HLSL_IR_CALL,
HLSL_IR_CONSTANT,
HLSL_IR_EXPR,
HLSL_IR_IF,
@ -183,12 +263,22 @@ enum hlsl_ir_node_type
HLSL_IR_SWIZZLE,
};
/* Common data for every type of IR instruction node. */
struct hlsl_ir_node
{
/* Item entry for storing the instruction in a list of instructions. */
struct list entry;
/* Type of node, which means that a pointer to this struct hlsl_ir_node can be casted to a
* pointer to the struct with the same name. */
enum hlsl_ir_node_type type;
/* HLSL data type of the node, when used by other nodes as a source (through an hlsl_src).
* HLSL_IR_CONSTANT, HLSL_IR_EXPR, HLSL_IR_LOAD, HLSL_IR_RESOURCE_LOAD, and HLSL_IR_SWIZZLE
* have a data type and can be used through an hlsl_src; other types of node don't. */
struct hlsl_type *data_type;
/* List containing all the struct hlsl_src·s that point to this node; linked by the
* hlsl_src.entry fields. */
struct list uses;
struct vkd3d_shader_location loc;
@ -198,17 +288,26 @@ struct hlsl_ir_node
* true even for loops, since currently we can't have a reference to a
* value generated in an earlier iteration of the loop. */
unsigned int index, last_read;
/* Temp. register allocated to store the result of this instruction (if any). */
struct hlsl_reg reg;
};
struct hlsl_block
{
/* List containing instruction nodes; linked by the hlsl_ir_node.entry fields. */
struct list instrs;
};
/* A reference to an instruction node (struct hlsl_ir_node), usable as a field in other structs.
* struct hlsl_src is more powerful than a mere pointer to an hlsl_ir_node because it also
* contains a linked list item entry, which is used by the referenced instruction node to keep
* track of all the hlsl_src·s that reference it.
* This allows replacing any hlsl_ir_node with any other in all the places it is used, or checking
* that a node has no uses before it is removed. */
struct hlsl_src
{
struct hlsl_ir_node *node;
/* Item entry for node->uses. */
struct list entry;
};
@ -228,14 +327,14 @@ struct hlsl_attribute
#define HLSL_STORAGE_GROUPSHARED 0x00000010
#define HLSL_STORAGE_STATIC 0x00000020
#define HLSL_STORAGE_UNIFORM 0x00000040
#define HLSL_STORAGE_VOLATILE 0x00000080
#define HLSL_MODIFIER_VOLATILE 0x00000080
#define HLSL_MODIFIER_CONST 0x00000100
#define HLSL_MODIFIER_ROW_MAJOR 0x00000200
#define HLSL_MODIFIER_COLUMN_MAJOR 0x00000400
#define HLSL_STORAGE_IN 0x00000800
#define HLSL_STORAGE_OUT 0x00001000
#define HLSL_TYPE_MODIFIERS_MASK (HLSL_MODIFIER_PRECISE | HLSL_STORAGE_VOLATILE | \
#define HLSL_TYPE_MODIFIERS_MASK (HLSL_MODIFIER_PRECISE | HLSL_MODIFIER_VOLATILE | \
HLSL_MODIFIER_CONST | HLSL_MODIFIER_ROW_MAJOR | \
HLSL_MODIFIER_COLUMN_MAJOR)
@ -243,6 +342,8 @@ struct hlsl_attribute
#define HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT 0
/* Reservation of a specific register to a variable, field, or buffer, written in the HLSL source
* using the register(·) syntax */
struct hlsl_reg_reservation
{
char type;
@ -255,14 +356,33 @@ struct hlsl_ir_var
struct vkd3d_shader_location loc;
const char *name;
struct hlsl_semantic semantic;
/* Buffer where the variable's value is stored, in case it is uniform. */
struct hlsl_buffer *buffer;
unsigned int modifiers;
/* Bitfield for storage modifiers (type modifiers are stored in data_type->modifiers). */
unsigned int storage_modifiers;
/* Optional register to be used as a starting point for the variable allocation, specified
* by the user via the register(·) syntax. */
struct hlsl_reg_reservation reg_reservation;
struct list scope_entry, param_entry, extern_entry;
/* Item entry in hlsl_scope.vars. Specifically hlsl_ctx.globals.vars if the variable is global. */
struct list scope_entry;
/* Item entry in hlsl_ctx.extern_vars, if the variable is extern. */
struct list extern_entry;
/* Indexes of the IR instructions where the variable is first written and last read (liveness
* range). The IR instructions are numerated starting from 2, because 0 means unused, and 1
* means function entry. */
unsigned int first_write, last_read;
/* Offset where the variable's value is stored within its buffer in numeric register components.
* This in case the variable is uniform. */
unsigned int buffer_offset;
struct hlsl_reg reg;
/* Register to which the variable is allocated during its lifetime, for each register set.
* In case that the variable spans multiple registers in one regset, this is set to the
* start of the register range.
* Builtin semantics don't use the field.
* In SM4, uniforms don't use the field because they are located using the buffer's hlsl_reg
* and the buffer_offset instead. */
struct hlsl_reg regs[HLSL_REGSET_LAST + 1];
uint32_t is_input_semantic : 1;
uint32_t is_output_semantic : 1;
@ -270,26 +390,56 @@ struct hlsl_ir_var
uint32_t is_param : 1;
};
/* Sized array of variables representing a function's parameters. */
struct hlsl_func_parameters
{
struct hlsl_ir_var **vars;
size_t count, capacity;
};
struct hlsl_ir_function
{
/* Item entry in hlsl_ctx.functions */
struct rb_entry entry;
const char *name;
/* Tree containing function definitions, stored as hlsl_ir_function_decl structures, which would
* be more than one in case of function overloading. */
struct rb_tree overloads;
bool intrinsic;
};
struct hlsl_ir_function_decl
{
struct hlsl_type *return_type;
/* Synthetic variable used to store the return value of the function. */
struct hlsl_ir_var *return_var;
struct vkd3d_shader_location loc;
/* Item entry in hlsl_ir_function.overloads. The parameters' types are used as key. */
struct rb_entry entry;
/* Function to which this declaration corresponds. */
struct hlsl_ir_function *func;
struct list *parameters;
struct hlsl_func_parameters parameters;
struct hlsl_block body;
bool has_body;
/* Array of attributes (like numthreads) specified just before the function declaration.
* Not to be confused with the function parameters! */
unsigned int attr_count;
const struct hlsl_attribute *const *attrs;
/* Synthetic boolean variable marking whether a return statement has been
* executed. Needed to deal with return statements in non-uniform control
* flow, since some backends can't handle them. */
struct hlsl_ir_var *early_return_var;
};
struct hlsl_ir_call
{
struct hlsl_ir_node node;
struct hlsl_ir_function_decl *decl;
};
struct hlsl_ir_if
@ -310,6 +460,8 @@ struct hlsl_ir_loop
enum hlsl_ir_expr_op
{
HLSL_OP0_VOID,
HLSL_OP1_ABS,
HLSL_OP1_BIT_NOT,
HLSL_OP1_CAST,
@ -354,6 +506,7 @@ enum hlsl_ir_expr_op
HLSL_OP2_NEQUAL,
HLSL_OP2_RSHIFT,
HLSL_OP3_DP2ADD,
HLSL_OP3_LERP,
};
@ -387,14 +540,28 @@ struct hlsl_ir_swizzle
DWORD swizzle;
};
/* Reference to a variable, or a part of it (e.g. a vector within a matrix within a struct). */
struct hlsl_deref
{
struct hlsl_ir_var *var;
/* An array of references to instruction nodes, of data type uint, that are used to reach the
* desired part of the variable.
* If path_len is 0, then this is a reference to the whole variable.
* The value of each instruction node in the path corresponds to the index of the element/field
* that has to be selected on each nesting level to reach this part.
* The path shall not contain additional values once a type that cannot be subdivided
* (a.k.a. "component") is reached. */
unsigned int path_len;
struct hlsl_src *path;
/* Single instruction node of data type uint used to represent the register offset (in register
* components, within the pertaining regset), from the start of the variable, of the part
* referenced.
* The path is lowered to this single offset -- whose value may vary between SM1 and SM4 --
* before writing the bytecode. */
struct hlsl_src offset;
enum hlsl_regset offset_regset;
};
struct hlsl_ir_load
@ -447,14 +614,21 @@ struct hlsl_ir_constant
float f;
double d;
} value[4];
/* Constant register of type 'c' where the constant value is stored for SM1. */
struct hlsl_reg reg;
};
struct hlsl_scope
{
/* Item entry for hlsl_ctx.scopes. */
struct list entry;
/* List containing the variables declared in this scope; linked by hlsl_ir_var->scope_entry. */
struct list vars;
/* Tree map containing the types declared in this scope, using hlsl_tree.name as key.
* The types are attached through the hlsl_type.scope_entry fields. */
struct rb_tree types;
/* Scope containing this scope. This value is NULL for the global scope. */
struct hlsl_scope *upper;
};
@ -480,15 +654,25 @@ enum hlsl_buffer_type
HLSL_BUFFER_TEXTURE,
};
/* In SM4, uniform variables are organized in different buffers. Besides buffers defined in the
* source code, there is also the implicit $Globals buffer and the implicit $Params buffer,
* to which uniform globals and parameters belong by default. */
struct hlsl_buffer
{
struct vkd3d_shader_location loc;
enum hlsl_buffer_type type;
const char *name;
/* Register reserved for this buffer, if any.
* If provided, it should be of type 'b' if type is HLSL_BUFFER_CONSTANT and 't' if type is
* HLSL_BUFFER_TEXTURE. */
struct hlsl_reg_reservation reservation;
/* Item entry for hlsl_ctx.buffers */
struct list entry;
/* The size of the buffer (in register components), and the size of the buffer as determined
* by its last variable that's actually used. */
unsigned size, used_size;
/* Register of type 'b' on which the buffer is allocated. */
struct hlsl_reg reg;
};
@ -498,48 +682,90 @@ struct hlsl_ctx
const char **source_files;
unsigned int source_files_count;
/* Current location being read in the HLSL source, updated while parsing. */
struct vkd3d_shader_location location;
/* Stores the logging messages and logging configuration. */
struct vkd3d_shader_message_context *message_context;
/* Cache for temporary string allocations. */
struct vkd3d_string_buffer_cache string_buffers;
/* A value from enum vkd3d_result with the current success/failure result of the whole
* compilation.
* It is initialized to VKD3D_OK and set to an error code in case a call to hlsl_fixme() or
* hlsl_error() is triggered, or in case of a memory allocation error.
* The value of this field is checked between compilation stages to stop execution in case of
* failure. */
int result;
/* Pointer to an opaque data structure managed by FLEX (during lexing), that encapsulates the
* current state of the scanner. This pointer is required by all FLEX API functions when the
* scanner is declared as reentrant, which is the case. */
void *scanner;
/* Pointer to the current scope; changes as the parser reads the code. */
struct hlsl_scope *cur_scope;
/* Scope of global variables. */
struct hlsl_scope *globals;
/* Dummy scope for variables which should never be looked up by name. */
struct hlsl_scope *dummy_scope;
/* List of all the scopes in the program; linked by the hlsl_scope.entry fields. */
struct list scopes;
/* List of all the extern variables; linked by the hlsl_ir_var.extern_entry fields.
* This exists as a convenience because it is often necessary to iterate all extern variables
* and these can be declared in global scope, as function parameters, or as the function
* return value. */
struct list extern_vars;
/* List containing both the built-in HLSL buffers ($Globals and $Params) and the ones declared
* in the shader; linked by the hlsl_buffer.entry fields. */
struct list buffers;
/* Current buffer (changes as the parser reads the code), $Globals buffer, and $Params buffer,
* respectively. */
struct hlsl_buffer *cur_buffer, *globals_buffer, *params_buffer;
/* List containing all created hlsl_types, except builtin_types; linked by the hlsl_type.entry
* fields. */
struct list types;
/* Tree map for the declared functions, using hlsl_ir_function.name as key.
* The functions are attached through the hlsl_ir_function.entry fields. */
struct rb_tree functions;
/* Pointer to the current function; changes as the parser reads the code. */
const struct hlsl_ir_function_decl *cur_function;
enum hlsl_matrix_majority matrix_majority;
/* Default matrix majority for matrix types. Can be set by a pragma within the HLSL source. */
unsigned int matrix_majority;
/* Basic data types stored for convenience. */
struct
{
struct hlsl_type *scalar[HLSL_TYPE_LAST_SCALAR + 1];
struct hlsl_type *vector[HLSL_TYPE_LAST_SCALAR + 1][4];
/* matrix[float][2][4] is a float4x2, i.e. dimx = 2, dimy = 4 */
/* matrix[HLSL_TYPE_FLOAT][1][3] is a float4x2, i.e. dimx = 2, dimy = 4 */
struct hlsl_type *matrix[HLSL_TYPE_LAST_SCALAR + 1][4][4];
struct hlsl_type *sampler[HLSL_SAMPLER_DIM_LAST_SAMPLER + 1];
struct hlsl_type *Void;
} builtin_types;
/* List of the instruction nodes for initializing static variables; linked by the
* hlsl_ir_node.entry fields. */
struct list static_initializers;
/* Dynamic array of constant values that appear in the shader, associated to the 'c' registers.
* Only used for SM1 profiles. */
struct hlsl_constant_defs
{
struct hlsl_vec4 *values;
size_t count, size;
} constant_defs;
/* Number of temp. registers required for the shader to run, i.e. the largest temp register
* index that will be used in the output bytecode (+1). */
uint32_t temp_count;
/* Number of threads to be executed (on the X, Y, and Z dimensions) in a single thread group in
* compute shader profiles. It is set using the numthreads() attribute in the entry point. */
uint32_t thread_count[3];
/* Whether the parser is inside a state block (effects' metadata) inside a variable declaration. */
uint32_t in_state_block : 1;
/* Whether the numthreads() attribute has been provided in the entry-point function. */
uint32_t found_numthreads : 1;
};
@ -558,6 +784,12 @@ struct hlsl_resource_load_params
struct hlsl_ir_node *coords, *lod, *texel_offset;
};
static inline struct hlsl_ir_call *hlsl_ir_call(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_CALL);
return CONTAINING_RECORD(node, struct hlsl_ir_call, node);
}
static inline struct hlsl_ir_constant *hlsl_ir_constant(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_CONSTANT);
@ -742,16 +974,22 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru
struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, unsigned int modifiers);
const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type);
void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function_decl *decl, bool intrinsic);
struct hlsl_ir_load *hlsl_add_conditional(struct hlsl_ctx *ctx, struct list *instrs,
struct hlsl_ir_node *condition, struct hlsl_ir_node *if_true, struct hlsl_ir_node *if_false);
void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function_decl *decl);
bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var);
bool hlsl_clone_block(struct hlsl_ctx *ctx, struct hlsl_block *dst_block, const struct hlsl_block *src_block);
void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func);
int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func,
enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out);
bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struct hlsl_deref *other);
void hlsl_cleanup_deref(struct hlsl_deref *deref);
void hlsl_cleanup_semantic(struct hlsl_semantic *semantic);
void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new);
@ -761,20 +999,24 @@ void hlsl_free_instr_list(struct list *list);
void hlsl_free_type(struct hlsl_type *type);
void hlsl_free_var(struct hlsl_ir_var *decl);
bool hlsl_get_function(struct hlsl_ctx *ctx, const char *name);
struct hlsl_ir_function *hlsl_get_function(struct hlsl_ctx *ctx, const char *name);
struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const char *name);
struct hlsl_type *hlsl_get_type(struct hlsl_scope *scope, const char *name, bool recursive);
struct hlsl_type *hlsl_get_type(struct hlsl_scope *scope, const char *name, bool recursive, bool case_insensitive);
struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name);
struct hlsl_type *hlsl_get_element_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type,
struct hlsl_ir_node *idx);
const char *hlsl_jump_type_to_string(enum hlsl_ir_jump_type type);
struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, unsigned int array_size);
struct hlsl_ir_node *hlsl_new_binary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1,
struct hlsl_ir_node *arg2);
struct hlsl_ir_constant *hlsl_new_bool_constant(struct hlsl_ctx *ctx, bool b, const struct vkd3d_shader_location *loc);
struct hlsl_buffer *hlsl_new_buffer(struct hlsl_ctx *ctx, enum hlsl_buffer_type type, const char *name,
const struct hlsl_reg_reservation *reservation, struct vkd3d_shader_location loc);
struct hlsl_ir_node *hlsl_new_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *decl,
const struct vkd3d_shader_location *loc);
struct hlsl_ir_expr *hlsl_new_cast(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_type *type,
const struct vkd3d_shader_location *loc);
struct hlsl_ir_constant *hlsl_new_constant(struct hlsl_ctx *ctx, struct hlsl_type *type,
@ -785,8 +1027,9 @@ struct hlsl_ir_node *hlsl_new_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op
struct hlsl_type *data_type, const struct vkd3d_shader_location *loc);
struct hlsl_ir_constant *hlsl_new_float_constant(struct hlsl_ctx *ctx,
float f, const struct vkd3d_shader_location *loc);
struct hlsl_ir_function_decl *hlsl_new_func_decl(struct hlsl_ctx *ctx, struct hlsl_type *return_type,
struct list *parameters, const struct hlsl_semantic *semantic, const struct vkd3d_shader_location *loc);
struct hlsl_ir_function_decl *hlsl_new_func_decl(struct hlsl_ctx *ctx,
struct hlsl_type *return_type, const struct hlsl_func_parameters *parameters,
const struct hlsl_semantic *semantic, const struct vkd3d_shader_location *loc);
struct hlsl_ir_if *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *condition, struct vkd3d_shader_location loc);
struct hlsl_ir_constant *hlsl_new_int_constant(struct hlsl_ctx *ctx, int n,
const struct vkd3d_shader_location *loc);
@ -818,7 +1061,8 @@ struct hlsl_ir_swizzle *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned
struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc);
struct hlsl_ir_var *hlsl_new_synthetic_var(struct hlsl_ctx *ctx, const char *template,
struct hlsl_type *type, const struct vkd3d_shader_location *loc);
struct hlsl_type *hlsl_new_texture_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format);
struct hlsl_type *hlsl_new_texture_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format,
unsigned int sample_count);
struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format);
struct hlsl_ir_constant *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n,
const struct vkd3d_shader_location *loc);
@ -845,13 +1089,15 @@ bool hlsl_scope_add_type(struct hlsl_scope *scope, struct hlsl_type *type);
struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old,
unsigned int default_majority, unsigned int modifiers);
unsigned int hlsl_type_component_count(const struct hlsl_type *type);
unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type);
unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type, enum hlsl_regset regset);
struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type,
unsigned int index);
bool hlsl_type_is_row_major(const struct hlsl_type *type);
unsigned int hlsl_type_minor_size(const struct hlsl_type *type);
unsigned int hlsl_type_major_size(const struct hlsl_type *type);
unsigned int hlsl_type_element_count(const struct hlsl_type *type);
bool hlsl_type_is_resource(const struct hlsl_type *type);
enum hlsl_regset hlsl_type_get_regset(const struct hlsl_type *type);
unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset);
bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2);

View file

@ -181,7 +181,7 @@ row_major {return KW_ROW_MAJOR; }
yylval->name = hlsl_strdup(ctx, yytext);
if (hlsl_get_var(ctx->cur_scope, yytext) || hlsl_get_function(ctx, yytext))
return VAR_IDENTIFIER;
else if (hlsl_get_type(ctx->cur_scope, yytext, true))
else if (hlsl_get_type(ctx->cur_scope, yytext, true, true))
return TYPE_IDENTIFIER;
else
return NEW_IDENTIFIER;
@ -233,14 +233,14 @@ row_major {return KW_ROW_MAJOR; }
struct hlsl_ctx *ctx = yyget_extra(yyscanner);
TRACE("#pragma setting row_major mode.\n");
ctx->matrix_majority = HLSL_ROW_MAJOR;
ctx->matrix_majority = HLSL_MODIFIER_ROW_MAJOR;
BEGIN(pp_ignore);
}
<pp_pragma>pack_matrix{WS}*\({WS}*column_major{WS}*\) {
struct hlsl_ctx *ctx = yyget_extra(yyscanner);
TRACE("#pragma setting column_major mode.\n");
ctx->matrix_majority = HLSL_COLUMN_MAJOR;
ctx->matrix_majority = HLSL_MODIFIER_COLUMN_MAJOR;
BEGIN(pp_ignore);
}
<pp_pragma>{NEWLINE} {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -509,6 +509,8 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
if (instr->type != HLSL_IR_EXPR)
return false;
expr = hlsl_ir_expr(instr);
if (!expr->operands[0].node)
return false;
if (instr->data_type->type > HLSL_CLASS_VECTOR)
return false;
@ -601,7 +603,7 @@ bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst
{
struct hlsl_ir_constant *value, *res;
struct hlsl_ir_swizzle *swizzle;
unsigned int i, swizzle_bits;
unsigned int i;
if (instr->type != HLSL_IR_SWIZZLE)
return false;
@ -613,12 +615,8 @@ bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst
if (!(res = hlsl_new_constant(ctx, instr->data_type, &instr->loc)))
return false;
swizzle_bits = swizzle->swizzle;
for (i = 0; i < swizzle->node.data_type->dimx; ++i)
{
res->value[i] = value->value[swizzle_bits & 3];
swizzle_bits >>= 2;
}
res->value[i] = value->value[hlsl_swizzle_get_component(swizzle->swizzle, i)];
list_add_before(&swizzle->node.entry, &res->node.entry);
hlsl_replace_node(&swizzle->node, &res->node);

View file

@ -315,7 +315,9 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (!var->semantic.name && var->reg.allocated)
enum hlsl_regset regset = hlsl_type_get_regset(var->data_type);
if (!var->semantic.name && var->regs[regset].allocated)
{
++uniform_count;
@ -353,20 +355,24 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (!var->semantic.name && var->reg.allocated)
enum hlsl_regset regset = hlsl_type_get_regset(var->data_type);
if (!var->semantic.name && var->regs[regset].allocated)
{
put_u32(buffer, 0); /* name */
if (var->data_type->type == HLSL_CLASS_OBJECT
&& (var->data_type->base_type == HLSL_TYPE_SAMPLER
|| var->data_type->base_type == HLSL_TYPE_TEXTURE))
{
put_u32(buffer, vkd3d_make_u32(D3DXRS_SAMPLER, var->reg.id));
assert(regset == HLSL_REGSET_SAMPLERS);
put_u32(buffer, vkd3d_make_u32(D3DXRS_SAMPLER, var->regs[regset].id));
put_u32(buffer, 1);
}
else
{
put_u32(buffer, vkd3d_make_u32(D3DXRS_FLOAT4, var->reg.id));
put_u32(buffer, var->data_type->reg_size / 4);
assert(regset == HLSL_REGSET_NUMERIC);
put_u32(buffer, vkd3d_make_u32(D3DXRS_FLOAT4, var->regs[regset].id));
put_u32(buffer, var->data_type->reg_size[regset] / 4);
}
put_u32(buffer, 0); /* type */
put_u32(buffer, 0); /* FIXME: default value */
@ -377,7 +383,9 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (!var->semantic.name && var->reg.allocated)
enum hlsl_regset regset = hlsl_type_get_regset(var->data_type);
if (!var->semantic.name && var->regs[regset].allocated)
{
size_t var_offset = vars_start + (uniform_count * 5 * sizeof(uint32_t));
size_t name_offset;
@ -422,7 +430,7 @@ struct sm1_instruction
D3DSHADER_PARAM_SRCMOD_TYPE mod;
unsigned int swizzle;
uint32_t reg;
} srcs[2];
} srcs[3];
unsigned int src_count;
unsigned int has_dst;
@ -435,11 +443,9 @@ static void write_sm1_dst_register(struct vkd3d_bytecode_buffer *buffer, const s
}
static void write_sm1_src_register(struct vkd3d_bytecode_buffer *buffer,
const struct sm1_src_register *reg, unsigned int dst_writemask)
const struct sm1_src_register *reg)
{
unsigned int swizzle = hlsl_map_swizzle(reg->swizzle, dst_writemask);
put_u32(buffer, (1u << 31) | sm1_encode_register_type(reg->type) | reg->mod | (swizzle << 16) | reg->reg);
put_u32(buffer, (1u << 31) | sm1_encode_register_type(reg->type) | reg->mod | (reg->swizzle << 16) | reg->reg);
}
static void write_sm1_instruction(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
@ -456,14 +462,47 @@ static void write_sm1_instruction(struct hlsl_ctx *ctx, struct vkd3d_bytecode_bu
write_sm1_dst_register(buffer, &instr->dst);
for (i = 0; i < instr->src_count; ++i)
write_sm1_src_register(buffer, &instr->srcs[i], instr->dst.writemask);
write_sm1_src_register(buffer, &instr->srcs[i]);
};
static void sm1_map_src_swizzle(struct sm1_src_register *src, unsigned int map_writemask)
{
src->swizzle = hlsl_map_swizzle(src->swizzle, map_writemask);
}
static void write_sm1_dp2add(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct hlsl_reg *dst, const struct hlsl_reg *src1, const struct hlsl_reg *src2,
const struct hlsl_reg *src3)
{
struct sm1_instruction instr =
{
.opcode = D3DSIO_DP2ADD,
.dst.type = D3DSPR_TEMP,
.dst.writemask = dst->writemask,
.dst.reg = dst->id,
.has_dst = 1,
.srcs[0].type = D3DSPR_TEMP,
.srcs[0].swizzle = hlsl_swizzle_from_writemask(src1->writemask),
.srcs[0].reg = src1->id,
.srcs[1].type = D3DSPR_TEMP,
.srcs[1].swizzle = hlsl_swizzle_from_writemask(src2->writemask),
.srcs[1].reg = src2->id,
.srcs[2].type = D3DSPR_TEMP,
.srcs[2].swizzle = hlsl_swizzle_from_writemask(src3->writemask),
.srcs[2].reg = src3->id,
.src_count = 3,
};
write_sm1_instruction(ctx, buffer, &instr);
}
static void write_sm1_binary_op(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode, const struct hlsl_reg *dst,
const struct hlsl_reg *src1, const struct hlsl_reg *src2)
{
const struct sm1_instruction instr =
struct sm1_instruction instr =
{
.opcode = opcode,
@ -480,18 +519,47 @@ static void write_sm1_binary_op(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buff
.srcs[1].reg = src2->id,
.src_count = 2,
};
sm1_map_src_swizzle(&instr.srcs[0], instr.dst.writemask);
sm1_map_src_swizzle(&instr.srcs[1], instr.dst.writemask);
write_sm1_instruction(ctx, buffer, &instr);
}
static void write_sm1_binary_op_dot(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode, const struct hlsl_reg *dst,
const struct hlsl_reg *src1, const struct hlsl_reg *src2)
{
struct sm1_instruction instr =
{
.opcode = opcode,
.dst.type = D3DSPR_TEMP,
.dst.writemask = dst->writemask,
.dst.reg = dst->id,
.has_dst = 1,
.srcs[0].type = D3DSPR_TEMP,
.srcs[0].swizzle = hlsl_swizzle_from_writemask(src1->writemask),
.srcs[0].reg = src1->id,
.srcs[1].type = D3DSPR_TEMP,
.srcs[1].swizzle = hlsl_swizzle_from_writemask(src2->writemask),
.srcs[1].reg = src2->id,
.src_count = 2,
};
write_sm1_instruction(ctx, buffer, &instr);
}
static void write_sm1_unary_op(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode, const struct hlsl_reg *dst,
const struct hlsl_reg *src, D3DSHADER_PARAM_SRCMOD_TYPE src_mod)
const struct hlsl_reg *src, D3DSHADER_PARAM_SRCMOD_TYPE src_mod, D3DSHADER_PARAM_DSTMOD_TYPE dst_mod)
{
const struct sm1_instruction instr =
struct sm1_instruction instr =
{
.opcode = opcode,
.dst.type = D3DSPR_TEMP,
.dst.mod = dst_mod,
.dst.writemask = dst->writemask,
.dst.reg = dst->id,
.has_dst = 1,
@ -502,6 +570,8 @@ static void write_sm1_unary_op(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe
.srcs[0].mod = src_mod,
.src_count = 1,
};
sm1_map_src_swizzle(&instr.srcs[0], instr.dst.writemask);
write_sm1_instruction(ctx, buffer, &instr);
}
@ -547,7 +617,7 @@ static void write_sm1_semantic_dcl(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b
ret = hlsl_sm1_usage_from_semantic(&var->semantic, &usage, &usage_idx);
assert(ret);
reg.type = output ? D3DSPR_OUTPUT : D3DSPR_INPUT;
reg.reg = var->reg.id;
reg.reg = var->regs[HLSL_REGSET_NUMERIC].id;
}
token = D3DSIO_DCL;
@ -606,15 +676,33 @@ static void write_sm1_constant(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe
assert(instr->reg.allocated);
assert(constant->reg.allocated);
sm1_map_src_swizzle(&sm1_instr.srcs[0], sm1_instr.dst.writemask);
write_sm1_instruction(ctx, buffer, &sm1_instr);
}
static void write_sm1_per_component_unary_op(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct hlsl_ir_node *instr, D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode)
{
struct hlsl_ir_expr *expr = hlsl_ir_expr(instr);
struct hlsl_ir_node *arg1 = expr->operands[0].node;
unsigned int i;
for (i = 0; i < instr->data_type->dimx; ++i)
{
struct hlsl_reg src = arg1->reg, dst = instr->reg;
src.writemask = hlsl_combine_writemasks(src.writemask, 1u << i);
dst.writemask = hlsl_combine_writemasks(dst.writemask, 1u << i);
write_sm1_unary_op(ctx, buffer, opcode, &dst, &src, 0, 0);
}
}
static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_node *instr)
{
struct hlsl_ir_expr *expr = hlsl_ir_expr(instr);
struct hlsl_ir_node *arg1 = expr->operands[0].node;
struct hlsl_ir_node *arg2 = expr->operands[1].node;
unsigned int i;
struct hlsl_ir_node *arg3 = expr->operands[2].node;
assert(instr->reg.allocated);
@ -627,19 +715,28 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
switch (expr->op)
{
case HLSL_OP1_ABS:
write_sm1_unary_op(ctx, buffer, D3DSIO_ABS, &instr->reg, &arg1->reg, 0, 0);
break;
case HLSL_OP1_EXP2:
write_sm1_per_component_unary_op(ctx, buffer, instr, D3DSIO_EXP);
break;
case HLSL_OP1_NEG:
write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, D3DSPSM_NEG);
write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, D3DSPSM_NEG, 0);
break;
case HLSL_OP1_SAT:
write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, 0, D3DSPDM_SATURATE);
break;
case HLSL_OP1_RCP:
for (i = 0; i < instr->data_type->dimx; ++i)
{
struct hlsl_reg src = arg1->reg, dst = instr->reg;
write_sm1_per_component_unary_op(ctx, buffer, instr, D3DSIO_RCP);
break;
src.writemask = hlsl_combine_writemasks(src.writemask, 1u << i);
dst.writemask = hlsl_combine_writemasks(dst.writemask, 1u << i);
write_sm1_unary_op(ctx, buffer, D3DSIO_RCP, &dst, &src, 0);
}
case HLSL_OP1_RSQ:
write_sm1_per_component_unary_op(ctx, buffer, instr, D3DSIO_RSQ);
break;
case HLSL_OP2_ADD:
@ -658,6 +755,30 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
write_sm1_binary_op(ctx, buffer, D3DSIO_MUL, &instr->reg, &arg1->reg, &arg2->reg);
break;
case HLSL_OP1_FRACT:
write_sm1_unary_op(ctx, buffer, D3DSIO_FRC, &instr->reg, &arg1->reg, D3DSPSM_NONE, 0);
break;
case HLSL_OP2_DOT:
switch (arg1->data_type->dimx)
{
case 4:
write_sm1_binary_op_dot(ctx, buffer, D3DSIO_DP4, &instr->reg, &arg1->reg, &arg2->reg);
break;
case 3:
write_sm1_binary_op_dot(ctx, buffer, D3DSIO_DP3, &instr->reg, &arg1->reg, &arg2->reg);
break;
default:
vkd3d_unreachable();
}
break;
case HLSL_OP3_DP2ADD:
write_sm1_dp2add(ctx, buffer, &instr->reg, &arg1->reg, &arg2->reg, &arg3->reg);
break;
default:
hlsl_fixme(ctx, &instr->loc, "SM1 \"%s\" expression.", debug_hlsl_expr_op(expr->op));
break;
@ -703,6 +824,7 @@ static void write_sm1_load(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
sm1_instr.srcs[0].swizzle = hlsl_swizzle_from_writemask((1 << load->src.var->data_type->dimx) - 1);
}
sm1_map_src_swizzle(&sm1_instr.srcs[0], sm1_instr.dst.writemask);
write_sm1_instruction(ctx, buffer, &sm1_instr);
}
@ -748,6 +870,7 @@ static void write_sm1_store(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *
else
assert(reg.allocated);
sm1_map_src_swizzle(&sm1_instr.srcs[0], sm1_instr.dst.writemask);
write_sm1_instruction(ctx, buffer, &sm1_instr);
}
@ -774,6 +897,7 @@ static void write_sm1_swizzle(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer
assert(instr->reg.allocated);
assert(val->reg.allocated);
sm1_map_src_swizzle(&sm1_instr.srcs[0], sm1_instr.dst.writemask);
write_sm1_instruction(ctx, buffer, &sm1_instr);
}
@ -803,6 +927,9 @@ static void write_sm1_instructions(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b
switch (instr->type)
{
case HLSL_IR_CALL:
vkd3d_unreachable();
case HLSL_IR_CONSTANT:
write_sm1_constant(ctx, buffer, instr);
break;
@ -824,7 +951,7 @@ static void write_sm1_instructions(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b
break;
default:
FIXME("Unhandled instruction type %s.\n", hlsl_node_type_to_string(instr->type));
hlsl_fixme(ctx, &instr->loc, "Instruction type %s.", hlsl_node_type_to_string(instr->type));
}
}
}

View file

@ -49,21 +49,25 @@ bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_sem
const char *semantic;
bool output;
enum vkd3d_shader_type shader_type;
enum vkd3d_sm4_register_type type;
enum vkd3d_sm4_swizzle_type swizzle_type;
enum vkd3d_sm4_register_type type;
bool has_idx;
}
register_table[] =
{
{"sv_primitiveid", false, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SM4_RT_PRIMID, VKD3D_SM4_SWIZZLE_NONE, false},
{"sv_dispatchthreadid", false, VKD3D_SHADER_TYPE_COMPUTE, VKD3D_SM4_SWIZZLE_VEC4, VKD3D_SM5_RT_THREAD_ID, false},
{"sv_groupid", false, VKD3D_SHADER_TYPE_COMPUTE, VKD3D_SM4_SWIZZLE_VEC4, VKD3D_SM5_RT_THREAD_GROUP_ID, false},
{"sv_groupthreadid", false, VKD3D_SHADER_TYPE_COMPUTE, VKD3D_SM4_SWIZZLE_VEC4, VKD3D_SM5_RT_LOCAL_THREAD_ID, false},
{"sv_primitiveid", false, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SM4_SWIZZLE_NONE, VKD3D_SM4_RT_PRIMID, false},
/* Put sv_target in this table, instead of letting it fall through to
* default varying allocation, so that the register index matches the
* usage index. */
{"color", true, VKD3D_SHADER_TYPE_PIXEL, VKD3D_SM4_RT_OUTPUT, VKD3D_SM4_SWIZZLE_VEC4, true},
{"depth", true, VKD3D_SHADER_TYPE_PIXEL, VKD3D_SM4_RT_DEPTHOUT, VKD3D_SM4_SWIZZLE_VEC4, false},
{"sv_depth", true, VKD3D_SHADER_TYPE_PIXEL, VKD3D_SM4_RT_DEPTHOUT, VKD3D_SM4_SWIZZLE_VEC4, false},
{"sv_target", true, VKD3D_SHADER_TYPE_PIXEL, VKD3D_SM4_RT_OUTPUT, VKD3D_SM4_SWIZZLE_VEC4, true},
{"color", true, VKD3D_SHADER_TYPE_PIXEL, VKD3D_SM4_SWIZZLE_VEC4, VKD3D_SM4_RT_OUTPUT, true},
{"depth", true, VKD3D_SHADER_TYPE_PIXEL, VKD3D_SM4_SWIZZLE_VEC4, VKD3D_SM4_RT_DEPTHOUT, false},
{"sv_depth", true, VKD3D_SHADER_TYPE_PIXEL, VKD3D_SM4_SWIZZLE_VEC4, VKD3D_SM4_RT_DEPTHOUT, false},
{"sv_target", true, VKD3D_SHADER_TYPE_PIXEL, VKD3D_SM4_SWIZZLE_VEC4, VKD3D_SM4_RT_OUTPUT, true},
};
for (i = 0; i < ARRAY_SIZE(register_table); ++i)
@ -97,6 +101,10 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant
}
semantics[] =
{
{"sv_dispatchthreadid", false, VKD3D_SHADER_TYPE_COMPUTE, ~0u},
{"sv_groupid", false, VKD3D_SHADER_TYPE_COMPUTE, ~0u},
{"sv_groupthreadid", false, VKD3D_SHADER_TYPE_COMPUTE, ~0u},
{"position", false, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_POSITION},
{"sv_position", false, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_POSITION},
{"sv_primitiveid", false, VKD3D_SHADER_TYPE_GEOMETRY, D3D_NAME_PRIMITIVE_ID},
@ -164,6 +172,8 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc,
ret = hlsl_sm4_usage_from_semantic(ctx, &var->semantic, output, &usage);
assert(ret);
if (usage == ~0u)
continue;
usage_idx = var->semantic.index;
if (hlsl_sm4_register_from_semantic(ctx, &var->semantic, output, &type, NULL, &has_idx))
@ -172,9 +182,9 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc,
}
else
{
assert(var->reg.allocated);
assert(var->regs[HLSL_REGSET_NUMERIC].allocated);
type = VKD3D_SM4_RT_INPUT;
reg_idx = var->reg.id;
reg_idx = var->regs[HLSL_REGSET_NUMERIC].id;
}
use_mask = width; /* FIXME: accurately report use mask */
@ -226,6 +236,8 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc,
continue;
hlsl_sm4_usage_from_semantic(ctx, &var->semantic, output, &usage);
if (usage == ~0u)
continue;
if (usage == D3D_NAME_TARGET && !ascii_strcasecmp(semantic, "color"))
string_offset = put_string(&buffer, "SV_Target");
@ -383,7 +395,7 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
put_u32(buffer, field->name_bytecode_offset);
put_u32(buffer, field->type->bytecode_offset);
put_u32(buffer, field->reg_offset);
put_u32(buffer, field->reg_offset[HLSL_REGSET_NUMERIC]);
}
}
@ -468,52 +480,60 @@ static D3D_SRV_DIMENSION sm4_rdef_resource_dimension(const struct hlsl_type *typ
}
}
static int sm4_compare_externs(const struct hlsl_ir_var *a, const struct hlsl_ir_var *b)
static int sm4_compare_extern_resources(const void *a, const void *b)
{
if (a->data_type->base_type != b->data_type->base_type)
return a->data_type->base_type - b->data_type->base_type;
if (a->reg.allocated && b->reg.allocated)
return a->reg.id - b->reg.id;
return strcmp(a->name, b->name);
const struct hlsl_ir_var *aa = *(const struct hlsl_ir_var **)a;
const struct hlsl_ir_var *bb = *(const struct hlsl_ir_var **)b;
enum hlsl_regset aa_regset, bb_regset;
aa_regset = hlsl_type_get_regset(aa->data_type);
bb_regset = hlsl_type_get_regset(bb->data_type);
if (aa_regset != bb_regset)
return aa_regset - bb_regset;
return aa->regs[aa_regset].id - bb->regs[bb_regset].id;
}
static void sm4_sort_extern(struct list *sorted, struct hlsl_ir_var *to_sort)
static const struct hlsl_ir_var **sm4_get_extern_resources(struct hlsl_ctx *ctx, unsigned int *count)
{
struct hlsl_ir_var *var;
const struct hlsl_ir_var **extern_resources = NULL;
const struct hlsl_ir_var *var;
enum hlsl_regset regset;
size_t capacity = 0;
list_remove(&to_sort->extern_entry);
*count = 0;
LIST_FOR_EACH_ENTRY(var, sorted, struct hlsl_ir_var, extern_entry)
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (sm4_compare_externs(to_sort, var) < 0)
if (!hlsl_type_is_resource(var->data_type))
continue;
regset = hlsl_type_get_regset(var->data_type);
if (!var->regs[regset].allocated)
continue;
if (!(hlsl_array_reserve(ctx, (void **)&extern_resources, &capacity, *count + 1,
sizeof(*extern_resources))))
{
list_add_before(&var->extern_entry, &to_sort->extern_entry);
return;
*count = 0;
return NULL;
}
extern_resources[*count] = var;
++*count;
}
list_add_tail(sorted, &to_sort->extern_entry);
}
static void sm4_sort_externs(struct hlsl_ctx *ctx)
{
struct list sorted = LIST_INIT(sorted);
struct hlsl_ir_var *var, *next;
LIST_FOR_EACH_ENTRY_SAFE(var, next, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (var->data_type->type == HLSL_CLASS_OBJECT)
sm4_sort_extern(&sorted, var);
}
list_move_tail(&ctx->extern_vars, &sorted);
qsort(extern_resources, *count, sizeof(*extern_resources), sm4_compare_extern_resources);
return extern_resources;
}
static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
{
unsigned int cbuffer_count = 0, resource_count = 0, extern_resources_count, i, j;
size_t cbuffers_offset, resources_offset, creator_offset, string_offset;
size_t cbuffer_position, resource_position, creator_position;
unsigned int cbuffer_count = 0, resource_count = 0, i, j;
const struct hlsl_profile_info *profile = ctx->profile;
const struct hlsl_ir_var **extern_resources;
struct vkd3d_bytecode_buffer buffer = {0};
const struct hlsl_buffer *cbuffer;
const struct hlsl_ir_var *var;
@ -528,14 +548,9 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
0x4353, /* COMPUTE */
};
sm4_sort_externs(ctx);
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (var->reg.allocated && var->data_type->type == HLSL_CLASS_OBJECT)
++resource_count;
}
extern_resources = sm4_get_extern_resources(ctx, &extern_resources_count);
resource_count += extern_resources_count;
LIST_FOR_EACH_ENTRY(cbuffer, &ctx->buffers, struct hlsl_buffer, entry)
{
if (cbuffer->reg.allocated)
@ -571,19 +586,20 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
resources_offset = bytecode_get_size(&buffer);
set_u32(&buffer, resource_position, resources_offset);
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
for (i = 0; i < extern_resources_count; ++i)
{
enum hlsl_regset regset;
uint32_t flags = 0;
if (!var->reg.allocated || var->data_type->type != HLSL_CLASS_OBJECT)
continue;
var = extern_resources[i];
regset = hlsl_type_get_regset(var->data_type);
if (var->reg_reservation.type)
flags |= D3D_SIF_USERPACKED;
put_u32(&buffer, 0); /* name */
put_u32(&buffer, sm4_resource_type(var->data_type));
if (var->data_type->base_type == HLSL_TYPE_SAMPLER)
if (regset == HLSL_REGSET_SAMPLERS)
{
put_u32(&buffer, 0);
put_u32(&buffer, 0);
@ -596,7 +612,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
put_u32(&buffer, ~0u); /* FIXME: multisample count */
flags |= (var->data_type->e.resource_format->dimx - 1) << VKD3D_SM4_SIF_TEXTURE_COMPONENTS_SHIFT;
}
put_u32(&buffer, var->reg.id);
put_u32(&buffer, var->regs[regset].id);
put_u32(&buffer, 1); /* bind count */
put_u32(&buffer, flags);
}
@ -621,12 +637,9 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
put_u32(&buffer, flags); /* flags */
}
i = 0;
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
for (i = 0; i < extern_resources_count; ++i)
{
if (!var->reg.allocated || var->data_type->type != HLSL_CLASS_OBJECT)
continue;
var = extern_resources[i];
string_offset = put_string(&buffer, var->name);
set_u32(&buffer, resources_offset + i++ * 8 * sizeof(uint32_t), string_offset);
@ -641,8 +654,6 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
set_u32(&buffer, resources_offset + i++ * 8 * sizeof(uint32_t), string_offset);
}
assert(i == resource_count);
/* Buffers. */
cbuffers_offset = bytecode_get_size(&buffer);
@ -699,7 +710,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
put_u32(&buffer, 0); /* name */
put_u32(&buffer, var->buffer_offset * sizeof(float));
put_u32(&buffer, var->data_type->reg_size * sizeof(float));
put_u32(&buffer, var->data_type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float));
put_u32(&buffer, flags);
put_u32(&buffer, 0); /* type */
put_u32(&buffer, 0); /* FIXME: default value */
@ -735,6 +746,8 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
set_u32(&buffer, creator_position, creator_offset);
dxbc_writer_add_section(dxbc, TAG_RDEF, buffer.data, buffer.size);
vkd3d_free(extern_resources);
}
static enum vkd3d_sm4_resource_type sm4_resource_dimension(const struct hlsl_type *type)
@ -851,7 +864,7 @@ static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct sm4_register *r
reg->dim = VKD3D_SM4_DIMENSION_VEC4;
if (swizzle_type)
*swizzle_type = VKD3D_SM4_SWIZZLE_VEC4;
reg->idx[0] = var->reg.id;
reg->idx[0] = var->regs[HLSL_REGSET_TEXTURES].id;
reg->idx_count = 1;
*writemask = VKD3DSP_WRITEMASK_ALL;
}
@ -861,7 +874,7 @@ static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct sm4_register *r
reg->dim = VKD3D_SM4_DIMENSION_VEC4;
if (swizzle_type)
*swizzle_type = VKD3D_SM4_SWIZZLE_VEC4;
reg->idx[0] = var->reg.id;
reg->idx[0] = var->regs[HLSL_REGSET_UAVS].id;
reg->idx_count = 1;
*writemask = VKD3DSP_WRITEMASK_ALL;
}
@ -871,7 +884,7 @@ static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct sm4_register *r
reg->dim = VKD3D_SM4_DIMENSION_NONE;
if (swizzle_type)
*swizzle_type = VKD3D_SM4_SWIZZLE_NONE;
reg->idx[0] = var->reg.id;
reg->idx[0] = var->regs[HLSL_REGSET_SAMPLERS].id;
reg->idx_count = 1;
*writemask = VKD3DSP_WRITEMASK_ALL;
}
@ -1141,7 +1154,7 @@ static void write_sm4_dcl_sampler(struct vkd3d_bytecode_buffer *buffer, const st
.opcode = VKD3D_SM4_OP_DCL_SAMPLER,
.dsts[0].reg.type = VKD3D_SM4_RT_SAMPLER,
.dsts[0].reg.idx = {var->reg.id},
.dsts[0].reg.idx = {var->regs[HLSL_REGSET_SAMPLERS].id},
.dsts[0].reg.idx_count = 1,
.dst_count = 1,
};
@ -1151,19 +1164,26 @@ static void write_sm4_dcl_sampler(struct vkd3d_bytecode_buffer *buffer, const st
static void write_sm4_dcl_texture(struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_var *var)
{
bool uav = (var->data_type->base_type == HLSL_TYPE_UAV);
const struct sm4_instruction instr =
struct sm4_instruction instr =
{
.opcode = (uav ? VKD3D_SM5_OP_DCL_UAV_TYPED : VKD3D_SM4_OP_DCL_RESOURCE)
| (sm4_resource_dimension(var->data_type) << VKD3D_SM4_RESOURCE_TYPE_SHIFT),
.dsts[0].reg.type = uav ? VKD3D_SM5_RT_UAV : VKD3D_SM4_RT_RESOURCE,
.dsts[0].reg.idx = {var->reg.id},
.dsts[0].reg.idx = {uav ? var->regs[HLSL_REGSET_UAVS].id : var->regs[HLSL_REGSET_TEXTURES].id},
.dsts[0].reg.idx_count = 1,
.dst_count = 1,
.idx[0] = sm4_resource_format(var->data_type) * 0x1111,
.idx_count = 1,
};
if (var->data_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS
|| var->data_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY)
{
instr.opcode |= var->data_type->sample_count << VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT;
}
write_sm4_instruction(buffer, &instr);
}
@ -1196,15 +1216,17 @@ static void write_sm4_dcl_semantic(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b
else
{
instr.dsts[0].reg.type = output ? VKD3D_SM4_RT_OUTPUT : VKD3D_SM4_RT_INPUT;
instr.dsts[0].reg.idx[0] = var->reg.id;
instr.dsts[0].reg.idx[0] = var->regs[HLSL_REGSET_NUMERIC].id;
instr.dsts[0].reg.idx_count = 1;
instr.dsts[0].writemask = var->reg.writemask;
instr.dsts[0].writemask = var->regs[HLSL_REGSET_NUMERIC].writemask;
}
if (instr.dsts[0].reg.type == VKD3D_SM4_RT_DEPTHOUT)
instr.dsts[0].reg.dim = VKD3D_SM4_DIMENSION_SCALAR;
hlsl_sm4_usage_from_semantic(ctx, &var->semantic, output, &usage);
if (usage == ~0u)
usage = D3D_NAME_UNDEFINED;
if (var->is_input_semantic)
{
@ -1232,7 +1254,7 @@ static void write_sm4_dcl_semantic(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b
{
enum vkd3d_shader_interpolation_mode mode = VKD3DSIM_LINEAR;
if ((var->modifiers & HLSL_STORAGE_NOINTERPOLATION) || type_is_integer(var->data_type))
if ((var->storage_modifiers & HLSL_STORAGE_NOINTERPOLATION) || type_is_integer(var->data_type))
mode = VKD3DSIM_CONSTANT;
instr.opcode |= mode << VKD3D_SM4_INTERPOLATION_MODE_SHIFT;
@ -1319,6 +1341,29 @@ static void write_sm4_unary_op(struct vkd3d_bytecode_buffer *buffer, enum vkd3d_
write_sm4_instruction(buffer, &instr);
}
static void write_sm4_unary_op_with_two_destinations(struct vkd3d_bytecode_buffer *buffer,
enum vkd3d_sm4_opcode opcode, const struct hlsl_ir_node *dst, unsigned dst_idx,
const struct hlsl_ir_node *src)
{
struct sm4_instruction instr;
memset(&instr, 0, sizeof(instr));
instr.opcode = opcode;
assert(dst_idx < ARRAY_SIZE(instr.dsts));
sm4_dst_from_node(&instr.dsts[dst_idx], dst);
assert(1 - dst_idx >= 0);
instr.dsts[1 - dst_idx].reg.type = VKD3D_SM4_RT_NULL;
instr.dsts[1 - dst_idx].reg.dim = VKD3D_SM4_DIMENSION_NONE;
instr.dsts[1 - dst_idx].reg.idx_count = 0;
instr.dst_count = 2;
sm4_src_from_node(&instr.srcs[0], src, instr.dsts[dst_idx].writemask);
instr.src_count = 1;
write_sm4_instruction(buffer, &instr);
}
static void write_sm4_binary_op(struct vkd3d_bytecode_buffer *buffer, enum vkd3d_sm4_opcode opcode,
const struct hlsl_ir_node *dst, const struct hlsl_ir_node *src1, const struct hlsl_ir_node *src2)
{
@ -1418,7 +1463,8 @@ static void write_sm4_constant(struct hlsl_ctx *ctx,
static void write_sm4_ld(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct hlsl_type *resource_type, const struct hlsl_ir_node *dst,
const struct hlsl_deref *resource, const struct hlsl_ir_node *coords)
const struct hlsl_deref *resource, const struct hlsl_ir_node *coords,
const struct hlsl_ir_node *texel_offset)
{
bool uav = (resource_type->base_type == HLSL_TYPE_UAV);
struct sm4_instruction instr;
@ -1427,6 +1473,16 @@ static void write_sm4_ld(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buf
memset(&instr, 0, sizeof(instr));
instr.opcode = uav ? VKD3D_SM5_OP_LD_UAV_TYPED : VKD3D_SM4_OP_LD;
if (texel_offset)
{
if (!encode_texel_offset_as_aoffimmi(&instr, texel_offset))
{
hlsl_error(ctx, &texel_offset->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TEXEL_OFFSET,
"Offset must resolve to integer literal in the range -8 to 7.");
return;
}
}
sm4_dst_from_node(&instr.dsts[0], dst);
instr.dst_count = 1;
@ -1675,6 +1731,11 @@ static void write_sm4_expr(struct hlsl_ctx *ctx,
write_sm4_cast(ctx, buffer, expr);
break;
case HLSL_OP1_COS:
assert(type_is_float(dst_type));
write_sm4_unary_op_with_two_destinations(buffer, VKD3D_SM4_OP_SINCOS, &expr->node, 1, arg1);
break;
case HLSL_OP1_EXP2:
assert(type_is_float(dst_type));
write_sm4_unary_op(buffer, VKD3D_SM4_OP_EXP, &expr->node, arg1, 0);
@ -1738,6 +1799,11 @@ static void write_sm4_expr(struct hlsl_ctx *ctx,
&expr->node, arg1, 0);
break;
case HLSL_OP1_SIN:
assert(type_is_float(dst_type));
write_sm4_unary_op_with_two_destinations(buffer, VKD3D_SM4_OP_SINCOS, &expr->node, 0, arg1);
break;
case HLSL_OP1_SQRT:
assert(type_is_float(dst_type));
write_sm4_unary_op(buffer, VKD3D_SM4_OP_SQRT, &expr->node, arg1, 0);
@ -2060,6 +2126,28 @@ static void write_sm4_if(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buf
write_sm4_instruction(buffer, &instr);
}
static void write_sm4_jump(struct hlsl_ctx *ctx,
struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_jump *jump)
{
struct sm4_instruction instr = {0};
switch (jump->type)
{
case HLSL_IR_JUMP_BREAK:
instr.opcode = VKD3D_SM4_OP_BREAK;
break;
case HLSL_IR_JUMP_RETURN:
vkd3d_unreachable();
default:
hlsl_fixme(ctx, &jump->node.loc, "Jump type %s.\n", hlsl_jump_type_to_string(jump->type));
return;
}
write_sm4_instruction(buffer, &instr);
}
static void write_sm4_load(struct hlsl_ctx *ctx,
struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_load *load)
{
@ -2110,11 +2198,19 @@ static void write_sm4_gather(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer
sm4_src_from_node(&instr.srcs[instr.src_count++], coords, VKD3DSP_WRITEMASK_ALL);
/* FIXME: Use an aoffimmi modifier if possible. */
if (texel_offset)
{
instr.opcode = VKD3D_SM5_OP_GATHER4_PO;
sm4_src_from_node(&instr.srcs[instr.src_count++], texel_offset, VKD3DSP_WRITEMASK_ALL);
if (!encode_texel_offset_as_aoffimmi(&instr, texel_offset))
{
if (ctx->profile->major_version < 5)
{
hlsl_error(ctx, &texel_offset->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TEXEL_OFFSET,
"Offset must resolve to integer literal in the range -8 to 7 for profiles < 5.");
return;
}
instr.opcode = VKD3D_SM5_OP_GATHER4_PO;
sm4_src_from_node(&instr.srcs[instr.src_count++], texel_offset, VKD3DSP_WRITEMASK_ALL);
}
}
sm4_src_from_deref(ctx, &instr.srcs[instr.src_count++], resource, resource_type, instr.dsts[0].writemask);
@ -2171,12 +2267,16 @@ static void write_sm4_resource_load(struct hlsl_ctx *ctx,
switch (load->load_type)
{
case HLSL_RESOURCE_LOAD:
write_sm4_ld(ctx, buffer, resource_type, &load->node, &load->resource, coords);
write_sm4_ld(ctx, buffer, resource_type, &load->node, &load->resource,
coords, texel_offset);
break;
case HLSL_RESOURCE_SAMPLE:
if (!load->sampler.var)
{
hlsl_fixme(ctx, &load->node.loc, "SM4 combined sample expression.");
return;
}
write_sm4_sample(ctx, buffer, resource_type, &load->node,
&load->resource, &load->sampler, coords, texel_offset);
break;
@ -2293,6 +2393,9 @@ static void write_sm4_block(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *
switch (instr->type)
{
case HLSL_IR_CALL:
vkd3d_unreachable();
case HLSL_IR_CONSTANT:
write_sm4_constant(ctx, buffer, hlsl_ir_constant(instr));
break;
@ -2305,6 +2408,10 @@ static void write_sm4_block(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *
write_sm4_if(ctx, buffer, hlsl_ir_if(instr));
break;
case HLSL_IR_JUMP:
write_sm4_jump(ctx, buffer, hlsl_ir_jump(instr));
break;
case HLSL_IR_LOAD:
write_sm4_load(ctx, buffer, hlsl_ir_load(instr));
break;
@ -2330,7 +2437,7 @@ static void write_sm4_block(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *
break;
default:
FIXME("Unhandled instruction type %s.\n", hlsl_node_type_to_string(instr->type));
hlsl_fixme(ctx, &instr->loc, "Instruction type %s.", hlsl_node_type_to_string(instr->type));
}
}
}
@ -2339,7 +2446,9 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
const struct hlsl_ir_function_decl *entry_func, struct dxbc_writer *dxbc)
{
const struct hlsl_profile_info *profile = ctx->profile;
const struct hlsl_ir_var **extern_resources;
struct vkd3d_bytecode_buffer buffer = {0};
unsigned int extern_resources_count, i;
const struct hlsl_buffer *cbuffer;
const struct hlsl_ir_var *var;
size_t token_count_position;
@ -2357,6 +2466,8 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
VKD3D_SM4_LIB,
};
extern_resources = sm4_get_extern_resources(ctx, &extern_resources_count);
put_u32(&buffer, vkd3d_make_u32((profile->major_version << 4) | profile->minor_version, shader_types[profile->type]));
token_count_position = put_u32(&buffer, 0);
@ -2366,10 +2477,9 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
write_sm4_dcl_constant_buffer(&buffer, cbuffer);
}
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, const struct hlsl_ir_var, extern_entry)
for (i = 0; i < extern_resources_count; ++i)
{
if (!var->reg.allocated || var->data_type->type != HLSL_CLASS_OBJECT)
continue;
var = extern_resources[i];
if (var->data_type->base_type == HLSL_TYPE_SAMPLER)
write_sm4_dcl_sampler(&buffer, var);
@ -2396,6 +2506,8 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
set_u32(&buffer, token_count_position, bytecode_get_size(&buffer) / sizeof(uint32_t));
dxbc_writer_add_section(dxbc, TAG_SHDR, buffer.data, buffer.size);
vkd3d_free(extern_resources);
}
int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out)
@ -2414,6 +2526,6 @@ int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun
if (!(ret = ctx->result))
ret = dxbc_writer_write(&dxbc, out);
for (i = 0; i < dxbc.section_count; ++i)
vkd3d_free((void *)dxbc.sections[i].data);
vkd3d_shader_free_shader_code(&dxbc.sections[i].data);
return ret;
}

View file

@ -56,6 +56,9 @@
#define VKD3D_SM4_RESOURCE_TYPE_SHIFT 11
#define VKD3D_SM4_RESOURCE_TYPE_MASK (0xfu << VKD3D_SM4_RESOURCE_TYPE_SHIFT)
#define VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT 16
#define VKD3D_SM4_RESOURCE_SAMPLE_COUNT_MASK (0xfu << VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT)
#define VKD3D_SM4_PRIMITIVE_TYPE_SHIFT 11
#define VKD3D_SM4_PRIMITIVE_TYPE_MASK (0x3fu << VKD3D_SM4_PRIMITIVE_TYPE_SHIFT)

View file

@ -206,7 +206,7 @@ static enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval(enum vkd3d_
#define VKD3D_SPIRV_VERSION 0x00010000
#define VKD3D_SPIRV_GENERATOR_ID 18
#define VKD3D_SPIRV_GENERATOR_VERSION 6
#define VKD3D_SPIRV_GENERATOR_VERSION 7
#define VKD3D_SPIRV_GENERATOR_MAGIC vkd3d_make_u32(VKD3D_SPIRV_GENERATOR_VERSION, VKD3D_SPIRV_GENERATOR_ID)
struct vkd3d_spirv_stream
@ -1767,7 +1767,7 @@ static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, const
rb_init(&builder->declarations, vkd3d_spirv_declaration_compare);
builder->main_function_id = vkd3d_spirv_alloc_id(builder);
vkd3d_spirv_build_op_name(builder, builder->main_function_id, entry_point);
vkd3d_spirv_build_op_name(builder, builder->main_function_id, "%s", entry_point);
}
static void vkd3d_spirv_builder_begin_main_function(struct vkd3d_spirv_builder *builder)
@ -2223,7 +2223,7 @@ struct spirv_compiler
struct vkd3d_spirv_builder spirv_builder;
struct vkd3d_shader_message_context *message_context;
const struct vkd3d_shader_location *location;
struct vkd3d_shader_location location;
bool failed;
bool strip_debug;
@ -2285,6 +2285,7 @@ struct spirv_compiler
struct vkd3d_shader_spec_constant *spec_constants;
size_t spec_constants_size;
enum vkd3d_shader_compile_option_formatting_flags formatting;
bool write_tess_geom_point_size;
struct vkd3d_string_buffer_cache string_buffers;
};
@ -2322,7 +2323,7 @@ struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version *
memset(compiler, 0, sizeof(*compiler));
compiler->message_context = message_context;
compiler->location = location;
compiler->location = *location;
if ((target_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO)))
{
@ -2351,6 +2352,7 @@ struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version *
compiler->formatting = VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT
| VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER;
compiler->write_tess_geom_point_size = true;
for (i = 0; i < compile_info->option_count; ++i)
{
@ -2389,6 +2391,10 @@ struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version *
else
WARN("Ignoring unrecognised value %#x for option %#x.\n", option->value, option->name);
break;
case VKD3D_SHADER_COMPILE_OPTION_WRITE_TESS_GEOM_POINT_SIZE:
compiler->write_tess_geom_point_size = option->value;
break;
}
}
@ -2560,7 +2566,7 @@ static void VKD3D_PRINTF_FUNC(3, 4) spirv_compiler_error(struct spirv_compiler *
va_list args;
va_start(args, format);
vkd3d_shader_verror(compiler->message_context, compiler->location, error, format, args);
vkd3d_shader_verror(compiler->message_context, &compiler->location, error, format, args);
va_end(args);
compiler->failed = true;
}
@ -6348,10 +6354,18 @@ static void spirv_compiler_emit_point_size(struct spirv_compiler *compiler)
/* Set the point size. Point sprites are not supported in d3d10+, but
* point primitives can still be used with e.g. stream output. Vulkan
* requires the point size to always be explicitly defined when outputting
* points. */
vkd3d_spirv_build_op_store(&compiler->spirv_builder,
spirv_compiler_emit_builtin_variable(compiler, &point_size, SpvStorageClassOutput, 0),
spirv_compiler_get_constant_float(compiler, 1.0f), SpvMemoryAccessMaskNone);
* points.
*
* If shaderTessellationAndGeometryPointSize is disabled, we must not write
* PointSize for tessellation and geometry shaders. In that case the point
* size defaults to 1.0. */
if (spirv_compiler_is_opengl_target(compiler) || compiler->shader_type == VKD3D_SHADER_TYPE_VERTEX
|| compiler->write_tess_geom_point_size)
{
vkd3d_spirv_build_op_store(&compiler->spirv_builder,
spirv_compiler_emit_builtin_variable(compiler, &point_size, SpvStorageClassOutput, 0),
spirv_compiler_get_constant_float(compiler, 1.0f), SpvMemoryAccessMaskNone);
}
}
static void spirv_compiler_emit_dcl_output_topology(struct spirv_compiler *compiler,
@ -9577,7 +9591,7 @@ static bool is_dcl_instruction(enum vkd3d_shader_opcode handler_idx)
|| handler_idx == VKD3DSIH_HS_DECLS;
}
int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
int ret = VKD3D_OK;
@ -9934,12 +9948,24 @@ int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
}
int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *spirv)
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_parser *parser,
struct vkd3d_shader_code *spirv)
{
const struct vkd3d_shader_instruction_array *instructions = &parser->instructions;
const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info;
const struct vkd3d_shader_spirv_domain_shader_target_info *ds_info;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_phase *phase;
enum vkd3d_result result = VKD3D_OK;
unsigned int i;
compiler->location.column = 0;
for (i = 0; i < instructions->count; ++i)
{
compiler->location.line = i + 1;
if ((result = spirv_compiler_handle_instruction(compiler, &instructions->elements[i])) < 0)
return result;
}
if ((phase = spirv_compiler_get_current_shader_phase(compiler)))
spirv_compiler_leave_shader_phase(compiler, phase);

View file

@ -663,8 +663,14 @@ static void shader_dump_decl_usage(struct vkd3d_d3d_asm_compiler *compiler,
shader_addline(buffer, "_resource_");
shader_dump_resource_type(compiler, semantic->resource_type);
if (semantic->resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS
|| semantic->resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY)
{
shader_addline(buffer, "(%u)", semantic->sample_count);
}
if (semantic->resource.reg.reg.type == VKD3DSPR_UAV)
shader_dump_uav_flags(compiler, flags);
shader_addline(buffer, " ");
shader_dump_data_type(compiler, semantic->resource_data_type);
}
else
@ -1859,7 +1865,7 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(struct vkd3d_shader_parser *parser,
struct vkd3d_d3d_asm_compiler compiler;
enum vkd3d_result result = VKD3D_OK;
struct vkd3d_string_buffer *buffer;
unsigned int indent, i;
unsigned int indent, i, j;
const char *indent_str;
void *code;
@ -1920,41 +1926,32 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(struct vkd3d_shader_parser *parser,
shader_version->minor, compiler.colours.reset);
indent = 0;
vkd3d_shader_parser_reset(parser);
while (!vkd3d_shader_parser_is_end(parser))
for (i = 0; i < parser->instructions.count; ++i)
{
struct vkd3d_shader_instruction ins;
struct vkd3d_shader_instruction *ins = &parser->instructions.elements[i];
vkd3d_shader_parser_read_instruction(parser, &ins);
if (ins.handler_idx == VKD3DSIH_INVALID)
{
WARN("Skipping unrecognized instruction.\n");
vkd3d_string_buffer_printf(buffer, "<unrecognized instruction>\n");
result = VKD3D_ERROR;
continue;
}
switch (ins.handler_idx)
switch (ins->handler_idx)
{
case VKD3DSIH_ELSE:
case VKD3DSIH_ENDIF:
case VKD3DSIH_ENDLOOP:
case VKD3DSIH_ENDSWITCH:
--indent;
if (indent)
--indent;
break;
default:
break;
}
for (i = 0; i < indent; ++i)
for (j = 0; j < indent; ++j)
{
vkd3d_string_buffer_printf(buffer, "%s", indent_str);
}
shader_dump_instruction(&compiler, &ins);
shader_dump_instruction(&compiler, ins);
switch (ins.handler_idx)
switch (ins->handler_idx)
{
case VKD3DSIH_ELSE:
case VKD3DSIH_IF:
@ -1968,9 +1965,6 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(struct vkd3d_shader_parser *parser,
}
}
if (parser->failed)
result = VKD3D_ERROR_INVALID_SHADER;
if ((code = vkd3d_malloc(buffer->content_size)))
{
memcpy(code, buffer->buffer, buffer->content_size);

View file

@ -425,9 +425,10 @@ void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type,
shader_get_source_type_suffix(source_type), shader->code, shader->size);
}
void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
struct vkd3d_shader_message_context *message_context, const char *source_name,
const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops)
const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops,
unsigned int instruction_reserve)
{
parser->message_context = message_context;
parser->location.source_name = source_name;
@ -435,6 +436,7 @@ void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
parser->location.column = 0;
parser->shader_version = *version;
parser->ops = ops;
return shader_instruction_array_init(&parser->instructions, instruction_reserve);
}
void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser,
@ -1053,9 +1055,10 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser *parser)
{
struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info;
struct vkd3d_shader_instruction instruction;
struct vkd3d_shader_instruction *instruction;
struct vkd3d_shader_scan_context context;
int ret;
int ret = VKD3D_OK;
unsigned int i;
if ((scan_descriptor_info = vkd3d_find_struct(compile_info->next, SCAN_DESCRIPTOR_INFO)))
{
@ -1068,33 +1071,19 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info
if (TRACE_ON())
{
vkd3d_shader_trace(parser);
vkd3d_shader_parser_reset(parser);
}
while (!vkd3d_shader_parser_is_end(parser))
for (i = 0; i < parser->instructions.count; ++i)
{
vkd3d_shader_parser_read_instruction(parser, &instruction);
if (instruction.handler_idx == VKD3DSIH_INVALID)
{
WARN("Encountered unrecognized or invalid instruction.\n");
if (scan_descriptor_info)
vkd3d_shader_free_scan_descriptor_info(scan_descriptor_info);
ret = VKD3D_ERROR_INVALID_SHADER;
goto done;
}
if ((ret = vkd3d_shader_scan_instruction(&context, &instruction)) < 0)
instruction = &parser->instructions.elements[i];
if ((ret = vkd3d_shader_scan_instruction(&context, instruction)) < 0)
{
if (scan_descriptor_info)
vkd3d_shader_free_scan_descriptor_info(scan_descriptor_info);
goto done;
break;
}
}
ret = parser->failed ? VKD3D_ERROR_INVALID_SHADER : VKD3D_OK;
done:
vkd3d_shader_scan_context_cleanup(&context);
return ret;
}
@ -1182,7 +1171,6 @@ static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_scan_descriptor_info scan_descriptor_info;
struct vkd3d_shader_instruction instruction;
struct vkd3d_shader_compile_info scan_info;
struct spirv_compiler *spirv_compiler;
struct vkd3d_shader_parser *parser;
@ -1243,26 +1231,7 @@ static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info
return VKD3D_ERROR;
}
while (!vkd3d_shader_parser_is_end(parser))
{
vkd3d_shader_parser_read_instruction(parser, &instruction);
if (instruction.handler_idx == VKD3DSIH_INVALID)
{
WARN("Encountered unrecognized or invalid instruction.\n");
ret = VKD3D_ERROR_INVALID_SHADER;
break;
}
if ((ret = spirv_compiler_handle_instruction(spirv_compiler, &instruction)) < 0)
break;
}
if (parser->failed)
ret = VKD3D_ERROR_INVALID_SHADER;
if (ret >= 0)
ret = spirv_compiler_generate_spirv(spirv_compiler, compile_info, out);
ret = spirv_compiler_generate_spirv(spirv_compiler, compile_info, parser, out);
spirv_compiler_destroy(spirv_compiler);
vkd3d_shader_parser_destroy(parser);
@ -1431,7 +1400,7 @@ int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
*messages = NULL;
vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO);
ret = shader_parse_input_signature(dxbc->code, dxbc->size, &message_context, signature);
ret = shader_parse_input_signature(dxbc, &message_context, signature);
vkd3d_shader_message_context_trace_messages(&message_context);
if (!vkd3d_shader_message_context_copy_messages(&message_context, messages))
ret = VKD3D_ERROR_OUT_OF_MEMORY;
@ -1581,3 +1550,106 @@ void vkd3d_shader_set_log_callback(PFN_vkd3d_log callback)
{
vkd3d_dbg_set_log_callback(callback);
}
static struct vkd3d_shader_param_node *shader_param_allocator_node_create(
struct vkd3d_shader_param_allocator *allocator)
{
struct vkd3d_shader_param_node *node;
if (!(node = vkd3d_malloc(offsetof(struct vkd3d_shader_param_node, param[allocator->count * allocator->stride]))))
return NULL;
node->next = NULL;
return node;
}
static void shader_param_allocator_init(struct vkd3d_shader_param_allocator *allocator,
unsigned int count, unsigned int stride)
{
allocator->count = max(count, 4);
allocator->stride = stride;
allocator->head = NULL;
allocator->current = NULL;
allocator->index = allocator->count;
}
static void shader_param_allocator_destroy(struct vkd3d_shader_param_allocator *allocator)
{
struct vkd3d_shader_param_node *current = allocator->head;
while (current)
{
struct vkd3d_shader_param_node *next = current->next;
vkd3d_free(current);
current = next;
}
}
void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, unsigned int count)
{
void *params;
if (!count)
return NULL;
if (count > allocator->count - allocator->index)
{
struct vkd3d_shader_param_node *next = shader_param_allocator_node_create(allocator);
if (!next)
return NULL;
if (allocator->current)
allocator->current->next = next;
else
allocator->head = next;
allocator->current = next;
allocator->index = 0;
}
params = &allocator->current->param[allocator->index * allocator->stride];
allocator->index += count;
return params;
}
bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve)
{
memset(instructions, 0, sizeof(*instructions));
/* Size the parameter initial allocations so they are large enough for most shaders. The
* code path for chained allocations will be tested if a few shaders need to use it. */
shader_param_allocator_init(&instructions->dst_params, reserve - reserve / 8u,
sizeof(*instructions->elements->dst));
shader_param_allocator_init(&instructions->src_params, reserve * 2u, sizeof(*instructions->elements->src));
return shader_instruction_array_reserve(instructions, reserve);
}
bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve)
{
if (!vkd3d_array_reserve((void **)&instructions->elements, &instructions->capacity, reserve,
sizeof(*instructions->elements)))
{
ERR("Failed to allocate instructions.\n");
return false;
}
return true;
}
bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions,
struct vkd3d_shader_immediate_constant_buffer *icb)
{
if (!vkd3d_array_reserve((void **)&instructions->icbs, &instructions->icb_capacity, instructions->icb_count + 1,
sizeof(*instructions->icbs)))
return false;
instructions->icbs[instructions->icb_count++] = icb;
return true;
}
void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions)
{
unsigned int i;
vkd3d_free(instructions->elements);
shader_param_allocator_destroy(&instructions->dst_params);
shader_param_allocator_destroy(&instructions->src_params);
for (i = 0; i < instructions->icb_count; ++i)
vkd3d_free(instructions->icbs[i]);
vkd3d_free(instructions->icbs);
}

View file

@ -68,9 +68,12 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_DXBC_INVALID_VERSION = 4,
VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET = 5,
VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE = 6,
VKD3D_SHADER_ERROR_DXBC_OUT_OF_MEMORY = 7,
VKD3D_SHADER_ERROR_DXBC_INVALID_SIGNATURE = 8,
VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF = 1000,
VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_RANGE = 1001,
VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY = 1002,
VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND = 2000,
VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001,
@ -121,6 +124,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF = 5022,
VKD3D_SHADER_ERROR_HLSL_INVALID_THREAD_COUNT = 5023,
VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE = 5024,
VKD3D_SHADER_ERROR_HLSL_RECURSIVE_CALL = 5025,
VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300,
VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301,
@ -132,6 +136,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_D3DBC_INVALID_VERSION_TOKEN = 7001,
VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE = 7002,
VKD3D_SHADER_ERROR_D3DBC_INVALID_RESOURCE_TYPE = 7003,
VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY = 7004,
VKD3D_SHADER_WARNING_D3DBC_IGNORED_INSTRUCTION_FLAGS= 7300,
};
@ -617,7 +622,6 @@ enum vkd3d_shader_conditional_op
VKD3D_SHADER_CONDITIONAL_OP_Z = 1
};
#define MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE 4096
#define MAX_REG_OUTPUT 32
enum vkd3d_shader_type
@ -647,7 +651,7 @@ struct vkd3d_shader_version
struct vkd3d_shader_immediate_constant_buffer
{
unsigned int vec4_count;
uint32_t data[MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE];
uint32_t data[];
};
struct vkd3d_shader_indexable_temp
@ -738,6 +742,7 @@ struct vkd3d_shader_semantic
enum vkd3d_decl_usage usage;
unsigned int usage_idx;
enum vkd3d_shader_resource_type resource_type;
unsigned int sample_count;
enum vkd3d_data_type resource_data_type[VKD3D_VEC4_SIZE];
struct vkd3d_shader_resource resource;
};
@ -928,6 +933,56 @@ struct vkd3d_shader_location
unsigned int line, column;
};
struct vkd3d_shader_param_node
{
struct vkd3d_shader_param_node *next;
uint8_t param[];
};
struct vkd3d_shader_param_allocator
{
struct vkd3d_shader_param_node *head;
struct vkd3d_shader_param_node *current;
unsigned int count;
unsigned int stride;
unsigned int index;
};
void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, unsigned int count);
static inline struct vkd3d_shader_src_param *shader_src_param_allocator_get(
struct vkd3d_shader_param_allocator *allocator, unsigned int count)
{
assert(allocator->stride == sizeof(struct vkd3d_shader_src_param));
return shader_param_allocator_get(allocator, count);
}
static inline struct vkd3d_shader_dst_param *shader_dst_param_allocator_get(
struct vkd3d_shader_param_allocator *allocator, unsigned int count)
{
assert(allocator->stride == sizeof(struct vkd3d_shader_dst_param));
return shader_param_allocator_get(allocator, count);
}
struct vkd3d_shader_instruction_array
{
struct vkd3d_shader_instruction *elements;
size_t capacity;
size_t count;
struct vkd3d_shader_param_allocator src_params;
struct vkd3d_shader_param_allocator dst_params;
struct vkd3d_shader_immediate_constant_buffer **icbs;
size_t icb_capacity;
size_t icb_count;
};
bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve);
bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve);
bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions,
struct vkd3d_shader_immediate_constant_buffer *icb);
void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions);
struct vkd3d_shader_parser
{
struct vkd3d_shader_message_context *message_context;
@ -938,45 +993,41 @@ struct vkd3d_shader_parser
struct vkd3d_shader_version shader_version;
const uint32_t *ptr;
const struct vkd3d_shader_parser_ops *ops;
struct vkd3d_shader_instruction_array instructions;
size_t instruction_idx;
};
struct vkd3d_shader_parser_ops
{
void (*parser_reset)(struct vkd3d_shader_parser *parser);
void (*parser_destroy)(struct vkd3d_shader_parser *parser);
void (*parser_read_instruction)(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *instruction);
bool (*parser_is_end)(struct vkd3d_shader_parser *parser);
};
void vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser,
enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4);
void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
struct vkd3d_shader_message_context *message_context, const char *source_name,
const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops);
const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops,
unsigned int instruction_reserve);
void vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser,
enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4);
static inline struct vkd3d_shader_dst_param *shader_parser_get_dst_params(
struct vkd3d_shader_parser *parser, unsigned int count)
{
return shader_dst_param_allocator_get(&parser->instructions.dst_params, count);
}
static inline struct vkd3d_shader_src_param *shader_parser_get_src_params(
struct vkd3d_shader_parser *parser, unsigned int count)
{
return shader_src_param_allocator_get(&parser->instructions.src_params, count);
}
static inline void vkd3d_shader_parser_destroy(struct vkd3d_shader_parser *parser)
{
parser->ops->parser_destroy(parser);
}
static inline bool vkd3d_shader_parser_is_end(struct vkd3d_shader_parser *parser)
{
return parser->ops->parser_is_end(parser);
}
static inline void vkd3d_shader_parser_read_instruction(struct vkd3d_shader_parser *parser,
struct vkd3d_shader_instruction *instruction)
{
parser->ops->parser_read_instruction(parser, instruction);
}
static inline void vkd3d_shader_parser_reset(struct vkd3d_shader_parser *parser)
{
parser->ops->parser_reset(parser);
}
void vkd3d_shader_trace(struct vkd3d_shader_parser *parser);
const char *shader_get_type_prefix(enum vkd3d_shader_type type);
@ -1077,7 +1128,7 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
void free_shader_desc(struct vkd3d_shader_desc *desc);
int shader_parse_input_signature(const void *dxbc, size_t dxbc_length,
int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_signature *signature);
struct vkd3d_glsl_generator;
@ -1096,10 +1147,9 @@ struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version *
const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info,
const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info,
struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location);
int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction);
int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *spirv);
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_parser *parser,
struct vkd3d_shader_code *spirv);
void spirv_compiler_destroy(struct spirv_compiler *compiler);
void vkd3d_compute_dxbc_checksum(const void *dxbc, size_t size, uint32_t checksum[4]);
@ -1261,19 +1311,12 @@ static inline void *vkd3d_find_struct_(const struct vkd3d_struct *chain,
#define TAG_SHEX VKD3D_MAKE_TAG('S', 'H', 'E', 'X')
#define TAG_TEXT VKD3D_MAKE_TAG('T', 'E', 'X', 'T')
struct dxbc_writer_section
{
uint32_t tag;
const uint8_t *data;
size_t size;
};
#define DXBC_MAX_SECTION_COUNT 5
struct dxbc_writer
{
unsigned int section_count;
struct dxbc_writer_section sections[DXBC_MAX_SECTION_COUNT];
struct vkd3d_shader_dxbc_section_desc sections[DXBC_MAX_SECTION_COUNT];
};
void dxbc_writer_add_section(struct dxbc_writer *dxbc, uint32_t tag, const void *data, size_t size);

File diff suppressed because it is too large Load diff

View file

@ -2052,13 +2052,8 @@ static HRESULT d3d12_device_init_pipeline_cache(struct d3d12_device *device)
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
VkPipelineCacheCreateInfo cache_info;
VkResult vr;
int rc;
if ((rc = vkd3d_mutex_init(&device->mutex)))
{
ERR("Failed to initialize mutex, error %d.\n", rc);
return hresult_from_errno(rc);
}
vkd3d_mutex_init(&device->mutex);
cache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
cache_info.pNext = NULL;
@ -2149,17 +2144,12 @@ D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_al
size_t alignment, size_t size, void *ptr)
{
D3D12_GPU_VIRTUAL_ADDRESS address;
int rc;
if (size > ~(size_t)0 - (alignment - 1))
return 0;
size = align(size, alignment);
if ((rc = vkd3d_mutex_lock(&allocator->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return 0;
}
vkd3d_mutex_lock(&allocator->mutex);
if (size <= VKD3D_VA_SLAB_SIZE && allocator->free_slab)
address = vkd3d_gpu_va_allocator_allocate_slab(allocator, size, ptr);
@ -2225,7 +2215,6 @@ void *vkd3d_gpu_va_allocator_dereference(struct vkd3d_gpu_va_allocator *allocato
D3D12_GPU_VIRTUAL_ADDRESS address)
{
void *ret;
int rc;
/* If we land in the non-fallback region, dereferencing VA is lock-less.
* The base pointer is immutable, and the only way we can have a data race
@ -2237,11 +2226,7 @@ void *vkd3d_gpu_va_allocator_dereference(struct vkd3d_gpu_va_allocator *allocato
return vkd3d_gpu_va_allocator_dereference_slab(allocator, address);
/* Slow fallback. */
if ((rc = vkd3d_mutex_lock(&allocator->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return NULL;
}
vkd3d_mutex_lock(&allocator->mutex);
ret = vkd3d_gpu_va_allocator_dereference_fallback(allocator, address);
@ -2298,13 +2283,7 @@ static void vkd3d_gpu_va_allocator_free_fallback(struct vkd3d_gpu_va_allocator *
void vkd3d_gpu_va_allocator_free(struct vkd3d_gpu_va_allocator *allocator, D3D12_GPU_VIRTUAL_ADDRESS address)
{
int rc;
if ((rc = vkd3d_mutex_lock(&allocator->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return;
}
vkd3d_mutex_lock(&allocator->mutex);
if (address < VKD3D_VA_FALLBACK_BASE)
{
@ -2321,7 +2300,6 @@ void vkd3d_gpu_va_allocator_free(struct vkd3d_gpu_va_allocator *allocator, D3D12
static bool vkd3d_gpu_va_allocator_init(struct vkd3d_gpu_va_allocator *allocator)
{
unsigned int i;
int rc;
memset(allocator, 0, sizeof(*allocator));
allocator->fallback_floor = VKD3D_VA_FALLBACK_BASE;
@ -2341,200 +2319,20 @@ static bool vkd3d_gpu_va_allocator_init(struct vkd3d_gpu_va_allocator *allocator
allocator->slabs[i].ptr = &allocator->slabs[i + 1];
}
if ((rc = vkd3d_mutex_init(&allocator->mutex)))
{
ERR("Failed to initialize mutex, error %d.\n", rc);
vkd3d_free(allocator->slabs);
return false;
}
vkd3d_mutex_init(&allocator->mutex);
return true;
}
static void vkd3d_gpu_va_allocator_cleanup(struct vkd3d_gpu_va_allocator *allocator)
{
int rc;
if ((rc = vkd3d_mutex_lock(&allocator->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return;
}
vkd3d_mutex_lock(&allocator->mutex);
vkd3d_free(allocator->slabs);
vkd3d_free(allocator->fallback_allocations);
vkd3d_mutex_unlock(&allocator->mutex);
vkd3d_mutex_destroy(&allocator->mutex);
}
/* We could use bsearch() or recursion here, but it probably helps to omit
* all the extra function calls. */
static struct vkd3d_gpu_descriptor_allocation *vkd3d_gpu_descriptor_allocator_binary_search(
const struct vkd3d_gpu_descriptor_allocator *allocator, const struct d3d12_desc *desc)
{
struct vkd3d_gpu_descriptor_allocation *allocations = allocator->allocations;
const struct d3d12_desc *base;
size_t centre, count;
for (count = allocator->allocation_count; count > 1; )
{
centre = count >> 1;
base = allocations[centre].base;
if (base <= desc)
{
allocations += centre;
count -= centre;
}
else
{
count = centre;
}
}
return allocations;
}
bool vkd3d_gpu_descriptor_allocator_register_range(struct vkd3d_gpu_descriptor_allocator *allocator,
const struct d3d12_desc *base, size_t count)
{
struct vkd3d_gpu_descriptor_allocation *allocation;
int rc;
if ((rc = vkd3d_mutex_lock(&allocator->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return false;
}
if (!vkd3d_array_reserve((void **)&allocator->allocations, &allocator->allocations_size,
allocator->allocation_count + 1, sizeof(*allocator->allocations)))
{
vkd3d_mutex_unlock(&allocator->mutex);
return false;
}
if (allocator->allocation_count > 1)
allocation = vkd3d_gpu_descriptor_allocator_binary_search(allocator, base);
else
allocation = allocator->allocations;
allocation += allocator->allocation_count && base > allocation->base;
memmove(&allocation[1], allocation, (allocator->allocation_count++ - (allocation - allocator->allocations))
* sizeof(*allocation));
allocation->base = base;
allocation->count = count;
vkd3d_mutex_unlock(&allocator->mutex);
return true;
}
bool vkd3d_gpu_descriptor_allocator_unregister_range(
struct vkd3d_gpu_descriptor_allocator *allocator, const struct d3d12_desc *base)
{
bool found;
size_t i;
int rc;
if ((rc = vkd3d_mutex_lock(&allocator->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return false;
}
for (i = 0, found = false; i < allocator->allocation_count; ++i)
{
if (allocator->allocations[i].base != base)
continue;
memmove(&allocator->allocations[i], &allocator->allocations[i + 1],
(--allocator->allocation_count - i) * sizeof(allocator->allocations[0]));
found = true;
break;
}
vkd3d_mutex_unlock(&allocator->mutex);
return found;
}
static inline const struct vkd3d_gpu_descriptor_allocation *vkd3d_gpu_descriptor_allocator_allocation_from_descriptor(
const struct vkd3d_gpu_descriptor_allocator *allocator, const struct d3d12_desc *desc)
{
const struct vkd3d_gpu_descriptor_allocation *allocation;
allocation = vkd3d_gpu_descriptor_allocator_binary_search(allocator, desc);
return (desc >= allocation->base && desc - allocation->base < allocation->count) ? allocation : NULL;
}
/* Return the available size from the specified descriptor to the heap end. */
size_t vkd3d_gpu_descriptor_allocator_range_size_from_descriptor(
struct vkd3d_gpu_descriptor_allocator *allocator, const struct d3d12_desc *desc)
{
const struct vkd3d_gpu_descriptor_allocation *allocation;
size_t remaining;
int rc;
assert(allocator->allocation_count);
if ((rc = vkd3d_mutex_lock(&allocator->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return 0;
}
remaining = 0;
if ((allocation = vkd3d_gpu_descriptor_allocator_allocation_from_descriptor(allocator, desc)))
remaining = allocation->count - (desc - allocation->base);
vkd3d_mutex_unlock(&allocator->mutex);
return remaining;
}
struct d3d12_descriptor_heap *vkd3d_gpu_descriptor_allocator_heap_from_descriptor(
struct vkd3d_gpu_descriptor_allocator *allocator, const struct d3d12_desc *desc)
{
const struct vkd3d_gpu_descriptor_allocation *allocation;
int rc;
if (!allocator->allocation_count)
return NULL;
if ((rc = vkd3d_mutex_lock(&allocator->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return NULL;
}
allocation = vkd3d_gpu_descriptor_allocator_allocation_from_descriptor(allocator, desc);
vkd3d_mutex_unlock(&allocator->mutex);
return allocation ? CONTAINING_RECORD(allocation->base, struct d3d12_descriptor_heap, descriptors)
: NULL;
}
static bool vkd3d_gpu_descriptor_allocator_init(struct vkd3d_gpu_descriptor_allocator *allocator)
{
int rc;
memset(allocator, 0, sizeof(*allocator));
if ((rc = vkd3d_mutex_init(&allocator->mutex)))
{
ERR("Failed to initialise mutex, error %d.\n", rc);
return false;
}
return true;
}
static void vkd3d_gpu_descriptor_allocator_cleanup(struct vkd3d_gpu_descriptor_allocator *allocator)
{
vkd3d_free(allocator->allocations);
vkd3d_mutex_destroy(&allocator->mutex);
}
static bool have_vk_time_domain(VkTimeDomainEXT *domains, unsigned int count, VkTimeDomainEXT domain)
{
unsigned int i;
@ -2664,6 +2462,8 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device *iface)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
vkd3d_mutex_destroy(&device->blocked_queues_mutex);
vkd3d_private_store_destroy(&device->private_store);
vkd3d_cleanup_format_info(device);
@ -2671,7 +2471,6 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device *iface)
vkd3d_uav_clear_state_cleanup(&device->uav_clear_state, device);
vkd3d_destroy_null_resources(&device->null_resources, device);
vkd3d_gpu_va_allocator_cleanup(&device->gpu_va_allocator);
vkd3d_gpu_descriptor_allocator_cleanup(&device->gpu_descriptor_allocator);
vkd3d_render_pass_cache_cleanup(&device->render_pass_cache, device);
d3d12_device_destroy_pipeline_cache(device);
d3d12_device_destroy_vkd3d_queues(device);
@ -3594,7 +3393,7 @@ static void d3d12_desc_buffered_copy_atomic(struct d3d12_desc *dst, const struct
mutex = d3d12_device_get_descriptor_mutex(device, src);
vkd3d_mutex_lock(mutex);
if (src->magic == VKD3D_DESCRIPTOR_MAGIC_FREE)
if (src->s.magic == VKD3D_DESCRIPTOR_MAGIC_FREE)
{
/* Source must be unlocked first, and therefore can't be used as a null source. */
static const struct d3d12_desc null = {0};
@ -3603,18 +3402,18 @@ static void d3d12_desc_buffered_copy_atomic(struct d3d12_desc *dst, const struct
return;
}
set = vkd3d_vk_descriptor_set_index_from_vk_descriptor_type(src->vk_descriptor_type);
set = vkd3d_vk_descriptor_set_index_from_vk_descriptor_type(src->s.vk_descriptor_type);
location = &locations[set][infos[set].count++];
location->src = *src;
location->src.s = src->s;
if (location->src.magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW)
vkd3d_view_incref(location->src.u.view_info.view);
if (location->src.s.magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW)
vkd3d_view_incref(location->src.s.u.view_info.view);
vkd3d_mutex_unlock(mutex);
infos[set].uav_counter |= (location->src.magic == VKD3D_DESCRIPTOR_MAGIC_UAV)
&& !!location->src.u.view_info.view->vk_counter_view;
infos[set].uav_counter |= (location->src.s.magic == VKD3D_DESCRIPTOR_MAGIC_UAV)
&& !!location->src.s.u.view_info.view->vk_counter_view;
location->dst = dst;
if (infos[set].count == ARRAY_SIZE(locations[0]))
@ -3643,8 +3442,7 @@ static void d3d12_device_vk_heaps_copy_descriptors(struct d3d12_device *device,
unsigned int dst_range_size, src_range_size;
struct d3d12_desc *dst;
descriptor_heap = vkd3d_gpu_descriptor_allocator_heap_from_descriptor(&device->gpu_descriptor_allocator,
d3d12_desc_from_cpu_handle(dst_descriptor_range_offsets[0]));
descriptor_heap = d3d12_desc_get_descriptor_heap(d3d12_desc_from_cpu_handle(dst_descriptor_range_offsets[0]));
heap_base = (const struct d3d12_desc *)descriptor_heap->descriptors;
heap_end = heap_base + descriptor_heap->desc.NumDescriptors;
@ -3662,8 +3460,7 @@ static void d3d12_device_vk_heaps_copy_descriptors(struct d3d12_device *device,
if (dst < heap_base || dst >= heap_end)
{
flush_desc_writes(locations, infos, descriptor_heap, device);
descriptor_heap = vkd3d_gpu_descriptor_allocator_heap_from_descriptor(&device->gpu_descriptor_allocator,
dst);
descriptor_heap = d3d12_desc_get_descriptor_heap(dst);
heap_base = (const struct d3d12_desc *)descriptor_heap->descriptors;
heap_end = heap_base + descriptor_heap->desc.NumDescriptors;
}
@ -3674,8 +3471,8 @@ static void d3d12_device_vk_heaps_copy_descriptors(struct d3d12_device *device,
* mutex is only intended to prevent use-after-free of the vkd3d_view caused by a
* race condition in the calling app. It is unnecessary to protect this test as it's
* the app's race condition, not ours. */
if (dst[dst_idx].magic == src[src_idx].magic && (dst[dst_idx].magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW)
&& dst[dst_idx].u.view_info.written_serial_id == src[src_idx].u.view_info.view->serial_id)
if (dst[dst_idx].s.magic == src[src_idx].s.magic && (dst[dst_idx].s.magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW)
&& dst[dst_idx].s.u.view_info.written_serial_id == src[src_idx].s.u.view_info.view->serial_id)
continue;
d3d12_desc_buffered_copy_atomic(&dst[dst_idx], &src[src_idx], locations, infos, descriptor_heap, device);
}
@ -3917,7 +3714,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource(ID3D12Devi
struct d3d12_resource *object;
HRESULT hr;
TRACE("iface %p, heap_properties %p, heap_flags %#x, desc %p, initial_state %#x, "
TRACE("iface %p, heap_properties %p, heap_flags %#x, desc %p, initial_state %#x, "
"optimized_clear_value %p, iid %s, resource %p.\n",
iface, heap_properties, heap_flags, desc, initial_state,
optimized_clear_value, debugstr_guid(iid), resource);
@ -4320,11 +4117,11 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
goto out_cleanup_uav_clear_state;
vkd3d_render_pass_cache_init(&device->render_pass_cache);
vkd3d_gpu_descriptor_allocator_init(&device->gpu_descriptor_allocator);
vkd3d_gpu_va_allocator_init(&device->gpu_va_allocator);
vkd3d_time_domains_init(device);
device->blocked_queue_count = 0;
vkd3d_mutex_init(&device->blocked_queues_mutex);
for (i = 0; i < ARRAY_SIZE(device->desc_mutex); ++i)
vkd3d_mutex_init(&device->desc_mutex[i]);

View file

@ -443,15 +443,8 @@ static HRESULT d3d12_heap_map(struct d3d12_heap *heap, uint64_t offset,
struct d3d12_device *device = heap->device;
HRESULT hr = S_OK;
VkResult vr;
int rc;
if ((rc = vkd3d_mutex_lock(&heap->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
if (data)
*data = NULL;
return hresult_from_errno(rc);
}
vkd3d_mutex_lock(&heap->mutex);
assert(!resource->map_count || heap->map_ptr);
@ -501,13 +494,8 @@ static HRESULT d3d12_heap_map(struct d3d12_heap *heap, uint64_t offset,
static void d3d12_heap_unmap(struct d3d12_heap *heap, struct d3d12_resource *resource)
{
struct d3d12_device *device = heap->device;
int rc;
if ((rc = vkd3d_mutex_lock(&heap->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return;
}
vkd3d_mutex_lock(&heap->mutex);
if (!resource->map_count)
{
@ -570,7 +558,6 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap,
VkMemoryRequirements memory_requirements;
VkDeviceSize vk_memory_size;
HRESULT hr;
int rc;
heap->ID3D12Heap_iface.lpVtbl = &d3d12_heap_vtbl;
heap->refcount = 1;
@ -596,11 +583,7 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap,
if (FAILED(hr = validate_heap_desc(&heap->desc, resource)))
return hr;
if ((rc = vkd3d_mutex_init(&heap->mutex)))
{
ERR("Failed to initialize mutex, error %d.\n", rc);
return hresult_from_errno(rc);
}
vkd3d_mutex_init(&heap->mutex);
if (FAILED(hr = vkd3d_private_store_init(&heap->private_store)))
{
@ -2137,14 +2120,14 @@ static void d3d12_descriptor_heap_write_vk_descriptor_range(struct d3d12_descrip
{
unsigned int i, info_index = 0, write_index = 0;
switch (locations[0].src.vk_descriptor_type)
switch (locations[0].src.s.vk_descriptor_type)
{
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
for (; write_index < write_count; ++write_index)
{
descriptor_set->vk_descriptor_writes[write_index].pBufferInfo = &descriptor_set->vk_buffer_infos[info_index];
for (i = 0; i < descriptor_set->vk_descriptor_writes[write_index].descriptorCount; ++i, ++info_index)
descriptor_set->vk_buffer_infos[info_index] = locations[info_index].src.u.vk_cbv_info;
descriptor_set->vk_buffer_infos[info_index] = locations[info_index].src.s.u.vk_cbv_info;
}
break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
@ -2153,7 +2136,7 @@ static void d3d12_descriptor_heap_write_vk_descriptor_range(struct d3d12_descrip
{
descriptor_set->vk_descriptor_writes[write_index].pImageInfo = &descriptor_set->vk_image_infos[info_index];
for (i = 0; i < descriptor_set->vk_descriptor_writes[write_index].descriptorCount; ++i, ++info_index)
descriptor_set->vk_image_infos[info_index].imageView = locations[info_index].src.u.view_info.view->u.vk_image_view;
descriptor_set->vk_image_infos[info_index].imageView = locations[info_index].src.s.u.view_info.view->u.vk_image_view;
}
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
@ -2162,7 +2145,7 @@ static void d3d12_descriptor_heap_write_vk_descriptor_range(struct d3d12_descrip
{
descriptor_set->vk_descriptor_writes[write_index].pTexelBufferView = &descriptor_set->vk_buffer_views[info_index];
for (i = 0; i < descriptor_set->vk_descriptor_writes[write_index].descriptorCount; ++i, ++info_index)
descriptor_set->vk_buffer_views[info_index] = locations[info_index].src.u.view_info.view->u.vk_buffer_view;
descriptor_set->vk_buffer_views[info_index] = locations[info_index].src.s.u.view_info.view->u.vk_buffer_view;
}
break;
case VK_DESCRIPTOR_TYPE_SAMPLER:
@ -2170,11 +2153,11 @@ static void d3d12_descriptor_heap_write_vk_descriptor_range(struct d3d12_descrip
{
descriptor_set->vk_descriptor_writes[write_index].pImageInfo = &descriptor_set->vk_image_infos[info_index];
for (i = 0; i < descriptor_set->vk_descriptor_writes[write_index].descriptorCount; ++i, ++info_index)
descriptor_set->vk_image_infos[info_index].sampler = locations[info_index].src.u.view_info.view->u.vk_sampler;
descriptor_set->vk_image_infos[info_index].sampler = locations[info_index].src.s.u.view_info.view->u.vk_sampler;
}
break;
default:
ERR("Unhandled descriptor type %#x.\n", locations[0].src.vk_descriptor_type);
ERR("Unhandled descriptor type %#x.\n", locations[0].src.s.vk_descriptor_type);
break;
}
}
@ -2230,36 +2213,35 @@ static void d3d12_desc_write_vk_heap(const struct d3d12_desc *dst, const struct
const struct vkd3d_vk_device_procs *vk_procs;
bool is_null = false;
descriptor_heap = vkd3d_gpu_descriptor_allocator_heap_from_descriptor(&device->gpu_descriptor_allocator, dst);
descriptor_heap = d3d12_desc_get_descriptor_heap(dst);
descriptor_set = &descriptor_heap->vk_descriptor_sets[vkd3d_vk_descriptor_set_index_from_vk_descriptor_type(
src->vk_descriptor_type)];
src->s.vk_descriptor_type)];
vk_procs = &device->vk_procs;
vkd3d_mutex_lock(&descriptor_heap->vk_sets_mutex);
descriptor_set->vk_descriptor_writes[0].dstArrayElement = dst
- (const struct d3d12_desc *)descriptor_heap->descriptors;
descriptor_set->vk_descriptor_writes[0].dstArrayElement = dst->index;
descriptor_set->vk_descriptor_writes[0].descriptorCount = 1;
switch (src->vk_descriptor_type)
switch (src->s.vk_descriptor_type)
{
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
descriptor_set->vk_descriptor_writes[0].pBufferInfo = &src->u.vk_cbv_info;
is_null = !src->u.vk_cbv_info.buffer;
descriptor_set->vk_descriptor_writes[0].pBufferInfo = &src->s.u.vk_cbv_info;
is_null = !src->s.u.vk_cbv_info.buffer;
break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
is_null = !(descriptor_set->vk_image_infos[0].imageView = src->u.view_info.view->u.vk_image_view);
is_null = !(descriptor_set->vk_image_infos[0].imageView = src->s.u.view_info.view->u.vk_image_view);
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
descriptor_set->vk_descriptor_writes[0].pTexelBufferView = &src->u.view_info.view->u.vk_buffer_view;
is_null = !src->u.view_info.view->u.vk_buffer_view;
descriptor_set->vk_descriptor_writes[0].pTexelBufferView = &src->s.u.view_info.view->u.vk_buffer_view;
is_null = !src->s.u.view_info.view->u.vk_buffer_view;
break;
case VK_DESCRIPTOR_TYPE_SAMPLER:
descriptor_set->vk_image_infos[0].sampler = src->u.view_info.view->u.vk_sampler;
descriptor_set->vk_image_infos[0].sampler = src->s.u.view_info.view->u.vk_sampler;
break;
default:
ERR("Unhandled descriptor type %#x.\n", src->vk_descriptor_type);
ERR("Unhandled descriptor type %#x.\n", src->s.vk_descriptor_type);
break;
}
if (is_null && device->vk_info.EXT_robustness2)
@ -2272,13 +2254,12 @@ static void d3d12_desc_write_vk_heap(const struct d3d12_desc *dst, const struct
VK_CALL(vkUpdateDescriptorSets(device->vk_device, 1, descriptor_set->vk_descriptor_writes, 0, NULL));
if (src->magic == VKD3D_DESCRIPTOR_MAGIC_UAV && src->u.view_info.view->vk_counter_view)
if (src->s.magic == VKD3D_DESCRIPTOR_MAGIC_UAV && src->s.u.view_info.view->vk_counter_view)
{
descriptor_set = &descriptor_heap->vk_descriptor_sets[VKD3D_SET_INDEX_UAV_COUNTER];
descriptor_set->vk_descriptor_writes[0].dstArrayElement = dst
- (const struct d3d12_desc *)descriptor_heap->descriptors;
descriptor_set->vk_descriptor_writes[0].dstArrayElement = dst->index;
descriptor_set->vk_descriptor_writes[0].descriptorCount = 1;
descriptor_set->vk_descriptor_writes[0].pTexelBufferView = &src->u.view_info.view->vk_counter_view;
descriptor_set->vk_descriptor_writes[0].pTexelBufferView = &src->s.u.view_info.view->vk_counter_view;
VK_CALL(vkUpdateDescriptorSets(device->vk_device, 1, descriptor_set->vk_descriptor_writes, 0, NULL));
}
@ -2293,15 +2274,15 @@ static void d3d12_desc_write_atomic_d3d12_only(struct d3d12_desc *dst, const str
mutex = d3d12_device_get_descriptor_mutex(device, dst);
vkd3d_mutex_lock(mutex);
if (!(dst->magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW) || InterlockedDecrement(&dst->u.view_info.view->refcount))
if (!(dst->s.magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW) || InterlockedDecrement(&dst->s.u.view_info.view->refcount))
{
*dst = *src;
d3d12_desc_copy_raw(dst, src);
vkd3d_mutex_unlock(mutex);
return;
}
defunct_view = dst->u.view_info.view;
*dst = *src;
defunct_view = dst->s.u.view_info.view;
d3d12_desc_copy_raw(dst, src);
vkd3d_mutex_unlock(mutex);
/* Destroy the view after unlocking to reduce wait time. */
@ -2318,11 +2299,11 @@ void d3d12_desc_write_atomic(struct d3d12_desc *dst, const struct d3d12_desc *sr
vkd3d_mutex_lock(mutex);
/* Nothing to do for VKD3D_DESCRIPTOR_MAGIC_CBV. */
if ((dst->magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW)
&& !InterlockedDecrement(&dst->u.view_info.view->refcount))
defunct_view = dst->u.view_info.view;
if ((dst->s.magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW)
&& !InterlockedDecrement(&dst->s.u.view_info.view->refcount))
defunct_view = dst->s.u.view_info.view;
*dst = *src;
d3d12_desc_copy_raw(dst, src);
vkd3d_mutex_unlock(mutex);
@ -2330,7 +2311,7 @@ void d3d12_desc_write_atomic(struct d3d12_desc *dst, const struct d3d12_desc *sr
if (defunct_view)
vkd3d_view_destroy(defunct_view, device);
if (device->use_vk_heaps && dst->magic)
if (device->use_vk_heaps && dst->s.magic)
d3d12_desc_write_vk_heap(dst, src, device);
}
@ -2360,6 +2341,7 @@ void d3d12_desc_copy_vk_heap_range(struct d3d12_desc_copy_location *locations, c
++descriptor_set->vk_descriptor_writes[write_count - 1].descriptorCount;
continue;
}
/* Accessing dst->index will be slow if a cache miss occurs, so calculate instead. */
descriptor_set->vk_descriptor_writes[write_count].dstArrayElement = locations[i].dst
- (const struct d3d12_desc *)descriptor_heap->descriptors;
descriptor_set->vk_descriptor_writes[write_count++].descriptorCount = 1;
@ -2377,10 +2359,11 @@ void d3d12_desc_copy_vk_heap_range(struct d3d12_desc_copy_location *locations, c
for (i = 0, write_count = 0; i < info->count; ++i)
{
if (!locations[i].src.u.view_info.view->vk_counter_view)
if (!locations[i].src.s.u.view_info.view->vk_counter_view)
continue;
descriptor_set->vk_buffer_views[write_count] = locations[i].src.u.view_info.view->vk_counter_view;
descriptor_set->vk_buffer_views[write_count] = locations[i].src.s.u.view_info.view->vk_counter_view;
descriptor_set->vk_descriptor_writes[write_count].pTexelBufferView = &descriptor_set->vk_buffer_views[write_count];
/* Accessing dst->index will be slow if a cache miss occurs, so calculate instead. */
descriptor_set->vk_descriptor_writes[write_count].dstArrayElement = locations[i].dst
- (const struct d3d12_desc *)descriptor_heap->descriptors;
descriptor_set->vk_descriptor_writes[write_count++].descriptorCount = 1;
@ -2404,10 +2387,10 @@ void d3d12_desc_copy(struct d3d12_desc *dst, const struct d3d12_desc *src,
mutex = d3d12_device_get_descriptor_mutex(device, src);
vkd3d_mutex_lock(mutex);
if (src->magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW)
vkd3d_view_incref(src->u.view_info.view);
if (src->s.magic & VKD3D_DESCRIPTOR_MAGIC_HAS_VIEW)
vkd3d_view_incref(src->s.u.view_info.view);
tmp = *src;
d3d12_desc_copy_raw(&tmp, src);
vkd3d_mutex_unlock(mutex);
@ -2825,7 +2808,7 @@ void d3d12_desc_create_cbv(struct d3d12_desc *descriptor,
return;
}
buffer_info = &descriptor->u.vk_cbv_info;
buffer_info = &descriptor->s.u.vk_cbv_info;
if (desc->BufferLocation)
{
resource = vkd3d_gpu_va_allocator_dereference(&device->gpu_va_allocator, desc->BufferLocation);
@ -2841,8 +2824,8 @@ void d3d12_desc_create_cbv(struct d3d12_desc *descriptor,
buffer_info->range = VK_WHOLE_SIZE;
}
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_CBV;
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptor->s.magic = VKD3D_DESCRIPTOR_MAGIC_CBV;
descriptor->s.vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
}
static unsigned int vkd3d_view_flags_from_d3d12_buffer_srv_flags(D3D12_BUFFER_SRV_FLAGS flags)
@ -2878,10 +2861,10 @@ static void vkd3d_create_null_srv(struct d3d12_desc *descriptor,
vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false),
0, VKD3D_NULL_BUFFER_SIZE, &view))
{
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
descriptor->u.view_info.view = view;
descriptor->u.view_info.written_serial_id = view->serial_id;
descriptor->s.magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
descriptor->s.vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
descriptor->s.u.view_info.view = view;
descriptor->s.u.view_info.written_serial_id = view->serial_id;
}
return;
@ -2914,6 +2897,7 @@ static void vkd3d_create_null_srv(struct d3d12_desc *descriptor,
vkd3d_desc.miplevel_count = 1;
vkd3d_desc.layer_idx = 0;
vkd3d_desc.layer_count = 1;
vkd3d_desc.vk_image_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
vkd3d_desc.components.r = VK_COMPONENT_SWIZZLE_ZERO;
vkd3d_desc.components.g = VK_COMPONENT_SWIZZLE_ZERO;
vkd3d_desc.components.b = VK_COMPONENT_SWIZZLE_ZERO;
@ -2923,10 +2907,10 @@ static void vkd3d_create_null_srv(struct d3d12_desc *descriptor,
if (!vkd3d_create_texture_view(device, vk_image, &vkd3d_desc, &view))
return;
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
descriptor->u.view_info.view = view;
descriptor->u.view_info.written_serial_id = view->serial_id;
descriptor->s.magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
descriptor->s.vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
descriptor->s.u.view_info.view = view;
descriptor->s.u.view_info.written_serial_id = view->serial_id;
}
static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor,
@ -2954,10 +2938,10 @@ static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor,
desc->u.Buffer.StructureByteStride, flags, &view))
return;
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
descriptor->u.view_info.view = view;
descriptor->u.view_info.written_serial_id = view->serial_id;
descriptor->s.magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
descriptor->s.vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
descriptor->s.u.view_info.view = view;
descriptor->s.u.view_info.written_serial_id = view->serial_id;
}
static VkImageAspectFlags vk_image_aspect_flags_from_d3d12_plane_slice(const struct vkd3d_format *format,
@ -3085,10 +3069,10 @@ void d3d12_desc_create_srv(struct d3d12_desc *descriptor,
if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
return;
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
descriptor->u.view_info.view = view;
descriptor->u.view_info.written_serial_id = view->serial_id;
descriptor->s.magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
descriptor->s.vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
descriptor->s.u.view_info.view = view;
descriptor->s.u.view_info.written_serial_id = view->serial_id;
}
static unsigned int vkd3d_view_flags_from_d3d12_buffer_uav_flags(D3D12_BUFFER_UAV_FLAGS flags)
@ -3124,10 +3108,10 @@ static void vkd3d_create_null_uav(struct d3d12_desc *descriptor,
vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false),
0, VKD3D_NULL_BUFFER_SIZE, &view))
{
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
descriptor->u.view_info.view = view;
descriptor->u.view_info.written_serial_id = view->serial_id;
descriptor->s.magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
descriptor->s.vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
descriptor->s.u.view_info.view = view;
descriptor->s.u.view_info.written_serial_id = view->serial_id;
}
return;
@ -3169,10 +3153,10 @@ static void vkd3d_create_null_uav(struct d3d12_desc *descriptor,
if (!vkd3d_create_texture_view(device, vk_image, &vkd3d_desc, &view))
return;
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
descriptor->u.view_info.view = view;
descriptor->u.view_info.written_serial_id = view->serial_id;
descriptor->s.magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
descriptor->s.vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
descriptor->s.u.view_info.view = view;
descriptor->s.u.view_info.written_serial_id = view->serial_id;
}
static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_device *device,
@ -3200,10 +3184,10 @@ static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_
desc->u.Buffer.StructureByteStride, flags, &view))
return;
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
descriptor->u.view_info.view = view;
descriptor->u.view_info.written_serial_id = view->serial_id;
descriptor->s.magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
descriptor->s.vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
descriptor->s.u.view_info.view = view;
descriptor->s.u.view_info.written_serial_id = view->serial_id;
if (counter_resource)
{
@ -3276,10 +3260,10 @@ static void vkd3d_create_texture_uav(struct d3d12_desc *descriptor,
if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
return;
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
descriptor->u.view_info.view = view;
descriptor->u.view_info.written_serial_id = view->serial_id;
descriptor->s.magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
descriptor->s.vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
descriptor->s.u.view_info.view = view;
descriptor->s.u.view_info.written_serial_id = view->serial_id;
}
void d3d12_desc_create_uav(struct d3d12_desc *descriptor, struct d3d12_device *device,
@ -3439,10 +3423,10 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler,
return;
}
sampler->magic = VKD3D_DESCRIPTOR_MAGIC_SAMPLER;
sampler->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLER;
sampler->u.view_info.view = view;
sampler->u.view_info.written_serial_id = view->serial_id;
sampler->s.magic = VKD3D_DESCRIPTOR_MAGIC_SAMPLER;
sampler->s.vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLER;
sampler->s.u.view_info.view = view;
sampler->s.u.view_info.written_serial_id = view->serial_id;
}
HRESULT vkd3d_create_static_sampler(struct d3d12_device *device,
@ -3708,9 +3692,6 @@ static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_Release(ID3D12DescriptorHea
d3d12_desc_destroy(&descriptors[i], device);
}
if (device->vk_info.EXT_descriptor_indexing && !vkd3d_gpu_descriptor_allocator_unregister_range(
&device->gpu_descriptor_allocator, descriptors))
ERR("Failed to unregister descriptor range.\n");
break;
}
@ -4025,6 +4006,8 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device,
{
size_t max_descriptor_count, descriptor_size;
struct d3d12_descriptor_heap *object;
struct d3d12_desc *dst;
unsigned int i;
HRESULT hr;
if (!(descriptor_size = d3d12_device_get_descriptor_handle_increment_size(device, desc->Type)))
@ -4057,12 +4040,19 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device,
return hr;
}
memset(object->descriptors, 0, descriptor_size * desc->NumDescriptors);
if ((desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER)
&& device->vk_info.EXT_descriptor_indexing && !vkd3d_gpu_descriptor_allocator_register_range(
&device->gpu_descriptor_allocator, (struct d3d12_desc *)object->descriptors, desc->NumDescriptors))
ERR("Failed to register descriptor range.\n");
if (desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || desc->Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER)
{
dst = (struct d3d12_desc *)object->descriptors;
for (i = 0; i < desc->NumDescriptors; ++i)
{
memset(&dst[i].s, 0, sizeof(dst[i].s));
dst[i].index = i;
}
}
else
{
memset(object->descriptors, 0, descriptor_size * desc->NumDescriptors);
}
TRACE("Created descriptor heap %p.\n", object);

View file

@ -1689,14 +1689,8 @@ HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache,
bool found = false;
HRESULT hr = S_OK;
unsigned int i;
int rc;
if ((rc = vkd3d_mutex_lock(&device->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
*vk_render_pass = VK_NULL_HANDLE;
return hresult_from_errno(rc);
}
vkd3d_mutex_lock(&device->mutex);
for (i = 0; i < cache->render_pass_count; ++i)
{
@ -1964,8 +1958,9 @@ static HRESULT create_shader_stage(struct d3d12_device *device,
const struct vkd3d_shader_compile_option options[] =
{
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_6},
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_7},
{VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV, typed_uav_compile_option(device)},
{VKD3D_SHADER_COMPILE_OPTION_WRITE_TESS_GEOM_POINT_SIZE, 0},
};
stage_desc->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
@ -2016,7 +2011,7 @@ static int vkd3d_scan_dxbc(const struct d3d12_device *device, const D3D12_SHADER
const struct vkd3d_shader_compile_option options[] =
{
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_6},
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_7},
{VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV, typed_uav_compile_option(device)},
};
@ -3370,28 +3365,23 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(const struct d3d12
struct d3d12_device *device = state->device;
VkPipeline vk_pipeline = VK_NULL_HANDLE;
struct vkd3d_compiled_pipeline *current;
int rc;
*vk_render_pass = VK_NULL_HANDLE;
if (!(rc = vkd3d_mutex_lock(&device->mutex)))
vkd3d_mutex_lock(&device->mutex);
LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry)
{
LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry)
if (!memcmp(&current->key, key, sizeof(*key)))
{
if (!memcmp(&current->key, key, sizeof(*key)))
{
vk_pipeline = current->vk_pipeline;
*vk_render_pass = current->vk_render_pass;
break;
}
vk_pipeline = current->vk_pipeline;
*vk_render_pass = current->vk_render_pass;
break;
}
vkd3d_mutex_unlock(&device->mutex);
}
else
{
ERR("Failed to lock mutex, error %d.\n", rc);
}
vkd3d_mutex_unlock(&device->mutex);
return vk_pipeline;
}
@ -3401,7 +3391,6 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta
struct d3d12_graphics_pipeline_state *graphics = &state->u.graphics;
struct vkd3d_compiled_pipeline *compiled_pipeline, *current;
struct d3d12_device *device = state->device;
int rc;
if (!(compiled_pipeline = vkd3d_malloc(sizeof(*compiled_pipeline))))
return false;
@ -3410,12 +3399,7 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta
compiled_pipeline->vk_pipeline = vk_pipeline;
compiled_pipeline->vk_render_pass = vk_render_pass;
if ((rc = vkd3d_mutex_lock(&device->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
vkd3d_free(compiled_pipeline);
return false;
}
vkd3d_mutex_lock(&device->mutex);
LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry)
{

View file

@ -948,16 +948,11 @@ HRESULT vkd3d_get_private_data(struct vkd3d_private_store *store,
const struct vkd3d_private_data *data;
HRESULT hr = S_OK;
unsigned int size;
int rc;
if (!out_size)
return E_INVALIDARG;
if ((rc = vkd3d_mutex_lock(&store->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return hresult_from_errno(rc);
}
vkd3d_mutex_lock(&store->mutex);
if (!(data = vkd3d_private_store_get_private_data(store, tag)))
{
@ -990,13 +985,8 @@ HRESULT vkd3d_set_private_data(struct vkd3d_private_store *store,
const GUID *tag, unsigned int data_size, const void *data)
{
HRESULT hr;
int rc;
if ((rc = vkd3d_mutex_lock(&store->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return hresult_from_errno(rc);
}
vkd3d_mutex_lock(&store->mutex);
hr = vkd3d_private_store_set_private_data(store, tag, data, data_size, false);
@ -1009,13 +999,8 @@ HRESULT vkd3d_set_private_data_interface(struct vkd3d_private_store *store,
{
const void *data = object ? object : (void *)&object;
HRESULT hr;
int rc;
if ((rc = vkd3d_mutex_lock(&store->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return hresult_from_errno(rc);
}
vkd3d_mutex_lock(&store->mutex);
hr = vkd3d_private_store_set_private_data(store, tag, data, sizeof(object), !!object);

View file

@ -207,56 +207,49 @@ struct vkd3d_cond
CONDITION_VARIABLE cond;
};
static inline int vkd3d_mutex_init(struct vkd3d_mutex *lock)
static inline void vkd3d_mutex_init(struct vkd3d_mutex *lock)
{
InitializeCriticalSection(&lock->lock);
return 0;
}
static inline int vkd3d_mutex_lock(struct vkd3d_mutex *lock)
static inline void vkd3d_mutex_lock(struct vkd3d_mutex *lock)
{
EnterCriticalSection(&lock->lock);
return 0;
}
static inline int vkd3d_mutex_unlock(struct vkd3d_mutex *lock)
static inline void vkd3d_mutex_unlock(struct vkd3d_mutex *lock)
{
LeaveCriticalSection(&lock->lock);
return 0;
}
static inline int vkd3d_mutex_destroy(struct vkd3d_mutex *lock)
static inline void vkd3d_mutex_destroy(struct vkd3d_mutex *lock)
{
DeleteCriticalSection(&lock->lock);
return 0;
}
static inline int vkd3d_cond_init(struct vkd3d_cond *cond)
static inline void vkd3d_cond_init(struct vkd3d_cond *cond)
{
InitializeConditionVariable(&cond->cond);
return 0;
}
static inline int vkd3d_cond_signal(struct vkd3d_cond *cond)
static inline void vkd3d_cond_signal(struct vkd3d_cond *cond)
{
WakeConditionVariable(&cond->cond);
return 0;
}
static inline int vkd3d_cond_broadcast(struct vkd3d_cond *cond)
static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond)
{
WakeAllConditionVariable(&cond->cond);
return 0;
}
static inline int vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock)
static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock)
{
return !SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE);
if (!SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE))
ERR("Could not sleep on the condition variable, error %u.\n", GetLastError());
}
static inline int vkd3d_cond_destroy(struct vkd3d_cond *cond)
static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond)
{
return 0;
}
#else /* _WIN32 */
@ -280,49 +273,85 @@ struct vkd3d_cond
};
static inline int vkd3d_mutex_init(struct vkd3d_mutex *lock)
static inline void vkd3d_mutex_init(struct vkd3d_mutex *lock)
{
return pthread_mutex_init(&lock->lock, NULL);
int ret;
ret = pthread_mutex_init(&lock->lock, NULL);
if (ret)
ERR("Could not initialize the mutex, error %d.\n", ret);
}
static inline int vkd3d_mutex_lock(struct vkd3d_mutex *lock)
static inline void vkd3d_mutex_lock(struct vkd3d_mutex *lock)
{
return pthread_mutex_lock(&lock->lock);
int ret;
ret = pthread_mutex_lock(&lock->lock);
if (ret)
ERR("Could not lock the mutex, error %d.\n", ret);
}
static inline int vkd3d_mutex_unlock(struct vkd3d_mutex *lock)
static inline void vkd3d_mutex_unlock(struct vkd3d_mutex *lock)
{
return pthread_mutex_unlock(&lock->lock);
int ret;
ret = pthread_mutex_unlock(&lock->lock);
if (ret)
ERR("Could not unlock the mutex, error %d.\n", ret);
}
static inline int vkd3d_mutex_destroy(struct vkd3d_mutex *lock)
static inline void vkd3d_mutex_destroy(struct vkd3d_mutex *lock)
{
return pthread_mutex_destroy(&lock->lock);
int ret;
ret = pthread_mutex_destroy(&lock->lock);
if (ret)
ERR("Could not destroy the mutex, error %d.\n", ret);
}
static inline int vkd3d_cond_init(struct vkd3d_cond *cond)
static inline void vkd3d_cond_init(struct vkd3d_cond *cond)
{
return pthread_cond_init(&cond->cond, NULL);
int ret;
ret = pthread_cond_init(&cond->cond, NULL);
if (ret)
ERR("Could not initialize the condition variable, error %d.\n", ret);
}
static inline int vkd3d_cond_signal(struct vkd3d_cond *cond)
static inline void vkd3d_cond_signal(struct vkd3d_cond *cond)
{
return pthread_cond_signal(&cond->cond);
int ret;
ret = pthread_cond_signal(&cond->cond);
if (ret)
ERR("Could not signal the condition variable, error %d.\n", ret);
}
static inline int vkd3d_cond_broadcast(struct vkd3d_cond *cond)
static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond)
{
return pthread_cond_broadcast(&cond->cond);
int ret;
ret = pthread_cond_broadcast(&cond->cond);
if (ret)
ERR("Could not broadcast the condition variable, error %d.\n", ret);
}
static inline int vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock)
static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock)
{
return pthread_cond_wait(&cond->cond, &lock->lock);
int ret;
ret = pthread_cond_wait(&cond->cond, &lock->lock);
if (ret)
ERR("Could not wait on the condition variable, error %d.\n", ret);
}
static inline int vkd3d_cond_destroy(struct vkd3d_cond *cond)
static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond)
{
return pthread_cond_destroy(&cond->cond);
int ret;
ret = pthread_cond_destroy(&cond->cond);
if (ret)
ERR("Could not destroy the condition variable, error %d.\n", ret);
}
#endif /* _WIN32 */
@ -391,30 +420,6 @@ D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate(struct vkd3d_gpu_va_al
void *vkd3d_gpu_va_allocator_dereference(struct vkd3d_gpu_va_allocator *allocator, D3D12_GPU_VIRTUAL_ADDRESS address);
void vkd3d_gpu_va_allocator_free(struct vkd3d_gpu_va_allocator *allocator, D3D12_GPU_VIRTUAL_ADDRESS address);
struct vkd3d_gpu_descriptor_allocation
{
const struct d3d12_desc *base;
size_t count;
};
struct vkd3d_gpu_descriptor_allocator
{
struct vkd3d_mutex mutex;
struct vkd3d_gpu_descriptor_allocation *allocations;
size_t allocations_size;
size_t allocation_count;
};
size_t vkd3d_gpu_descriptor_allocator_range_size_from_descriptor(
struct vkd3d_gpu_descriptor_allocator *allocator, const struct d3d12_desc *desc);
bool vkd3d_gpu_descriptor_allocator_register_range(struct vkd3d_gpu_descriptor_allocator *allocator,
const struct d3d12_desc *base, size_t count);
bool vkd3d_gpu_descriptor_allocator_unregister_range(
struct vkd3d_gpu_descriptor_allocator *allocator, const struct d3d12_desc *base);
struct d3d12_descriptor_heap *vkd3d_gpu_descriptor_allocator_heap_from_descriptor(
struct vkd3d_gpu_descriptor_allocator *allocator, const struct d3d12_desc *desc);
struct vkd3d_render_pass_key
{
unsigned int attachment_count;
@ -471,14 +476,11 @@ static inline void vkd3d_private_data_destroy(struct vkd3d_private_data *data)
static inline HRESULT vkd3d_private_store_init(struct vkd3d_private_store *store)
{
int rc;
list_init(&store->content);
if ((rc = vkd3d_mutex_init(&store->mutex)))
ERR("Failed to initialize mutex, error %d.\n", rc);
vkd3d_mutex_init(&store->mutex);
return hresult_from_errno(rc);
return S_OK;
}
static inline void vkd3d_private_store_destroy(struct vkd3d_private_store *store)
@ -718,13 +720,17 @@ struct vkd3d_view_info
struct d3d12_desc
{
uint32_t magic;
VkDescriptorType vk_descriptor_type;
union
struct
{
VkDescriptorBufferInfo vk_cbv_info;
struct vkd3d_view_info view_info;
} u;
uint32_t magic;
VkDescriptorType vk_descriptor_type;
union
{
VkDescriptorBufferInfo vk_cbv_info;
struct vkd3d_view_info view_info;
} u;
} s;
unsigned int index;
};
static inline struct d3d12_desc *d3d12_desc_from_cpu_handle(D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle)
@ -737,6 +743,11 @@ static inline struct d3d12_desc *d3d12_desc_from_gpu_handle(D3D12_GPU_DESCRIPTOR
return (struct d3d12_desc *)(intptr_t)gpu_handle.ptr;
}
static inline void d3d12_desc_copy_raw(struct d3d12_desc *dst, const struct d3d12_desc *src)
{
dst->s = src->s;
}
void d3d12_desc_copy(struct d3d12_desc *dst, const struct d3d12_desc *src, struct d3d12_device *device);
void d3d12_desc_create_cbv(struct d3d12_desc *descriptor,
struct d3d12_device *device, const D3D12_CONSTANT_BUFFER_VIEW_DESC *desc);
@ -857,6 +868,17 @@ struct d3d12_descriptor_heap
BYTE descriptors[];
};
static inline struct d3d12_descriptor_heap *d3d12_desc_get_descriptor_heap(const struct d3d12_desc *descriptor)
{
return CONTAINING_RECORD(descriptor - descriptor->index, struct d3d12_descriptor_heap, descriptors);
}
static inline unsigned int d3d12_desc_heap_range_size(const struct d3d12_desc *descriptor)
{
const struct d3d12_descriptor_heap *heap = d3d12_desc_get_descriptor_heap(descriptor);
return heap->desc.NumDescriptors - descriptor->index;
}
HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device,
const D3D12_DESCRIPTOR_HEAP_DESC *desc, struct d3d12_descriptor_heap **descriptor_heap);
@ -1348,6 +1370,13 @@ struct vkd3d_cs_op_data
} u;
};
struct d3d12_command_queue_op_array
{
struct vkd3d_cs_op_data *ops;
size_t count;
size_t size;
};
/* ID3D12CommandQueue */
struct d3d12_command_queue
{
@ -1365,11 +1394,16 @@ struct d3d12_command_queue
struct d3d12_device *device;
struct vkd3d_mutex op_mutex;
struct vkd3d_cs_op_data *ops;
size_t ops_count;
size_t ops_size;
/* These fields are protected by op_mutex. */
struct d3d12_command_queue_op_array op_queue;
bool is_flushing;
/* This field is not protected by op_mutex, but can only be used
* by the thread that set is_flushing; when is_flushing is not
* set, aux_op_queue.count must be zero. */
struct d3d12_command_queue_op_array aux_op_queue;
struct vkd3d_private_store private_store;
};
@ -1465,7 +1499,6 @@ struct d3d12_device
PFN_vkd3d_signal_event signal_event;
size_t wchar_size;
struct vkd3d_gpu_descriptor_allocator gpu_descriptor_allocator;
struct vkd3d_gpu_va_allocator gpu_va_allocator;
struct vkd3d_mutex mutex;
@ -1491,6 +1524,7 @@ struct d3d12_device
unsigned int queue_family_count;
VkTimeDomainEXT vk_host_time_domain;
struct vkd3d_mutex blocked_queues_mutex;
struct d3d12_command_queue *blocked_queues[VKD3D_MAX_DEVICE_BLOCKED_QUEUES];
unsigned int blocked_queue_count;