vkd3d: Import upstream release 1.7.
This commit is contained in:
parent
3149d27220
commit
75ab843114
28 changed files with 4506 additions and 1807 deletions
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -8,6 +8,7 @@ Chip Davis
|
|||
Conor McCarthy
|
||||
David Gow
|
||||
Derek Lesho
|
||||
Fabian Maurer
|
||||
Francisco Casas
|
||||
Francois Gouget
|
||||
Giovanni Mascellani
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = §ions[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(§ion->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;
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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(¤t->key, key, sizeof(*key)))
|
||||
{
|
||||
if (!memcmp(¤t->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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue