For clarity.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- v4: No change.
libs/vkd3d-shader/hlsl.c | 3 +++ libs/vkd3d-shader/hlsl.h | 2 +- libs/vkd3d-shader/hlsl_codegen.c | 15 ++------------- 3 files changed, 6 insertions(+), 14 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 0b8c660c..bc593f82 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -1664,6 +1664,9 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct hlsl_profile_info * if (!(ctx->globals_buffer = hlsl_new_buffer(ctx, HLSL_BUFFER_CONSTANT, hlsl_strdup(ctx, "$Globals"), NULL, ctx->location))) return false; + if (!(ctx->params_buffer = hlsl_new_buffer(ctx, HLSL_BUFFER_CONSTANT, + hlsl_strdup(ctx, "$Params"), NULL, ctx->location))) + return false; ctx->cur_buffer = ctx->globals_buffer;
return true; diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index b62e7818..e0045acf 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -456,7 +456,7 @@ struct hlsl_ctx struct list extern_vars;
struct list buffers; - struct hlsl_buffer *cur_buffer, *globals_buffer; + struct hlsl_buffer *cur_buffer, *globals_buffer, *params_buffer; struct list types; struct rb_tree functions; const struct hlsl_ir_function_decl *cur_function; diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 6336ddfc..778d9dff 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1142,27 +1142,16 @@ static void calculate_buffer_offset(struct hlsl_ir_var *var)
static void allocate_buffers(struct hlsl_ctx *ctx) { - struct hlsl_buffer *buffer, *params_buffer; + struct hlsl_buffer *buffer; struct hlsl_ir_var *var; uint32_t index = 0;
- if (!(params_buffer = hlsl_new_buffer(ctx, HLSL_BUFFER_CONSTANT, - hlsl_strdup(ctx, "$Params"), NULL, ctx->location))) - return; - - /* The $Globals and $Params buffers should be allocated first, before all - * explicit buffers. */ - list_remove(¶ms_buffer->entry); - list_add_head(&ctx->buffers, ¶ms_buffer->entry); - list_remove(&ctx->globals_buffer->entry); - list_add_head(&ctx->buffers, &ctx->globals_buffer->entry); - LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { if (var->is_uniform) { if (var->is_param) - var->buffer = params_buffer; + var->buffer = ctx->params_buffer;
calculate_buffer_offset(var); }
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- v4: No change.
libs/vkd3d-shader/hlsl.h | 4 +- libs/vkd3d-shader/hlsl_codegen.c | 101 ++++++++++++++----------------- 2 files changed, 47 insertions(+), 58 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index e0045acf..54273ac6 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -126,7 +126,7 @@ struct hlsl_type } e;
unsigned int reg_size; - unsigned int bytecode_offset; + size_t bytecode_offset; };
struct hlsl_semantic @@ -144,7 +144,7 @@ struct hlsl_struct_field struct hlsl_semantic semantic; unsigned int reg_offset;
- unsigned int name_bytecode_offset; + size_t name_bytecode_offset; };
struct hlsl_reg diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 778d9dff..51cb789f 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1324,72 +1324,57 @@ static struct hlsl_reg hlsl_reg_from_deref(const struct hlsl_deref *deref, const struct bytecode_buffer { struct hlsl_ctx *ctx; - uint32_t *data; - size_t count, size; + uint8_t *data; + size_t size, capacity; int status; };
-/* Returns the token index. */ -static unsigned int put_dword(struct bytecode_buffer *buffer, uint32_t value) +static size_t put_bytes(struct bytecode_buffer *buffer, const void *bytes, size_t size) { - unsigned int index = buffer->count; + size_t aligned_size = align(size, 4); + size_t offset = buffer->size;
if (buffer->status) - return index; + return offset;
- if (!hlsl_array_reserve(buffer->ctx, (void **)&buffer->data, &buffer->size, - buffer->count + 1, sizeof(*buffer->data))) + if (!hlsl_array_reserve(buffer->ctx, (void **)&buffer->data, &buffer->capacity, offset + aligned_size, 1)) { buffer->status = VKD3D_ERROR_OUT_OF_MEMORY; - return index; + return offset; } - buffer->data[buffer->count++] = value; + memcpy(buffer->data + offset, bytes, size); + memset(buffer->data + offset + size, 0xab, aligned_size - size); + buffer->size = offset + aligned_size; + return offset; +}
- return index; +static size_t put_dword(struct bytecode_buffer *buffer, uint32_t value) +{ + return put_bytes(buffer, &value, sizeof(value)); }
-/* Returns the token index. */ -static unsigned int put_float(struct bytecode_buffer *buffer, float value) +static size_t put_float(struct bytecode_buffer *buffer, float value) { - union - { - float f; - uint32_t u; - } u; - u.f = value; - return put_dword(buffer, u.u); + return put_bytes(buffer, &value, sizeof(value)); }
-static void set_dword(struct bytecode_buffer *buffer, unsigned int index, uint32_t value) +static void set_dword(struct bytecode_buffer *buffer, size_t offset, uint32_t value) { if (buffer->status) return;
- assert(index < buffer->count); - buffer->data[index] = value; + assert(offset + sizeof(value) <= buffer->size); + memcpy(buffer->data + offset, &value, sizeof(value)); }
-/* Returns the token index. */ -static unsigned int put_string(struct bytecode_buffer *buffer, const char *str) +static size_t put_string(struct bytecode_buffer *buffer, const char *string) { - unsigned int index = buffer->count; - size_t len = strlen(str) + 1; - unsigned int token_count = (len + 3) / sizeof(*buffer->data); - - if (buffer->status) - return index; - - if (!hlsl_array_reserve(buffer->ctx, (void **)&buffer->data, &buffer->size, - buffer->count + token_count, sizeof(*buffer->data))) - { - buffer->status = E_OUTOFMEMORY; - return index; - } + return put_bytes(buffer, string, strlen(string) + 1); +}
- buffer->data[buffer->count + token_count - 1] = 0xabababab; - memcpy(buffer->data + buffer->count, str, len); - buffer->count += token_count; - return index; +static size_t get_buffer_size(struct bytecode_buffer *buffer) +{ + return buffer->size; }
static uint32_t sm1_version(enum vkd3d_shader_type type, unsigned int major, unsigned int minor) @@ -1505,9 +1490,10 @@ static unsigned int get_array_size(const struct hlsl_type *type) static void write_sm1_type(struct bytecode_buffer *buffer, struct hlsl_type *type, unsigned int ctab_start) { const struct hlsl_type *array_type = get_array_type(type); - unsigned int fields_offset = 0, field_count = 0; unsigned int array_size = get_array_size(type); struct hlsl_struct_field *field; + unsigned int field_count = 0; + size_t fields_offset = 0;
if (type->bytecode_offset) return; @@ -1520,12 +1506,12 @@ static void write_sm1_type(struct bytecode_buffer *buffer, struct hlsl_type *typ write_sm1_type(buffer, field->type, ctab_start); }
- fields_offset = (buffer->count - ctab_start) * sizeof(*buffer->data); + fields_offset = get_buffer_size(buffer) - ctab_start;
LIST_FOR_EACH_ENTRY(field, array_type->e.elements, struct hlsl_struct_field, entry) { - put_dword(buffer, (field->name_bytecode_offset - ctab_start) * sizeof(*buffer->data)); - put_dword(buffer, (field->type->bytecode_offset - ctab_start) * sizeof(*buffer->data)); + put_dword(buffer, field->name_bytecode_offset - ctab_start); + put_dword(buffer, field->type->bytecode_offset - ctab_start); ++field_count; } } @@ -1567,7 +1553,7 @@ static void sm1_sort_externs(struct hlsl_ctx *ctx) static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, struct hlsl_ir_function_decl *entry_func) { - unsigned int ctab_start, vars_start, size_offset, creator_offset, offset; + size_t ctab_offset, ctab_start, ctab_end, vars_start, size_offset, creator_offset, offset; unsigned int uniform_count = 0; struct hlsl_ir_var *var;
@@ -1597,7 +1583,7 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct bytecode_buffer *buf sm1_sort_externs(ctx);
size_offset = put_dword(buffer, 0); - put_dword(buffer, MAKEFOURCC('C','T','A','B')); + ctab_offset = put_dword(buffer, MAKEFOURCC('C','T','A','B'));
ctab_start = put_dword(buffer, sizeof(D3DXSHADER_CONSTANTTABLE)); creator_offset = put_dword(buffer, 0); @@ -1607,7 +1593,7 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct bytecode_buffer *buf put_dword(buffer, 0); /* FIXME: flags */ put_dword(buffer, 0); /* FIXME: target string */
- vars_start = buffer->count; + vars_start = get_buffer_size(buffer);
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { @@ -1627,20 +1613,23 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct bytecode_buffer *buf { if (!var->semantic.name && var->reg.allocated) { - set_dword(buffer, vars_start + (uniform_count * 5), (buffer->count - ctab_start) * sizeof(*buffer->data)); - put_string(buffer, var->name); + size_t var_offset = vars_start + (uniform_count * 5 * sizeof(uint32_t)); + size_t name_offset; + + name_offset = put_string(buffer, var->name); + set_dword(buffer, var_offset, name_offset - ctab_start);
write_sm1_type(buffer, var->data_type, ctab_start); - set_dword(buffer, vars_start + (uniform_count * 5) + 3, - (var->data_type->bytecode_offset - ctab_start) * sizeof(*buffer->data)); + set_dword(buffer, var_offset + 3 * sizeof(uint32_t), var->data_type->bytecode_offset - ctab_start); ++uniform_count; } }
offset = put_string(buffer, vkd3d_shader_get_version(NULL, NULL)); - set_dword(buffer, creator_offset, (offset - ctab_start) * sizeof(*buffer->data)); + set_dword(buffer, creator_offset, offset - ctab_start);
- set_dword(buffer, size_offset, D3DSIO_COMMENT | ((buffer->count - (ctab_start - 1)) << 16)); + ctab_end = get_buffer_size(buffer); + set_dword(buffer, size_offset, D3DSIO_COMMENT | (((ctab_end - ctab_offset) / sizeof(uint32_t)) << 16)); }
static uint32_t sm1_encode_register_type(D3DSHADER_PARAM_REGISTER_TYPE type) @@ -2078,7 +2067,7 @@ static int write_sm1_shader(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl * if (!(ret = buffer.status)) { out->code = buffer.data; - out->size = buffer.count * sizeof(*buffer.data); + out->size = buffer.size; } return ret; }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- v4: New patch.
configure.ac | 1 + include/private/vkd3d_common.h | 11 +++++++++++ libs/vkd3d/command.c | 4 ++-- libs/vkd3d/device.c | 5 ++--- 4 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/configure.ac b/configure.ac index 275bca26..88d58e40 100644 --- a/configure.ac +++ b/configure.ac @@ -127,6 +127,7 @@ AS_IF([test "x$with_xcb" != "xno"], dnl Check for functions VKD3D_CHECK_FUNC([HAVE_BUILTIN_CLZ], [__builtin_clz], [__builtin_clz(0)]) VKD3D_CHECK_FUNC([HAVE_BUILTIN_POPCOUNT], [__builtin_popcount], [__builtin_popcount(0)]) +VKD3D_CHECK_FUNC([HAVE_BUILTIN_ADD_OVERFLOW], [__builtin_add_overflow], [__builtin_add_overflow(0, 0, (int *)0)]) VKD3D_CHECK_FUNC([HAVE_SYNC_ADD_AND_FETCH], [__sync_add_and_fetch], [__sync_add_and_fetch((int *)0, 0)]) VKD3D_CHECK_FUNC([HAVE_SYNC_SUB_AND_FETCH], [__sync_sub_and_fetch], [__sync_sub_and_fetch((int *)0, 0)])
diff --git a/include/private/vkd3d_common.h b/include/private/vkd3d_common.h index 4ce2a2e3..369226f8 100644 --- a/include/private/vkd3d_common.h +++ b/include/private/vkd3d_common.h @@ -138,6 +138,17 @@ static inline void *vkd3d_memmem( const void *haystack, size_t haystack_len, con return NULL; }
+static inline bool vkd3d_bound_range(size_t start, size_t count, size_t limit) +{ +#ifdef HAVE_BUILTIN_ADD_OVERFLOW + size_t sum; + + return !__builtin_add_overflow(start, count, &sum) && sum <= limit; +#else + return start <= limit && count <= limit - start; +#endif +} + static inline int ascii_isupper(int c) { return 'A' <= c && c <= 'Z'; diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 116a8a62..60c4b37c 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4421,7 +4421,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_IASetVertexBuffers(ID3D12Graphi null_resources = &list->device->null_resources; gpu_va_allocator = &list->device->gpu_va_allocator;
- if (start_slot >= ARRAY_SIZE(list->strides) || view_count > ARRAY_SIZE(list->strides) - start_slot) + if (!vkd3d_bound_range(start_slot, view_count, ARRAY_SIZE(list->strides))) { WARN("Invalid start slot %u / view count %u.\n", start_slot, view_count); return; @@ -4476,7 +4476,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_SOSetTargets(ID3D12GraphicsComm return; }
- if (start_slot >= ARRAY_SIZE(buffers) || view_count > ARRAY_SIZE(buffers) - start_slot) + if (!vkd3d_bound_range(start_slot, view_count, ARRAY_SIZE(buffers))) { WARN("Invalid start slot %u / view count %u.\n", start_slot, view_count); return; diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 159bc470..ac6f14c7 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -1925,7 +1925,7 @@ static D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate_fallback(struct base = allocator->fallback_floor; ceiling = ~(D3D12_GPU_VIRTUAL_ADDRESS)0; ceiling -= alignment - 1; - if (aligned_size > ceiling || ceiling - aligned_size < base) + if (!vkd3d_bound_range(base, aligned_size, ceiling)) return 0;
base = (base + (alignment - 1)) & ~((D3D12_GPU_VIRTUAL_ADDRESS)alignment - 1); @@ -3515,8 +3515,7 @@ static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device *i
array_size = d3d12_resource_desc_get_layer_count(desc);
- if (first_sub_resource >= desc->MipLevels * array_size - || sub_resource_count > desc->MipLevels * array_size - first_sub_resource) + if (!vkd3d_bound_range(first_sub_resource, sub_resource_count, desc->MipLevels * array_size)) { WARN("Invalid sub-resource range %u-%u for resource.\n", first_sub_resource, sub_resource_count); return;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=93920
Your paranoid android.
=== debiant2 (build log) ===
error: patch failed: configure.ac:127 Task: Patch failed to apply
=== debiant2 (build log) ===
error: patch failed: configure.ac:127 Task: Patch failed to apply
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
On Fri, 9 Jul 2021 at 04:14, Zebediah Figura zfigura@codeweavers.com wrote:
+static inline bool vkd3d_bound_range(size_t start, size_t count, size_t limit) +{ +#ifdef HAVE_BUILTIN_ADD_OVERFLOW
- size_t sum;
- return !__builtin_add_overflow(start, count, &sum) && sum <= limit;
+#else
- return start <= limit && count <= limit - start;
+#endif +}
[...]
@@ -1925,7 +1925,7 @@ static D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate_fallback(struct base = allocator->fallback_floor; ceiling = ~(D3D12_GPU_VIRTUAL_ADDRESS)0; ceiling -= alignment - 1;
- if (aligned_size > ceiling || ceiling - aligned_size < base)
- if (!vkd3d_bound_range(base, aligned_size, ceiling)) return 0;
Actually, you can't necessarily do that. D3D12_GPU_VIRTUAL_ADDRESS is always a 64-bit type, but size_t may not be.
On 7/22/21 4:15 AM, Henri Verbeet wrote:
On Fri, 9 Jul 2021 at 04:14, Zebediah Figura zfigura@codeweavers.com wrote:
+static inline bool vkd3d_bound_range(size_t start, size_t count, size_t limit) +{ +#ifdef HAVE_BUILTIN_ADD_OVERFLOW
- size_t sum;
- return !__builtin_add_overflow(start, count, &sum) && sum <= limit;
+#else
- return start <= limit && count <= limit - start;
+#endif +}
[...]
@@ -1925,7 +1925,7 @@ static D3D12_GPU_VIRTUAL_ADDRESS vkd3d_gpu_va_allocator_allocate_fallback(struct base = allocator->fallback_floor; ceiling = ~(D3D12_GPU_VIRTUAL_ADDRESS)0; ceiling -= alignment - 1;
- if (aligned_size > ceiling || ceiling - aligned_size < base)
- if (!vkd3d_bound_range(base, aligned_size, ceiling)) return 0;
Actually, you can't necessarily do that. D3D12_GPU_VIRTUAL_ADDRESS is always a 64-bit type, but size_t may not be.
Oops, I thought I checked all of my types :-(
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- v4: Make the assertion in set_u32() overflow-safe, use uint8_t instead of char, rename put_float() to put_f32().
libs/vkd3d-shader/hlsl_codegen.c | 165 ++++++++--------------- libs/vkd3d-shader/vkd3d_shader_main.c | 28 ++++ libs/vkd3d-shader/vkd3d_shader_private.h | 30 +++++ 3 files changed, 114 insertions(+), 109 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 51cb789f..7e3e4d77 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1321,62 +1321,6 @@ static struct hlsl_reg hlsl_reg_from_deref(const struct hlsl_deref *deref, const return ret; }
-struct bytecode_buffer -{ - struct hlsl_ctx *ctx; - uint8_t *data; - size_t size, capacity; - int status; -}; - -static size_t put_bytes(struct bytecode_buffer *buffer, const void *bytes, size_t size) -{ - size_t aligned_size = align(size, 4); - size_t offset = buffer->size; - - if (buffer->status) - return offset; - - if (!hlsl_array_reserve(buffer->ctx, (void **)&buffer->data, &buffer->capacity, offset + aligned_size, 1)) - { - buffer->status = VKD3D_ERROR_OUT_OF_MEMORY; - return offset; - } - memcpy(buffer->data + offset, bytes, size); - memset(buffer->data + offset + size, 0xab, aligned_size - size); - buffer->size = offset + aligned_size; - return offset; -} - -static size_t put_dword(struct bytecode_buffer *buffer, uint32_t value) -{ - return put_bytes(buffer, &value, sizeof(value)); -} - -static size_t put_float(struct bytecode_buffer *buffer, float value) -{ - return put_bytes(buffer, &value, sizeof(value)); -} - -static void set_dword(struct bytecode_buffer *buffer, size_t offset, uint32_t value) -{ - if (buffer->status) - return; - - assert(offset + sizeof(value) <= buffer->size); - memcpy(buffer->data + offset, &value, sizeof(value)); -} - -static size_t put_string(struct bytecode_buffer *buffer, const char *string) -{ - return put_bytes(buffer, string, strlen(string) + 1); -} - -static size_t get_buffer_size(struct bytecode_buffer *buffer) -{ - return buffer->size; -} - static uint32_t sm1_version(enum vkd3d_shader_type type, unsigned int major, unsigned int minor) { if (type == VKD3D_SHADER_TYPE_VERTEX) @@ -1487,7 +1431,7 @@ static unsigned int get_array_size(const struct hlsl_type *type) return 1; }
-static void write_sm1_type(struct bytecode_buffer *buffer, struct hlsl_type *type, unsigned int ctab_start) +static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, struct hlsl_type *type, unsigned int ctab_start) { const struct hlsl_type *array_type = get_array_type(type); unsigned int array_size = get_array_size(type); @@ -1506,20 +1450,20 @@ static void write_sm1_type(struct bytecode_buffer *buffer, struct hlsl_type *typ write_sm1_type(buffer, field->type, ctab_start); }
- fields_offset = get_buffer_size(buffer) - ctab_start; + fields_offset = bytecode_get_size(buffer) - ctab_start;
LIST_FOR_EACH_ENTRY(field, array_type->e.elements, struct hlsl_struct_field, entry) { - put_dword(buffer, field->name_bytecode_offset - ctab_start); - put_dword(buffer, field->type->bytecode_offset - ctab_start); + put_u32(buffer, field->name_bytecode_offset - ctab_start); + put_u32(buffer, field->type->bytecode_offset - ctab_start); ++field_count; } }
- type->bytecode_offset = put_dword(buffer, sm1_class(type) | (sm1_base_type(type) << 16)); - put_dword(buffer, type->dimy | (type->dimx << 16)); - put_dword(buffer, array_size | (field_count << 16)); - put_dword(buffer, fields_offset); + type->bytecode_offset = put_u32(buffer, sm1_class(type) | (sm1_base_type(type) << 16)); + put_u32(buffer, type->dimy | (type->dimx << 16)); + put_u32(buffer, array_size | (field_count << 16)); + put_u32(buffer, fields_offset); }
static void sm1_sort_extern(struct list *sorted, struct hlsl_ir_var *to_sort) @@ -1550,7 +1494,7 @@ static void sm1_sort_externs(struct hlsl_ctx *ctx) list_move_tail(&ctx->extern_vars, &sorted); }
-static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, +static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, struct hlsl_ir_function_decl *entry_func) { size_t ctab_offset, ctab_start, ctab_end, vars_start, size_offset, creator_offset, offset; @@ -1582,28 +1526,28 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct bytecode_buffer *buf
sm1_sort_externs(ctx);
- size_offset = put_dword(buffer, 0); - ctab_offset = put_dword(buffer, MAKEFOURCC('C','T','A','B')); + size_offset = put_u32(buffer, 0); + ctab_offset = put_u32(buffer, MAKEFOURCC('C','T','A','B'));
- ctab_start = put_dword(buffer, sizeof(D3DXSHADER_CONSTANTTABLE)); - creator_offset = put_dword(buffer, 0); - put_dword(buffer, sm1_version(ctx->profile->type, ctx->profile->major_version, ctx->profile->minor_version)); - put_dword(buffer, uniform_count); - put_dword(buffer, sizeof(D3DXSHADER_CONSTANTTABLE)); /* offset of constants */ - put_dword(buffer, 0); /* FIXME: flags */ - put_dword(buffer, 0); /* FIXME: target string */ + ctab_start = put_u32(buffer, sizeof(D3DXSHADER_CONSTANTTABLE)); + creator_offset = put_u32(buffer, 0); + put_u32(buffer, sm1_version(ctx->profile->type, ctx->profile->major_version, ctx->profile->minor_version)); + put_u32(buffer, uniform_count); + put_u32(buffer, sizeof(D3DXSHADER_CONSTANTTABLE)); /* offset of constants */ + put_u32(buffer, 0); /* FIXME: flags */ + put_u32(buffer, 0); /* FIXME: target string */
- vars_start = get_buffer_size(buffer); + vars_start = bytecode_get_size(buffer);
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { if (!var->semantic.name && var->reg.allocated) { - put_dword(buffer, 0); /* name */ - put_dword(buffer, D3DXRS_FLOAT4 | (var->reg.id << 16)); - put_dword(buffer, var->data_type->reg_size / 4); - put_dword(buffer, 0); /* type */ - put_dword(buffer, 0); /* FIXME: default value */ + put_u32(buffer, 0); /* name */ + put_u32(buffer, D3DXRS_FLOAT4 | (var->reg.id << 16)); + put_u32(buffer, var->data_type->reg_size / 4); + put_u32(buffer, 0); /* type */ + put_u32(buffer, 0); /* FIXME: default value */ } }
@@ -1617,19 +1561,19 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct bytecode_buffer *buf size_t name_offset;
name_offset = put_string(buffer, var->name); - set_dword(buffer, var_offset, name_offset - ctab_start); + set_u32(buffer, var_offset, name_offset - ctab_start);
write_sm1_type(buffer, var->data_type, ctab_start); - set_dword(buffer, var_offset + 3 * sizeof(uint32_t), var->data_type->bytecode_offset - ctab_start); + set_u32(buffer, var_offset + 3 * sizeof(uint32_t), var->data_type->bytecode_offset - ctab_start); ++uniform_count; } }
offset = put_string(buffer, vkd3d_shader_get_version(NULL, NULL)); - set_dword(buffer, creator_offset, offset - ctab_start); + set_u32(buffer, creator_offset, offset - ctab_start);
- ctab_end = get_buffer_size(buffer); - set_dword(buffer, size_offset, D3DSIO_COMMENT | (((ctab_end - ctab_offset) / sizeof(uint32_t)) << 16)); + ctab_end = bytecode_get_size(buffer); + set_u32(buffer, size_offset, D3DSIO_COMMENT | (((ctab_end - ctab_offset) / sizeof(uint32_t)) << 16)); }
static uint32_t sm1_encode_register_type(D3DSHADER_PARAM_REGISTER_TYPE type) @@ -1662,21 +1606,21 @@ struct sm1_instruction unsigned int has_dst; };
-static void write_sm1_dst_register(struct bytecode_buffer *buffer, const struct sm1_dst_register *reg) +static void write_sm1_dst_register(struct vkd3d_bytecode_buffer *buffer, const struct sm1_dst_register *reg) { assert(reg->writemask); - put_dword(buffer, (1u << 31) | sm1_encode_register_type(reg->type) | reg->mod | (reg->writemask << 16) | reg->reg); + put_u32(buffer, (1u << 31) | sm1_encode_register_type(reg->type) | reg->mod | (reg->writemask << 16) | reg->reg); }
-static void write_sm1_src_register(struct bytecode_buffer *buffer, +static void write_sm1_src_register(struct vkd3d_bytecode_buffer *buffer, const struct sm1_src_register *reg, unsigned int dst_writemask) { unsigned int swizzle = map_swizzle(reg->swizzle, dst_writemask);
- put_dword(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 | (swizzle << 16) | reg->reg); }
-static void write_sm1_instruction(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, +static void write_sm1_instruction(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct sm1_instruction *instr) { uint32_t token = instr->opcode; @@ -1684,7 +1628,7 @@ static void write_sm1_instruction(struct hlsl_ctx *ctx, struct bytecode_buffer *
if (ctx->profile->major_version > 1) token |= (instr->has_dst + instr->src_count) << D3DSI_INSTLENGTH_SHIFT; - put_dword(buffer, token); + put_u32(buffer, token);
if (instr->has_dst) write_sm1_dst_register(buffer, &instr->dst); @@ -1693,7 +1637,7 @@ static void write_sm1_instruction(struct hlsl_ctx *ctx, struct bytecode_buffer * write_sm1_src_register(buffer, &instr->srcs[i], instr->dst.writemask); };
-static void write_sm1_binary_op(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, +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) { @@ -1717,7 +1661,7 @@ static void write_sm1_binary_op(struct hlsl_ctx *ctx, struct bytecode_buffer *bu write_sm1_instruction(ctx, buffer, &instr); }
-static void write_sm1_unary_op(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, +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) { @@ -1739,7 +1683,7 @@ static void write_sm1_unary_op(struct hlsl_ctx *ctx, struct bytecode_buffer *buf write_sm1_instruction(ctx, buffer, &instr); }
-static void write_sm1_constant_defs(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer) +static void write_sm1_constant_defs(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer) { unsigned int i, x;
@@ -1755,15 +1699,15 @@ static void write_sm1_constant_defs(struct hlsl_ctx *ctx, struct bytecode_buffer
if (ctx->profile->major_version > 1) token |= 5 << D3DSI_INSTLENGTH_SHIFT; - put_dword(buffer, token); + put_u32(buffer, token);
write_sm1_dst_register(buffer, ®); for (x = 0; x < 4; ++x) - put_float(buffer, ctx->constant_defs.values[i].f[x]); + put_f32(buffer, ctx->constant_defs.values[i].f[x]); } }
-static void write_sm1_semantic_dcl(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, +static void write_sm1_semantic_dcl(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_var *var, bool output) { struct sm1_dst_register reg = {0}; @@ -1787,18 +1731,18 @@ static void write_sm1_semantic_dcl(struct hlsl_ctx *ctx, struct bytecode_buffer token = D3DSIO_DCL; if (ctx->profile->major_version > 1) token |= 2 << D3DSI_INSTLENGTH_SHIFT; - put_dword(buffer, token); + put_u32(buffer, token);
token = (1u << 31); token |= usage << D3DSP_DCL_USAGE_SHIFT; token |= usage_idx << D3DSP_DCL_USAGEINDEX_SHIFT; - put_dword(buffer, token); + put_u32(buffer, token);
reg.writemask = (1 << var->data_type->dimx) - 1; write_sm1_dst_register(buffer, ®); }
-static void write_sm1_semantic_dcls(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer) +static void write_sm1_semantic_dcls(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer) { bool write_in = false, write_out = false; struct hlsl_ir_var *var; @@ -1819,7 +1763,8 @@ static void write_sm1_semantic_dcls(struct hlsl_ctx *ctx, struct bytecode_buffer } }
-static void write_sm1_constant(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, const struct hlsl_ir_node *instr) +static void write_sm1_constant(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, + const struct hlsl_ir_node *instr) { const struct hlsl_ir_constant *constant = hlsl_ir_constant(instr); struct sm1_instruction sm1_instr = @@ -1842,7 +1787,7 @@ static void write_sm1_constant(struct hlsl_ctx *ctx, struct bytecode_buffer *buf write_sm1_instruction(ctx, buffer, &sm1_instr); }
-static void write_sm1_expr(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, const struct hlsl_ir_node *instr) +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; @@ -1892,7 +1837,7 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, } }
-static void write_sm1_load(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, const struct hlsl_ir_node *instr) +static void write_sm1_load(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_node *instr) { const struct hlsl_ir_load *load = hlsl_ir_load(instr); const struct hlsl_reg reg = hlsl_reg_from_deref(&load->src, instr->data_type); @@ -1934,7 +1879,8 @@ static void write_sm1_load(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, write_sm1_instruction(ctx, buffer, &sm1_instr); }
-static void write_sm1_store(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, const struct hlsl_ir_node *instr) +static void write_sm1_store(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, + const struct hlsl_ir_node *instr) { const struct hlsl_ir_store *store = hlsl_ir_store(instr); const struct hlsl_ir_node *rhs = store->rhs.node; @@ -1977,7 +1923,8 @@ static void write_sm1_store(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer write_sm1_instruction(ctx, buffer, &sm1_instr); }
-static void write_sm1_swizzle(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, const struct hlsl_ir_node *instr) +static void write_sm1_swizzle(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, + const struct hlsl_ir_node *instr) { const struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(instr); const struct hlsl_ir_node *val = swizzle->val.node; @@ -2002,7 +1949,7 @@ static void write_sm1_swizzle(struct hlsl_ctx *ctx, struct bytecode_buffer *buff write_sm1_instruction(ctx, buffer, &sm1_instr); }
-static void write_sm1_instructions(struct hlsl_ctx *ctx, struct bytecode_buffer *buffer, +static void write_sm1_instructions(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_function_decl *entry_func) { const struct hlsl_ir_node *instr; @@ -2051,10 +1998,10 @@ static void write_sm1_instructions(struct hlsl_ctx *ctx, struct bytecode_buffer static int write_sm1_shader(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out) { - struct bytecode_buffer buffer = {.ctx = ctx}; + struct vkd3d_bytecode_buffer buffer = {0}; int ret;
- put_dword(&buffer, sm1_version(ctx->profile->type, ctx->profile->major_version, ctx->profile->minor_version)); + put_u32(&buffer, sm1_version(ctx->profile->type, ctx->profile->major_version, ctx->profile->minor_version));
write_sm1_uniforms(ctx, &buffer, entry_func);
@@ -2062,7 +2009,7 @@ static int write_sm1_shader(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl * write_sm1_semantic_dcls(ctx, &buffer); write_sm1_instructions(ctx, &buffer, entry_func);
- put_dword(&buffer, D3DSIO_END); + put_u32(&buffer, D3DSIO_END);
if (!(ret = buffer.status)) { diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 54654f3f..046b7666 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -282,6 +282,34 @@ void vkd3d_shader_error(struct vkd3d_shader_message_context *context, const stru va_end(args); }
+size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *bytes, size_t size) +{ + size_t aligned_size = align(size, 4); + size_t offset = buffer->size; + + if (buffer->status) + return offset; + + if (!vkd3d_array_reserve((void **)&buffer->data, &buffer->capacity, offset + aligned_size, 1)) + { + buffer->status = VKD3D_ERROR_OUT_OF_MEMORY; + return offset; + } + memcpy(buffer->data + offset, bytes, size); + memset(buffer->data + offset + size, 0xab, aligned_size - size); + buffer->size = offset + aligned_size; + return offset; +} + +void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value) +{ + if (buffer->status) + return; + + assert(vkd3d_bound_range(offset, sizeof(value), buffer->size)); + memcpy(buffer->data + offset, &value, sizeof(value)); +} + static void vkd3d_shader_dump_blob(const char *path, const char *prefix, const void *data, size_t size) { static int shader_id = 0; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index c5d1372a..fe01cdfa 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -902,6 +902,36 @@ void vkd3d_string_buffer_release(struct vkd3d_string_buffer_cache *list, void vkd3d_string_buffer_trace_(const struct vkd3d_string_buffer *buffer, const char *function) DECLSPEC_HIDDEN; int vkd3d_string_buffer_vprintf(struct vkd3d_string_buffer *buffer, const char *format, va_list args) DECLSPEC_HIDDEN;
+struct vkd3d_bytecode_buffer +{ + uint8_t *data; + size_t size, capacity; + int status; +}; + +size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *bytes, size_t size) DECLSPEC_HIDDEN; +void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value) DECLSPEC_HIDDEN; + +static inline size_t put_u32(struct vkd3d_bytecode_buffer *buffer, uint32_t value) +{ + return bytecode_put_bytes(buffer, &value, sizeof(value)); +} + +static inline size_t put_f32(struct vkd3d_bytecode_buffer *buffer, float value) +{ + return bytecode_put_bytes(buffer, &value, sizeof(value)); +} + +static inline size_t put_string(struct vkd3d_bytecode_buffer *buffer, const char *string) +{ + return bytecode_put_bytes(buffer, string, strlen(string) + 1); +} + +static inline size_t bytecode_get_size(struct vkd3d_bytecode_buffer *buffer) +{ + return buffer->size; +} + struct vkd3d_shader_location { const char *source_name;
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- v4: Split up the patch, and preserve an out-of-memory error message.
libs/vkd3d-shader/dxbc.c | 65 +++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 30 deletions(-)
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index 4bc62014..a0c083f1 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -2911,9 +2911,7 @@ struct root_signature_writer_context { struct vkd3d_shader_message_context message_context;
- DWORD *data; - size_t position; - size_t capacity; + struct vkd3d_bytecode_buffer buffer;
size_t total_size_position; size_t chunk_position; @@ -2924,12 +2922,10 @@ static bool write_dwords(struct root_signature_writer_context *context, { unsigned int i;
- if (!vkd3d_array_reserve((void **)&context->data, &context->capacity, - context->position + count, sizeof(*context->data))) - return false; for (i = 0; i < count; ++i) - context->data[context->position++] = d; - return true; + put_u32(&context->buffer, d); + + return !context->buffer.status; }
static bool write_dword(struct root_signature_writer_context *context, DWORD d) @@ -2939,22 +2935,19 @@ static bool write_dword(struct root_signature_writer_context *context, DWORD d)
static bool write_float(struct root_signature_writer_context *context, float f) { - union - { - float f; - DWORD d; - } u; - u.f = f; - return write_dword(context, u.d); + put_f32(&context->buffer, f); + return !context->buffer.status; }
static size_t get_chunk_offset(struct root_signature_writer_context *context) { - return (context->position - context->chunk_position) * sizeof(DWORD); + return bytecode_get_size(&context->buffer) - context->chunk_position; }
static int shader_write_root_signature_header(struct root_signature_writer_context *context) { + struct vkd3d_bytecode_buffer *buffer = &context->buffer; + if (!write_dword(context, TAG_DXBC)) goto fail;
@@ -2965,7 +2958,7 @@ static int shader_write_root_signature_header(struct root_signature_writer_conte if (!write_dword(context, 0x00000001)) goto fail;
- context->total_size_position = context->position; + context->total_size_position = bytecode_get_size(buffer); if (!write_dword(context, 0xffffffff)) /* total size */ goto fail;
@@ -2973,14 +2966,14 @@ static int shader_write_root_signature_header(struct root_signature_writer_conte goto fail;
/* chunk offset */ - if (!write_dword(context, (context->position + 1) * sizeof(DWORD))) + if (!write_dword(context, bytecode_get_size(buffer) + sizeof(uint32_t))) goto fail;
if (!write_dword(context, TAG_RTS0)) goto fail; if (!write_dword(context, 0xffffffff)) /* chunk size */ goto fail; - context->chunk_position = context->position; + context->chunk_position = bytecode_get_size(buffer);
return VKD3D_OK;
@@ -3136,11 +3129,12 @@ static int shader_write_root_parameters(struct root_signature_writer_context *co const struct vkd3d_shader_versioned_root_signature_desc *desc) { unsigned int parameter_count = versioned_root_signature_get_parameter_count(desc); + struct vkd3d_bytecode_buffer *buffer = &context->buffer; size_t parameters_position; unsigned int i; int ret;
- parameters_position = context->position; + parameters_position = bytecode_get_size(buffer); for (i = 0; i < parameter_count; ++i) { if (!write_dword(context, versioned_root_signature_get_parameter_type(desc, i))) @@ -3153,7 +3147,7 @@ static int shader_write_root_parameters(struct root_signature_writer_context *co
for (i = 0; i < parameter_count; ++i) { - context->data[parameters_position + 3 * i + 2] = get_chunk_offset(context); /* offset */ + set_u32(buffer, parameters_position + ((3 * i + 2) * sizeof(uint32_t)), get_chunk_offset(context));
switch (versioned_root_signature_get_parameter_type(desc, i)) { @@ -3241,6 +3235,7 @@ fail: static int shader_write_root_signature(struct root_signature_writer_context *context, const struct vkd3d_shader_versioned_root_signature_desc *desc) { + struct vkd3d_bytecode_buffer *buffer = &context->buffer; size_t samplers_offset_position; int ret;
@@ -3254,7 +3249,7 @@ static int shader_write_root_signature(struct root_signature_writer_context *con
if (!write_dword(context, versioned_root_signature_get_static_sampler_count(desc))) goto fail; - samplers_offset_position = context->position; + samplers_offset_position = bytecode_get_size(buffer); if (!write_dword(context, 0xffffffff)) /* offset */ goto fail;
@@ -3264,7 +3259,7 @@ static int shader_write_root_signature(struct root_signature_writer_context *con if ((ret = shader_write_root_parameters(context, desc)) < 0) return ret;
- context->data[samplers_offset_position] = get_chunk_offset(context); + set_u32(buffer, samplers_offset_position, get_chunk_offset(context)); return shader_write_static_samplers(context, desc);
fail: @@ -3387,6 +3382,7 @@ int vkd3d_shader_serialize_root_signature(const struct vkd3d_shader_versioned_ro struct root_signature_writer_context context; size_t total_size, chunk_size; uint32_t checksum[4]; + unsigned int i; int ret;
TRACE("root_signature %p, dxbc %p, messages %p.\n", root_signature, dxbc, messages); @@ -3413,26 +3409,35 @@ int vkd3d_shader_serialize_root_signature(const struct vkd3d_shader_versioned_ro memset(dxbc, 0, sizeof(*dxbc)); if ((ret = shader_write_root_signature_header(&context)) < 0) { - vkd3d_free(context.data); + vkd3d_free(context.buffer.data); goto done; }
if ((ret = shader_write_root_signature(&context, root_signature)) < 0) { - vkd3d_free(context.data); + vkd3d_free(context.buffer.data); + goto done; + } + + if (context.buffer.status) + { + vkd3d_shader_error(&context.message_context, NULL, VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY, + "Out of memory while writing root signature."); + vkd3d_free(context.buffer.data); goto done; }
- total_size = context.position * sizeof(DWORD); + total_size = bytecode_get_size(&context.buffer); chunk_size = get_chunk_offset(&context); - context.data[context.total_size_position] = total_size; - context.data[context.chunk_position - 1] = chunk_size; + set_u32(&context.buffer, context.total_size_position, total_size); + set_u32(&context.buffer, context.chunk_position - sizeof(uint32_t), chunk_size);
- dxbc->code = context.data; + dxbc->code = context.buffer.data; dxbc->size = total_size;
vkd3d_compute_dxbc_checksum(dxbc->code, dxbc->size, checksum); - memcpy((uint32_t *)dxbc->code + 1, checksum, sizeof(checksum)); + for (i = 0; i < 4; ++i) + set_u32(&context.buffer, (i + 1) * sizeof(uint32_t), checksum[i]);
ret = VKD3D_OK;
Signed-off-by: Matteo Bruni mbruni@codeweavers.com