mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
vkd3d-shader/d3dbc: Scan descriptors for constant register sets.
This commit is contained in:
parent
55c5129ad9
commit
d077562f79
Notes:
Alexandre Julliard
2023-07-17 23:26:26 +02:00
Approved-by: Henri Verbeet (@hverbeet) Approved-by: Alexandre Julliard (@julliard) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/273
@ -193,6 +193,21 @@ static inline int vkd3d_u32_compare(uint32_t x, uint32_t y)
|
||||
return (x > y) - (x < y);
|
||||
}
|
||||
|
||||
static inline bool bitmap_clear(uint32_t *map, unsigned int idx)
|
||||
{
|
||||
return map[idx >> 5] &= ~(1u << (idx & 0x1f));
|
||||
}
|
||||
|
||||
static inline bool bitmap_set(uint32_t *map, unsigned int idx)
|
||||
{
|
||||
return map[idx >> 5] |= (1u << (idx & 0x1f));
|
||||
}
|
||||
|
||||
static inline bool bitmap_is_set(const uint32_t *map, unsigned int idx)
|
||||
{
|
||||
return map[idx >> 5] & (1u << (idx & 0x1f));
|
||||
}
|
||||
|
||||
static inline int ascii_isupper(int c)
|
||||
{
|
||||
return 'A' <= c && c <= 'Z';
|
||||
|
@ -214,6 +214,9 @@ struct vkd3d_shader_sm1_parser
|
||||
bool abort;
|
||||
|
||||
struct vkd3d_shader_parser p;
|
||||
|
||||
#define MAX_CONSTANT_COUNT 8192
|
||||
uint32_t constant_def_mask[3][MAX_CONSTANT_COUNT / 32];
|
||||
};
|
||||
|
||||
/* This table is not order or position dependent. */
|
||||
@ -729,12 +732,60 @@ static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser *
|
||||
semantic->usage_idx, sysval, reg->idx[0].offset, true, mask);
|
||||
}
|
||||
|
||||
static void shader_sm1_scan_register(struct vkd3d_shader_sm1_parser *sm1, const struct vkd3d_shader_register *reg, unsigned int mask)
|
||||
static void record_constant_register(struct vkd3d_shader_sm1_parser *sm1,
|
||||
enum vkd3d_shader_d3dbc_constant_register set, uint32_t index, bool from_def)
|
||||
{
|
||||
struct vkd3d_shader_desc *desc = &sm1->p.shader_desc;
|
||||
|
||||
desc->flat_constant_count[set].used = max(desc->flat_constant_count[set].used, index + 1);
|
||||
if (from_def)
|
||||
{
|
||||
/* d3d shaders have a maximum of 8192 constants; we should not overrun
|
||||
* this array. */
|
||||
assert((index / 32) <= ARRAY_SIZE(sm1->constant_def_mask[set]));
|
||||
bitmap_set(sm1->constant_def_mask[set], index);
|
||||
}
|
||||
}
|
||||
|
||||
static void shader_sm1_scan_register(struct vkd3d_shader_sm1_parser *sm1,
|
||||
const struct vkd3d_shader_register *reg, unsigned int mask, bool from_def)
|
||||
{
|
||||
struct vkd3d_shader_desc *desc = &sm1->p.shader_desc;
|
||||
uint32_t register_index = reg->idx[0].offset;
|
||||
|
||||
if (reg->type == VKD3DSPR_TEMP)
|
||||
sm1->p.shader_desc.temp_count = max(sm1->p.shader_desc.temp_count, register_index + 1);
|
||||
switch (reg->type)
|
||||
{
|
||||
case VKD3DSPR_TEMP:
|
||||
desc->temp_count = max(desc->temp_count, register_index + 1);
|
||||
break;
|
||||
|
||||
case VKD3DSPR_CONST:
|
||||
record_constant_register(sm1, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, register_index, from_def);
|
||||
break;
|
||||
|
||||
case VKD3DSPR_CONST2:
|
||||
record_constant_register(sm1, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, 2048 + register_index, from_def);
|
||||
break;
|
||||
|
||||
case VKD3DSPR_CONST3:
|
||||
record_constant_register(sm1, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, 4096 + register_index, from_def);
|
||||
break;
|
||||
|
||||
case VKD3DSPR_CONST4:
|
||||
record_constant_register(sm1, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, 6144 + register_index, from_def);
|
||||
break;
|
||||
|
||||
case VKD3DSPR_CONSTINT:
|
||||
record_constant_register(sm1, VKD3D_SHADER_D3DBC_INT_CONSTANT_REGISTER, register_index, from_def);
|
||||
break;
|
||||
|
||||
case VKD3DSPR_CONSTBOOL:
|
||||
record_constant_register(sm1, VKD3D_SHADER_D3DBC_BOOL_CONSTANT_REGISTER, register_index, from_def);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
add_signature_element_from_register(sm1, reg, false, mask);
|
||||
}
|
||||
@ -1076,16 +1127,19 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str
|
||||
{
|
||||
shader_sm1_read_dst_param(sm1, &p, dst_param);
|
||||
shader_sm1_read_immconst(sm1, &p, &src_params[0], VKD3D_IMMCONST_VEC4, VKD3D_DATA_FLOAT);
|
||||
shader_sm1_scan_register(sm1, &dst_param->reg, dst_param->write_mask, true);
|
||||
}
|
||||
else if (ins->handler_idx == VKD3DSIH_DEFB)
|
||||
{
|
||||
shader_sm1_read_dst_param(sm1, &p, dst_param);
|
||||
shader_sm1_read_immconst(sm1, &p, &src_params[0], VKD3D_IMMCONST_SCALAR, VKD3D_DATA_UINT);
|
||||
shader_sm1_scan_register(sm1, &dst_param->reg, dst_param->write_mask, true);
|
||||
}
|
||||
else if (ins->handler_idx == VKD3DSIH_DEFI)
|
||||
{
|
||||
shader_sm1_read_dst_param(sm1, &p, dst_param);
|
||||
shader_sm1_read_immconst(sm1, &p, &src_params[0], VKD3D_IMMCONST_VEC4, VKD3D_DATA_INT);
|
||||
shader_sm1_scan_register(sm1, &dst_param->reg, dst_param->write_mask, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1093,7 +1147,7 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str
|
||||
if (ins->dst_count)
|
||||
{
|
||||
shader_sm1_read_dst_param(sm1, &p, dst_param);
|
||||
shader_sm1_scan_register(sm1, &dst_param->reg, dst_param->write_mask);
|
||||
shader_sm1_scan_register(sm1, &dst_param->reg, dst_param->write_mask, false);
|
||||
}
|
||||
|
||||
/* Predication token */
|
||||
@ -1104,7 +1158,7 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str
|
||||
for (i = 0; i < ins->src_count; ++i)
|
||||
{
|
||||
shader_sm1_read_src_param(sm1, &p, &src_params[i]);
|
||||
shader_sm1_scan_register(sm1, &src_params[i].reg, mask_from_swizzle(src_params[i].swizzle));
|
||||
shader_sm1_scan_register(sm1, &src_params[i].reg, mask_from_swizzle(src_params[i].swizzle), false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1212,12 +1266,30 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1,
|
||||
return VKD3D_OK;
|
||||
}
|
||||
|
||||
static uint32_t get_external_constant_count(struct vkd3d_shader_sm1_parser *sm1,
|
||||
enum vkd3d_shader_d3dbc_constant_register set)
|
||||
{
|
||||
unsigned int j;
|
||||
|
||||
/* Find the highest constant index which is not written by a DEF
|
||||
* instruction. We can't (easily) use an FFZ function for this since it
|
||||
* needs to be limited by the highest used register index. */
|
||||
for (j = sm1->p.shader_desc.flat_constant_count[set].used; j > 0; --j)
|
||||
{
|
||||
if (!bitmap_is_set(sm1->constant_def_mask[set], j - 1))
|
||||
return j;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (!(sm1 = vkd3d_calloc(1, sizeof(*sm1))))
|
||||
@ -1257,6 +1329,9 @@ int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compi
|
||||
|
||||
*parser = &sm1->p;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sm1->p.shader_desc.flat_constant_count); ++i)
|
||||
sm1->p.shader_desc.flat_constant_count[i].external = get_external_constant_count(sm1, i);
|
||||
|
||||
return sm1->p.failed ? VKD3D_ERROR_INVALID_SHADER : VKD3D_OK;
|
||||
}
|
||||
|
||||
|
@ -1152,6 +1152,15 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(parser->shader_desc.flat_constant_count); ++i)
|
||||
{
|
||||
struct vkd3d_shader_register_range range = {.space = 0, .first = i, .last = i};
|
||||
|
||||
if (parser->shader_desc.flat_constant_count[i].external)
|
||||
vkd3d_shader_scan_add_descriptor(&context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV,
|
||||
&range, VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT, 0);
|
||||
}
|
||||
|
||||
if (!ret && signature_info)
|
||||
{
|
||||
if (!vkd3d_shader_signature_from_shader_signature(&signature_info->input, &parser->shader_desc.input_signature)
|
||||
|
@ -840,6 +840,11 @@ struct vkd3d_shader_desc
|
||||
struct shader_signature patch_constant_signature;
|
||||
|
||||
uint32_t temp_count;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t used, external;
|
||||
} flat_constant_count[3];
|
||||
};
|
||||
|
||||
struct vkd3d_shader_register_semantic
|
||||
|
@ -729,6 +729,100 @@ static void test_scan_signatures(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void test_scan_descriptors(void)
|
||||
{
|
||||
struct vkd3d_shader_scan_descriptor_info descriptor_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_DESCRIPTOR_INFO};
|
||||
struct vkd3d_shader_hlsl_source_info hlsl_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_HLSL_SOURCE_INFO};
|
||||
struct vkd3d_shader_compile_info compile_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO};
|
||||
struct vkd3d_shader_code dxbc;
|
||||
size_t i, j;
|
||||
int rc;
|
||||
|
||||
static const char ps1_source[] =
|
||||
"float4 main(uniform float4 u, uniform float4 v) : sv_target\n"
|
||||
"{\n"
|
||||
" return u * v + 1.0;\n"
|
||||
"}";
|
||||
|
||||
static const char ps2_source[] =
|
||||
"float4 main() : sv_target\n"
|
||||
"{\n"
|
||||
" return 1.0;\n"
|
||||
"}";
|
||||
|
||||
static const struct vkd3d_shader_descriptor_info ps1_descriptors[] =
|
||||
{
|
||||
{VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, 0, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER,
|
||||
VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT, 0, 1},
|
||||
};
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char *source;
|
||||
bool sm4;
|
||||
const char *profile;
|
||||
const struct vkd3d_shader_descriptor_info *descriptors;
|
||||
size_t descriptor_count;
|
||||
}
|
||||
tests[] =
|
||||
{
|
||||
{ps1_source, false, "ps_2_0", ps1_descriptors, ARRAY_SIZE(ps1_descriptors)},
|
||||
{ps2_source, false, "ps_2_0", NULL, 0},
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tests); ++i)
|
||||
{
|
||||
vkd3d_test_push_context("test %u", i);
|
||||
|
||||
compile_info.source.code = tests[i].source;
|
||||
compile_info.source.size = strlen(tests[i].source);
|
||||
compile_info.source_type = VKD3D_SHADER_SOURCE_HLSL;
|
||||
compile_info.target_type = tests[i].sm4 ? VKD3D_SHADER_TARGET_DXBC_TPF : VKD3D_SHADER_TARGET_D3D_BYTECODE;
|
||||
compile_info.log_level = VKD3D_SHADER_LOG_INFO;
|
||||
|
||||
compile_info.next = &hlsl_info;
|
||||
hlsl_info.profile = tests[i].profile;
|
||||
|
||||
rc = vkd3d_shader_compile(&compile_info, &dxbc, NULL);
|
||||
ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc);
|
||||
|
||||
compile_info.source_type = tests[i].sm4 ? VKD3D_SHADER_SOURCE_DXBC_TPF : VKD3D_SHADER_SOURCE_D3D_BYTECODE;
|
||||
compile_info.source = dxbc;
|
||||
|
||||
compile_info.next = &descriptor_info;
|
||||
|
||||
rc = vkd3d_shader_scan(&compile_info, NULL);
|
||||
ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc);
|
||||
|
||||
ok(descriptor_info.descriptor_count == tests[i].descriptor_count,
|
||||
"Got descriptor count %u.\n", descriptor_info.descriptor_count);
|
||||
for (j = 0; j < descriptor_info.descriptor_count; ++j)
|
||||
{
|
||||
const struct vkd3d_shader_descriptor_info *descriptor = &descriptor_info.descriptors[j];
|
||||
const struct vkd3d_shader_descriptor_info *expect = &tests[i].descriptors[j];
|
||||
|
||||
vkd3d_test_push_context("descriptor %u", j);
|
||||
|
||||
ok(descriptor->type == expect->type, "Got type %#x.\n", descriptor->type);
|
||||
ok(descriptor->register_space == expect->register_space, "Got space %u.\n", descriptor->register_space);
|
||||
ok(descriptor->register_index == expect->register_index, "Got index %u.\n", descriptor->register_index);
|
||||
ok(descriptor->resource_type == expect->resource_type,
|
||||
"Got resource type %#x.\n", descriptor->resource_type);
|
||||
ok(descriptor->resource_data_type == expect->resource_data_type,
|
||||
"Got data type %#x.\n", descriptor->resource_data_type);
|
||||
ok(descriptor->flags == expect->flags, "Got flags %#x.\n", descriptor->flags);
|
||||
ok(descriptor->count == expect->count, "Got count %u.\n", descriptor->count);
|
||||
|
||||
vkd3d_test_pop_context();
|
||||
}
|
||||
|
||||
vkd3d_shader_free_scan_descriptor_info(&descriptor_info);
|
||||
vkd3d_shader_free_shader_code(&dxbc);
|
||||
|
||||
vkd3d_test_pop_context();
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(vkd3d_shader_api)
|
||||
{
|
||||
setlocale(LC_ALL, "");
|
||||
@ -739,4 +833,5 @@ START_TEST(vkd3d_shader_api)
|
||||
run_test(test_d3dbc);
|
||||
run_test(test_dxbc);
|
||||
run_test(test_scan_signatures);
|
||||
run_test(test_scan_descriptors);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user