2023-11-05 13:07:01 -08:00
|
|
|
/*
|
|
|
|
* FX (Direct3D 9/10/11 effect) support
|
|
|
|
*
|
|
|
|
* Copyright 2023 Nikolay Sivov for CodeWeavers
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "hlsl.h"
|
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
static inline size_t put_u32_unaligned(struct vkd3d_bytecode_buffer *buffer, uint32_t value)
|
|
|
|
{
|
|
|
|
return bytecode_put_bytes_unaligned(buffer, &value, sizeof(value));
|
|
|
|
}
|
|
|
|
|
2024-01-12 05:33:05 -08:00
|
|
|
struct string_entry
|
|
|
|
{
|
|
|
|
struct rb_entry entry;
|
|
|
|
/* String points to original data, should not be freed. */
|
|
|
|
const char *string;
|
|
|
|
uint32_t offset;
|
|
|
|
};
|
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
struct type_entry
|
|
|
|
{
|
|
|
|
struct list entry;
|
|
|
|
const char *name;
|
|
|
|
uint32_t elements_count;
|
|
|
|
uint32_t offset;
|
|
|
|
};
|
|
|
|
|
2024-01-12 05:33:05 -08:00
|
|
|
static int string_storage_compare(const void *key, const struct rb_entry *entry)
|
|
|
|
{
|
|
|
|
struct string_entry *string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry);
|
|
|
|
const char *string = key;
|
|
|
|
|
|
|
|
return strcmp(string, string_entry->string);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void string_storage_destroy(struct rb_entry *entry, void *context)
|
|
|
|
{
|
|
|
|
struct string_entry *string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry);
|
|
|
|
|
|
|
|
vkd3d_free(string_entry);
|
|
|
|
}
|
|
|
|
|
2024-06-06 14:50:05 -07:00
|
|
|
struct state_block_function_info
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
unsigned int min_args, max_args;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct state_block_function_info *get_state_block_function_info(const char *name)
|
|
|
|
{
|
|
|
|
static const struct state_block_function_info valid_functions[] =
|
|
|
|
{
|
|
|
|
{"SetBlendState", 3, 3},
|
|
|
|
{"SetDepthStencilState", 2, 2},
|
|
|
|
{"SetRasterizerState", 1, 1},
|
|
|
|
{"SetVertexShader", 1, 1},
|
|
|
|
{"SetDomainShader", 1, 1},
|
|
|
|
{"SetHullShader", 1, 1},
|
|
|
|
{"SetGeometryShader", 1, 1},
|
|
|
|
{"SetPixelShader", 1, 1},
|
|
|
|
{"SetComputeShader", 1, 1},
|
|
|
|
{"OMSetRenderTargets", 2, 9},
|
|
|
|
};
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < ARRAY_SIZE(valid_functions); ++i)
|
|
|
|
{
|
|
|
|
if (!strcmp(name, valid_functions[i].name))
|
|
|
|
return &valid_functions[i];
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool hlsl_validate_state_block_entry(struct hlsl_ctx *ctx, struct hlsl_state_block_entry *entry,
|
|
|
|
const struct vkd3d_shader_location *loc)
|
|
|
|
{
|
|
|
|
if (entry->is_function_call)
|
|
|
|
{
|
|
|
|
const struct state_block_function_info *info = get_state_block_function_info(entry->name);
|
|
|
|
|
|
|
|
if (!info)
|
|
|
|
{
|
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_STATE_BLOCK_ENTRY,
|
|
|
|
"Invalid state block function '%s'.", entry->name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (entry->args_count < info->min_args || entry->args_count > info->max_args)
|
|
|
|
{
|
|
|
|
if (info->min_args == info->max_args)
|
|
|
|
{
|
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_STATE_BLOCK_ENTRY,
|
|
|
|
"Invalid argument count for state block function '%s' (expected %u).",
|
|
|
|
entry->name, info->min_args);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_STATE_BLOCK_ENTRY,
|
|
|
|
"Invalid argument count for state block function '%s' (expected from %u to %u).",
|
|
|
|
entry->name, info->min_args, info->max_args);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
struct fx_write_context;
|
|
|
|
|
|
|
|
struct fx_write_context_ops
|
|
|
|
{
|
|
|
|
uint32_t (*write_string)(const char *string, struct fx_write_context *fx);
|
|
|
|
void (*write_technique)(struct hlsl_ir_var *var, struct fx_write_context *fx);
|
2023-11-15 14:31:01 -08:00
|
|
|
void (*write_pass)(struct hlsl_ir_var *var, struct fx_write_context *fx);
|
2024-06-15 14:44:08 -07:00
|
|
|
void (*write_annotation)(struct hlsl_ir_var *var, struct fx_write_context *fx);
|
2024-02-24 16:08:46 -08:00
|
|
|
bool are_child_effects_supported;
|
2024-01-16 03:17:06 -08:00
|
|
|
};
|
|
|
|
|
2023-11-05 13:07:01 -08:00
|
|
|
struct fx_write_context
|
|
|
|
{
|
2024-01-12 05:33:05 -08:00
|
|
|
struct hlsl_ctx *ctx;
|
|
|
|
|
2023-11-05 13:07:01 -08:00
|
|
|
struct vkd3d_bytecode_buffer unstructured;
|
|
|
|
struct vkd3d_bytecode_buffer structured;
|
|
|
|
|
2024-01-12 05:33:05 -08:00
|
|
|
struct rb_tree strings;
|
2024-02-06 06:11:47 -08:00
|
|
|
struct list types;
|
2024-01-12 05:33:05 -08:00
|
|
|
|
2024-01-12 05:26:39 -08:00
|
|
|
unsigned int min_technique_version;
|
|
|
|
unsigned int max_technique_version;
|
|
|
|
|
2023-11-05 13:07:01 -08:00
|
|
|
uint32_t technique_count;
|
2024-07-11 05:02:31 -07:00
|
|
|
uint32_t pass_count;
|
2024-01-12 05:26:39 -08:00
|
|
|
uint32_t group_count;
|
2024-02-06 06:11:47 -08:00
|
|
|
uint32_t buffer_count;
|
2024-04-21 10:06:55 -07:00
|
|
|
uint32_t shared_buffer_count;
|
2024-02-06 06:11:47 -08:00
|
|
|
uint32_t numeric_variable_count;
|
2024-04-21 10:06:55 -07:00
|
|
|
uint32_t shared_numeric_variable_count;
|
2024-02-09 13:42:23 -08:00
|
|
|
uint32_t object_variable_count;
|
2024-02-24 16:08:46 -08:00
|
|
|
uint32_t shared_object_count;
|
2024-04-20 07:30:05 -07:00
|
|
|
uint32_t shader_count;
|
2024-02-13 03:52:11 -08:00
|
|
|
uint32_t parameter_count;
|
2024-05-06 14:29:15 -07:00
|
|
|
uint32_t dsv_count;
|
2024-04-20 07:19:54 -07:00
|
|
|
uint32_t rtv_count;
|
2024-04-20 07:28:34 -07:00
|
|
|
uint32_t texture_count;
|
2024-04-19 02:40:14 -07:00
|
|
|
uint32_t uav_count;
|
2024-04-20 15:33:41 -07:00
|
|
|
uint32_t sampler_state_count;
|
2024-06-10 04:05:13 -07:00
|
|
|
uint32_t depth_stencil_state_count;
|
2024-06-10 04:18:43 -07:00
|
|
|
uint32_t rasterizer_state_count;
|
2023-11-05 13:07:01 -08:00
|
|
|
int status;
|
2024-01-16 03:17:06 -08:00
|
|
|
|
2024-02-24 16:08:46 -08:00
|
|
|
bool child_effect;
|
2024-03-28 03:39:04 -07:00
|
|
|
bool include_empty_buffers;
|
2024-02-24 16:08:46 -08:00
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
const struct fx_write_context_ops *ops;
|
2023-11-05 13:07:01 -08:00
|
|
|
};
|
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
static void set_status(struct fx_write_context *fx, int status)
|
|
|
|
{
|
|
|
|
if (fx->status < 0)
|
|
|
|
return;
|
|
|
|
if (status < 0)
|
|
|
|
fx->status = status;
|
|
|
|
}
|
|
|
|
|
2024-03-14 05:49:14 -07:00
|
|
|
static bool has_annotations(const struct hlsl_ir_var *var)
|
|
|
|
{
|
|
|
|
return var->annotations && !list_empty(&var->annotations->vars);
|
|
|
|
}
|
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
static uint32_t write_string(const char *string, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
return fx->ops->write_string(string, fx);
|
|
|
|
}
|
|
|
|
|
2023-11-15 14:31:01 -08:00
|
|
|
static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
|
|
{
|
2024-07-09 06:11:47 -07:00
|
|
|
if (var->state_block_count && var->state_blocks[0]->count)
|
|
|
|
hlsl_fixme(fx->ctx, &var->loc, "Write pass assignments.");
|
2024-03-19 11:35:59 -07:00
|
|
|
|
2023-11-15 14:31:01 -08:00
|
|
|
fx->ops->write_pass(var, fx);
|
2024-07-11 05:02:31 -07:00
|
|
|
++fx->pass_count;
|
2023-11-15 14:31:01 -08:00
|
|
|
}
|
|
|
|
|
2024-06-15 14:44:08 -07:00
|
|
|
static uint32_t write_annotations(struct hlsl_scope *scope, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
|
|
|
struct hlsl_ir_var *v;
|
|
|
|
uint32_t count = 0;
|
|
|
|
|
|
|
|
if (!scope)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY(v, &scope->vars, struct hlsl_ir_var, scope_entry)
|
|
|
|
{
|
|
|
|
if (!v->default_values)
|
|
|
|
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
|
|
|
"Annotation variable is missing default value.");
|
|
|
|
|
|
|
|
fx->ops->write_annotation(v, fx);
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_fx_4_annotations(struct hlsl_scope *scope, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
|
|
|
uint32_t count_offset, count;
|
|
|
|
|
|
|
|
count_offset = put_u32(buffer, 0);
|
|
|
|
count = write_annotations(scope, fx);
|
|
|
|
set_u32(buffer, count_offset, count);
|
|
|
|
}
|
|
|
|
|
2024-03-11 03:31:21 -07:00
|
|
|
static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx);
|
2024-04-21 11:11:05 -07:00
|
|
|
static const char * get_fx_4_type_name(const struct hlsl_type *type);
|
2024-06-15 14:44:08 -07:00
|
|
|
static void write_fx_4_annotation(struct hlsl_ir_var *var, struct fx_write_context *fx);
|
2024-03-11 03:31:21 -07:00
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context *fx)
|
|
|
|
{
|
2024-04-21 11:11:05 -07:00
|
|
|
const struct hlsl_type *element_type;
|
2024-02-06 06:11:47 -08:00
|
|
|
struct type_entry *type_entry;
|
|
|
|
unsigned int elements_count;
|
|
|
|
const char *name;
|
|
|
|
|
2024-03-11 03:31:21 -07:00
|
|
|
assert(fx->ctx->profile->major_version >= 4);
|
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
if (type->class == HLSL_CLASS_ARRAY)
|
|
|
|
{
|
|
|
|
elements_count = hlsl_get_multiarray_size(type);
|
2024-04-21 11:11:05 -07:00
|
|
|
element_type = hlsl_get_multiarray_element_type(type);
|
2024-02-06 06:11:47 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
elements_count = 0;
|
2024-04-21 11:11:05 -07:00
|
|
|
element_type = type;
|
2024-02-06 06:11:47 -08:00
|
|
|
}
|
|
|
|
|
2024-04-21 11:11:05 -07:00
|
|
|
name = get_fx_4_type_name(element_type);
|
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
LIST_FOR_EACH_ENTRY(type_entry, &fx->types, struct type_entry, entry)
|
|
|
|
{
|
|
|
|
if (strcmp(type_entry->name, name))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (type_entry->elements_count != elements_count)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
return type_entry->offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(type_entry = hlsl_alloc(fx->ctx, sizeof(*type_entry))))
|
|
|
|
return 0;
|
|
|
|
|
2024-03-11 03:31:21 -07:00
|
|
|
type_entry->offset = write_fx_4_type(type, fx);
|
2024-02-06 06:11:47 -08:00
|
|
|
type_entry->name = name;
|
|
|
|
type_entry->elements_count = elements_count;
|
|
|
|
|
|
|
|
list_add_tail(&fx->types, &type_entry->entry);
|
|
|
|
|
|
|
|
return type_entry->offset;
|
|
|
|
}
|
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_context_ops *ops,
|
|
|
|
struct fx_write_context *fx)
|
2024-01-12 05:26:39 -08:00
|
|
|
{
|
|
|
|
unsigned int version = ctx->profile->major_version;
|
2024-04-23 12:38:06 -07:00
|
|
|
struct hlsl_ir_var *var;
|
2024-01-12 05:26:39 -08:00
|
|
|
|
|
|
|
memset(fx, 0, sizeof(*fx));
|
|
|
|
|
2024-01-12 05:33:05 -08:00
|
|
|
fx->ctx = ctx;
|
2024-01-16 03:17:06 -08:00
|
|
|
fx->ops = ops;
|
2024-01-12 05:26:39 -08:00
|
|
|
if (version == 2)
|
|
|
|
{
|
|
|
|
fx->min_technique_version = 9;
|
|
|
|
fx->max_technique_version = 9;
|
|
|
|
}
|
|
|
|
else if (version == 4)
|
|
|
|
{
|
|
|
|
fx->min_technique_version = 10;
|
|
|
|
fx->max_technique_version = 10;
|
|
|
|
}
|
|
|
|
else if (version == 5)
|
|
|
|
{
|
|
|
|
fx->min_technique_version = 10;
|
|
|
|
fx->max_technique_version = 11;
|
|
|
|
}
|
2024-01-12 05:33:05 -08:00
|
|
|
|
|
|
|
rb_init(&fx->strings, string_storage_compare);
|
2024-02-06 06:11:47 -08:00
|
|
|
list_init(&fx->types);
|
2024-02-24 16:08:46 -08:00
|
|
|
|
|
|
|
fx->child_effect = fx->ops->are_child_effects_supported && ctx->child_effect;
|
2024-03-28 03:39:04 -07:00
|
|
|
fx->include_empty_buffers = version == 4 && ctx->include_empty_buffers;
|
2024-03-13 15:39:27 -07:00
|
|
|
|
2024-04-23 12:38:06 -07:00
|
|
|
LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry)
|
|
|
|
{
|
|
|
|
if (var->storage_modifiers & HLSL_STORAGE_UNIFORM)
|
|
|
|
{
|
|
|
|
list_add_tail(&ctx->extern_vars, &var->extern_entry);
|
|
|
|
var->is_uniform = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-13 15:39:27 -07:00
|
|
|
hlsl_calculate_buffer_offsets(fx->ctx);
|
2024-01-12 05:33:05 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int fx_write_context_cleanup(struct fx_write_context *fx)
|
|
|
|
{
|
2024-02-06 06:11:47 -08:00
|
|
|
struct type_entry *type, *next_type;
|
|
|
|
|
2024-01-12 05:33:05 -08:00
|
|
|
rb_destroy(&fx->strings, string_storage_destroy, NULL);
|
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(type, next_type, &fx->types, struct type_entry, entry)
|
|
|
|
{
|
|
|
|
list_remove(&type->entry);
|
|
|
|
vkd3d_free(type);
|
|
|
|
}
|
|
|
|
|
2024-02-22 17:11:38 -08:00
|
|
|
return fx->ctx->result;
|
2024-01-12 05:26:39 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool technique_matches_version(const struct hlsl_ir_var *var, const struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
const struct hlsl_type *type = var->data_type;
|
|
|
|
|
2024-02-06 15:15:48 -08:00
|
|
|
if (type->class != HLSL_CLASS_TECHNIQUE)
|
2024-01-12 05:26:39 -08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return type->e.version >= fx->min_technique_version && type->e.version <= fx->max_technique_version;
|
|
|
|
}
|
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
static uint32_t write_fx_4_string(const char *string, struct fx_write_context *fx)
|
2023-11-05 13:07:01 -08:00
|
|
|
{
|
2024-01-12 05:33:05 -08:00
|
|
|
struct string_entry *string_entry;
|
|
|
|
struct rb_entry *entry;
|
|
|
|
|
2023-11-05 13:07:01 -08:00
|
|
|
/* NULLs are emitted as empty strings using the same 4 bytes at the start of the section. */
|
2024-01-12 05:33:05 -08:00
|
|
|
if (!string)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if ((entry = rb_get(&fx->strings, string)))
|
|
|
|
{
|
|
|
|
string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry);
|
|
|
|
return string_entry->offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(string_entry = hlsl_alloc(fx->ctx, sizeof(*string_entry))))
|
|
|
|
return 0;
|
|
|
|
|
2024-02-06 05:21:46 -08:00
|
|
|
string_entry->offset = bytecode_put_bytes_unaligned(&fx->unstructured, string, strlen(string) + 1);
|
2024-01-12 05:33:05 -08:00
|
|
|
string_entry->string = string;
|
|
|
|
|
|
|
|
rb_put(&fx->strings, string, &string_entry->entry);
|
|
|
|
|
|
|
|
return string_entry->offset;
|
2023-11-05 13:07:01 -08:00
|
|
|
}
|
|
|
|
|
2023-11-15 14:31:01 -08:00
|
|
|
static void write_fx_4_pass(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
|
|
|
uint32_t name_offset;
|
|
|
|
|
|
|
|
name_offset = write_string(var->name, fx);
|
|
|
|
put_u32(buffer, name_offset);
|
|
|
|
put_u32(buffer, 0); /* Assignment count. */
|
|
|
|
|
2024-06-15 14:44:08 -07:00
|
|
|
write_fx_4_annotations(var->annotations, fx);
|
|
|
|
|
2023-11-15 14:31:01 -08:00
|
|
|
/* TODO: assignments */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
2023-11-05 13:07:01 -08:00
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
|
|
|
uint32_t name_offset;
|
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
name_offset = write_string(var->name, fx);
|
2023-11-05 13:07:01 -08:00
|
|
|
put_u32(buffer, name_offset);
|
|
|
|
put_u32(buffer, 0); /* Annotation count. */
|
2023-11-10 16:14:03 -08:00
|
|
|
put_u32(buffer, 0); /* Assignment count. */
|
2023-11-15 14:31:01 -08:00
|
|
|
|
|
|
|
/* TODO: annotations */
|
|
|
|
/* TODO: assignments */
|
2023-11-10 16:14:03 -08:00
|
|
|
}
|
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
static uint32_t get_fx_4_type_size(const struct hlsl_type *type)
|
|
|
|
{
|
|
|
|
uint32_t elements_count;
|
|
|
|
|
|
|
|
elements_count = hlsl_get_multiarray_size(type);
|
|
|
|
type = hlsl_get_multiarray_element_type(type);
|
|
|
|
|
|
|
|
return type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float) * elements_count;
|
|
|
|
}
|
|
|
|
|
2024-04-20 15:33:41 -07:00
|
|
|
static const uint32_t fx_4_numeric_base_type[] =
|
|
|
|
{
|
|
|
|
[HLSL_TYPE_FLOAT] = 1,
|
|
|
|
[HLSL_TYPE_INT ] = 2,
|
|
|
|
[HLSL_TYPE_UINT ] = 3,
|
|
|
|
[HLSL_TYPE_BOOL ] = 4,
|
|
|
|
};
|
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
static const unsigned int NUMERIC_BASE_TYPE_SHIFT = 3;
|
|
|
|
static const unsigned int NUMERIC_ROWS_SHIFT = 8;
|
|
|
|
static const unsigned int NUMERIC_COLUMNS_SHIFT = 11;
|
|
|
|
static const unsigned int NUMERIC_COLUMN_MAJOR_MASK = 0x4000;
|
|
|
|
static const uint32_t numeric_type_class[] =
|
|
|
|
{
|
|
|
|
[HLSL_CLASS_SCALAR] = 1,
|
|
|
|
[HLSL_CLASS_VECTOR] = 2,
|
|
|
|
[HLSL_CLASS_MATRIX] = 3,
|
|
|
|
};
|
2024-02-23 05:55:34 -08:00
|
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
2024-02-06 06:11:47 -08:00
|
|
|
uint32_t value = 0;
|
|
|
|
|
|
|
|
switch (type->class)
|
|
|
|
{
|
|
|
|
case HLSL_CLASS_SCALAR:
|
|
|
|
case HLSL_CLASS_VECTOR:
|
|
|
|
case HLSL_CLASS_MATRIX:
|
|
|
|
value |= numeric_type_class[type->class];
|
|
|
|
break;
|
|
|
|
default:
|
2024-03-14 05:31:00 -07:00
|
|
|
hlsl_fixme(ctx, &ctx->location, "Not implemented for type class %u.", type->class);
|
2024-02-06 06:11:47 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-02-27 15:30:51 -08:00
|
|
|
switch (type->e.numeric.type)
|
2024-02-06 06:11:47 -08:00
|
|
|
{
|
|
|
|
case HLSL_TYPE_FLOAT:
|
|
|
|
case HLSL_TYPE_INT:
|
|
|
|
case HLSL_TYPE_UINT:
|
|
|
|
case HLSL_TYPE_BOOL:
|
2024-04-20 15:33:41 -07:00
|
|
|
value |= (fx_4_numeric_base_type[type->e.numeric.type] << NUMERIC_BASE_TYPE_SHIFT);
|
2024-02-06 06:11:47 -08:00
|
|
|
break;
|
|
|
|
default:
|
2024-02-27 15:30:51 -08:00
|
|
|
hlsl_fixme(ctx, &ctx->location, "Not implemented for base type %u.", type->e.numeric.type);
|
2024-02-06 06:11:47 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
value |= (type->dimy & 0x7) << NUMERIC_ROWS_SHIFT;
|
|
|
|
value |= (type->dimx & 0x7) << NUMERIC_COLUMNS_SHIFT;
|
|
|
|
if (type->modifiers & HLSL_MODIFIER_COLUMN_MAJOR)
|
|
|
|
value |= NUMERIC_COLUMN_MAJOR_MASK;
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2024-02-23 15:39:37 -08:00
|
|
|
static const char * get_fx_4_type_name(const struct hlsl_type *type)
|
2024-02-06 06:11:47 -08:00
|
|
|
{
|
2024-02-10 15:02:16 -08:00
|
|
|
static const char * const texture_type_names[] =
|
|
|
|
{
|
|
|
|
[HLSL_SAMPLER_DIM_GENERIC] = "texture",
|
|
|
|
[HLSL_SAMPLER_DIM_1D] = "Texture1D",
|
|
|
|
[HLSL_SAMPLER_DIM_1DARRAY] = "Texture1DArray",
|
|
|
|
[HLSL_SAMPLER_DIM_2D] = "Texture2D",
|
|
|
|
[HLSL_SAMPLER_DIM_2DARRAY] = "Texture2DArray",
|
|
|
|
[HLSL_SAMPLER_DIM_2DMS] = "Texture2DMS",
|
|
|
|
[HLSL_SAMPLER_DIM_2DMSARRAY] = "Texture2DMSArray",
|
|
|
|
[HLSL_SAMPLER_DIM_3D] = "Texture3D",
|
|
|
|
[HLSL_SAMPLER_DIM_CUBE] = "TextureCube",
|
|
|
|
[HLSL_SAMPLER_DIM_CUBEARRAY] = "TextureCubeArray",
|
|
|
|
};
|
2024-02-11 02:04:14 -08:00
|
|
|
static const char * const uav_type_names[] =
|
|
|
|
{
|
|
|
|
[HLSL_SAMPLER_DIM_1D] = "RWTexture1D",
|
|
|
|
[HLSL_SAMPLER_DIM_1DARRAY] = "RWTexture1DArray",
|
|
|
|
[HLSL_SAMPLER_DIM_2D] = "RWTexture2D",
|
|
|
|
[HLSL_SAMPLER_DIM_2DARRAY] = "RWTexture2DArray",
|
|
|
|
[HLSL_SAMPLER_DIM_3D] = "RWTexture3D",
|
|
|
|
[HLSL_SAMPLER_DIM_BUFFER] = "RWBuffer",
|
|
|
|
[HLSL_SAMPLER_DIM_STRUCTURED_BUFFER] = "RWStructuredBuffer",
|
|
|
|
};
|
2024-02-23 15:39:37 -08:00
|
|
|
|
2024-02-27 11:31:20 -08:00
|
|
|
switch (type->class)
|
|
|
|
{
|
2024-04-20 15:33:41 -07:00
|
|
|
case HLSL_CLASS_SAMPLER:
|
|
|
|
return "SamplerState";
|
|
|
|
|
2024-02-27 11:31:20 -08:00
|
|
|
case HLSL_CLASS_TEXTURE:
|
|
|
|
return texture_type_names[type->sampler_dim];
|
2024-02-23 15:39:37 -08:00
|
|
|
|
2024-02-27 11:31:20 -08:00
|
|
|
case HLSL_CLASS_UAV:
|
|
|
|
return uav_type_names[type->sampler_dim];
|
|
|
|
|
2024-06-10 04:05:13 -07:00
|
|
|
case HLSL_CLASS_DEPTH_STENCIL_STATE:
|
|
|
|
return "DepthStencilState";
|
|
|
|
|
2024-02-27 11:31:20 -08:00
|
|
|
case HLSL_CLASS_DEPTH_STENCIL_VIEW:
|
|
|
|
return "DepthStencilView";
|
|
|
|
|
2024-02-27 11:34:52 -08:00
|
|
|
case HLSL_CLASS_RENDER_TARGET_VIEW:
|
|
|
|
return "RenderTargetView";
|
|
|
|
|
2024-02-06 15:33:26 -08:00
|
|
|
case HLSL_CLASS_VERTEX_SHADER:
|
|
|
|
return "VertexShader";
|
|
|
|
|
2024-02-06 17:41:15 -08:00
|
|
|
case HLSL_CLASS_PIXEL_SHADER:
|
|
|
|
return "PixelShader";
|
2024-02-23 15:39:37 -08:00
|
|
|
|
|
|
|
default:
|
|
|
|
return type->name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx)
|
|
|
|
{
|
2024-06-30 14:06:11 -07:00
|
|
|
struct field_offsets
|
|
|
|
{
|
|
|
|
uint32_t name;
|
|
|
|
uint32_t semantic;
|
|
|
|
uint32_t offset;
|
|
|
|
uint32_t type;
|
|
|
|
};
|
2024-06-30 14:31:50 -07:00
|
|
|
uint32_t name_offset, offset, total_size, packed_size, stride, numeric_desc;
|
2024-02-23 15:39:37 -08:00
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
|
2024-06-30 14:06:11 -07:00
|
|
|
struct field_offsets *field_offsets = NULL;
|
|
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
2024-02-23 15:39:37 -08:00
|
|
|
uint32_t elements_count = 0;
|
|
|
|
const char *name;
|
2024-06-30 14:06:11 -07:00
|
|
|
size_t i;
|
2024-02-06 06:11:47 -08:00
|
|
|
|
|
|
|
/* Resolve arrays to element type and number of elements. */
|
|
|
|
if (type->class == HLSL_CLASS_ARRAY)
|
|
|
|
{
|
|
|
|
elements_count = hlsl_get_multiarray_size(type);
|
|
|
|
type = hlsl_get_multiarray_element_type(type);
|
|
|
|
}
|
|
|
|
|
2024-02-23 15:39:37 -08:00
|
|
|
name = get_fx_4_type_name(type);
|
2024-02-10 15:02:16 -08:00
|
|
|
|
|
|
|
name_offset = write_string(name, fx);
|
2024-06-30 14:06:11 -07:00
|
|
|
if (type->class == HLSL_CLASS_STRUCT)
|
|
|
|
{
|
|
|
|
if (!(field_offsets = hlsl_calloc(ctx, type->e.record.field_count, sizeof(*field_offsets))))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (i = 0; i < type->e.record.field_count; ++i)
|
|
|
|
{
|
|
|
|
const struct hlsl_struct_field *field = &type->e.record.fields[i];
|
|
|
|
|
|
|
|
field_offsets[i].name = write_string(field->name, fx);
|
|
|
|
field_offsets[i].semantic = write_string(field->semantic.raw_name, fx);
|
|
|
|
field_offsets[i].offset = field->reg_offset[HLSL_REGSET_NUMERIC];
|
|
|
|
field_offsets[i].type = write_type(field->type, fx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
offset = put_u32_unaligned(buffer, name_offset);
|
|
|
|
|
|
|
|
switch (type->class)
|
|
|
|
{
|
|
|
|
case HLSL_CLASS_SCALAR:
|
|
|
|
case HLSL_CLASS_VECTOR:
|
|
|
|
case HLSL_CLASS_MATRIX:
|
2024-04-09 14:05:33 -07:00
|
|
|
put_u32_unaligned(buffer, 1);
|
|
|
|
break;
|
|
|
|
|
2024-06-10 04:05:13 -07:00
|
|
|
case HLSL_CLASS_DEPTH_STENCIL_STATE:
|
2024-02-27 11:31:20 -08:00
|
|
|
case HLSL_CLASS_DEPTH_STENCIL_VIEW:
|
2024-02-06 17:41:15 -08:00
|
|
|
case HLSL_CLASS_PIXEL_SHADER:
|
2024-04-24 02:12:08 -07:00
|
|
|
case HLSL_CLASS_RASTERIZER_STATE:
|
2024-02-27 11:34:52 -08:00
|
|
|
case HLSL_CLASS_RENDER_TARGET_VIEW:
|
2024-04-20 15:33:41 -07:00
|
|
|
case HLSL_CLASS_SAMPLER:
|
2024-02-05 18:25:57 -08:00
|
|
|
case HLSL_CLASS_TEXTURE:
|
2024-02-05 18:32:37 -08:00
|
|
|
case HLSL_CLASS_UAV:
|
2024-02-06 15:33:26 -08:00
|
|
|
case HLSL_CLASS_VERTEX_SHADER:
|
2024-04-09 14:05:33 -07:00
|
|
|
put_u32_unaligned(buffer, 2);
|
|
|
|
break;
|
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
case HLSL_CLASS_STRUCT:
|
2024-04-09 14:05:33 -07:00
|
|
|
put_u32_unaligned(buffer, 3);
|
2024-02-06 06:11:47 -08:00
|
|
|
break;
|
2024-04-09 14:05:33 -07:00
|
|
|
|
|
|
|
case HLSL_CLASS_ARRAY:
|
2024-02-05 18:35:22 -08:00
|
|
|
case HLSL_CLASS_EFFECT_GROUP:
|
2024-02-06 15:08:01 -08:00
|
|
|
case HLSL_CLASS_PASS:
|
2024-02-06 15:15:48 -08:00
|
|
|
case HLSL_CLASS_TECHNIQUE:
|
2024-05-27 15:31:51 -07:00
|
|
|
case HLSL_CLASS_CONSTANT_BUFFER:
|
2024-04-09 14:05:33 -07:00
|
|
|
vkd3d_unreachable();
|
2024-04-09 14:42:00 -07:00
|
|
|
|
2024-02-05 18:04:02 -08:00
|
|
|
case HLSL_CLASS_STRING:
|
2024-04-09 14:42:00 -07:00
|
|
|
case HLSL_CLASS_VOID:
|
|
|
|
FIXME("Writing type class %u is not implemented.\n", type->class);
|
|
|
|
set_status(fx, VKD3D_ERROR_NOT_IMPLEMENTED);
|
|
|
|
return 0;
|
2024-02-06 06:11:47 -08:00
|
|
|
}
|
|
|
|
|
2024-06-30 14:31:50 -07:00
|
|
|
/* Structures can only contain numeric fields, this is validated during variable declaration. */
|
|
|
|
total_size = stride = type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float);
|
|
|
|
packed_size = 0;
|
|
|
|
if (type->class == HLSL_CLASS_STRUCT || hlsl_is_numeric_type(type))
|
|
|
|
packed_size = hlsl_type_component_count(type) * sizeof(float);
|
2024-02-06 06:11:47 -08:00
|
|
|
if (elements_count)
|
2024-06-30 14:31:50 -07:00
|
|
|
{
|
|
|
|
total_size *= elements_count;
|
|
|
|
packed_size *= elements_count;
|
|
|
|
}
|
2024-02-06 06:11:47 -08:00
|
|
|
stride = align(stride, 4 * sizeof(float));
|
|
|
|
|
|
|
|
put_u32_unaligned(buffer, elements_count);
|
2024-06-30 14:31:50 -07:00
|
|
|
put_u32_unaligned(buffer, total_size);
|
|
|
|
put_u32_unaligned(buffer, stride);
|
|
|
|
put_u32_unaligned(buffer, packed_size);
|
2024-02-06 06:11:47 -08:00
|
|
|
|
|
|
|
if (type->class == HLSL_CLASS_STRUCT)
|
|
|
|
{
|
|
|
|
put_u32_unaligned(buffer, type->e.record.field_count);
|
|
|
|
for (i = 0; i < type->e.record.field_count; ++i)
|
|
|
|
{
|
2024-06-30 14:06:11 -07:00
|
|
|
const struct field_offsets *field = &field_offsets[i];
|
2024-02-06 06:11:47 -08:00
|
|
|
|
2024-06-30 14:06:11 -07:00
|
|
|
put_u32_unaligned(buffer, field->name);
|
|
|
|
put_u32_unaligned(buffer, field->semantic);
|
|
|
|
put_u32_unaligned(buffer, field->offset);
|
|
|
|
put_u32_unaligned(buffer, field->type);
|
2024-02-06 06:11:47 -08:00
|
|
|
}
|
2024-06-30 14:39:30 -07:00
|
|
|
|
|
|
|
if (ctx->profile->major_version == 5)
|
|
|
|
{
|
|
|
|
put_u32_unaligned(buffer, 0); /* Base class type */
|
|
|
|
put_u32_unaligned(buffer, 0); /* Interface count */
|
|
|
|
}
|
2024-02-06 06:11:47 -08:00
|
|
|
}
|
2024-02-05 18:25:57 -08:00
|
|
|
else if (type->class == HLSL_CLASS_TEXTURE)
|
2024-02-06 06:11:47 -08:00
|
|
|
{
|
2024-02-10 15:02:16 -08:00
|
|
|
static const uint32_t texture_type[] =
|
|
|
|
{
|
|
|
|
[HLSL_SAMPLER_DIM_GENERIC] = 9,
|
|
|
|
[HLSL_SAMPLER_DIM_1D] = 10,
|
|
|
|
[HLSL_SAMPLER_DIM_1DARRAY] = 11,
|
|
|
|
[HLSL_SAMPLER_DIM_2D] = 12,
|
|
|
|
[HLSL_SAMPLER_DIM_2DARRAY] = 13,
|
|
|
|
[HLSL_SAMPLER_DIM_2DMS] = 14,
|
|
|
|
[HLSL_SAMPLER_DIM_2DMSARRAY] = 15,
|
|
|
|
[HLSL_SAMPLER_DIM_3D] = 16,
|
|
|
|
[HLSL_SAMPLER_DIM_CUBE] = 17,
|
|
|
|
[HLSL_SAMPLER_DIM_CUBEARRAY] = 23,
|
|
|
|
};
|
2024-02-05 18:25:57 -08:00
|
|
|
|
|
|
|
put_u32_unaligned(buffer, texture_type[type->sampler_dim]);
|
|
|
|
}
|
2024-04-20 15:33:41 -07:00
|
|
|
else if (type->class == HLSL_CLASS_SAMPLER)
|
|
|
|
{
|
|
|
|
put_u32_unaligned(buffer, 21);
|
|
|
|
}
|
2024-02-05 18:32:37 -08:00
|
|
|
else if (type->class == HLSL_CLASS_UAV)
|
2024-02-05 18:25:57 -08:00
|
|
|
{
|
2024-02-11 02:04:14 -08:00
|
|
|
static const uint32_t uav_type[] =
|
|
|
|
{
|
|
|
|
[HLSL_SAMPLER_DIM_1D] = 31,
|
|
|
|
[HLSL_SAMPLER_DIM_1DARRAY] = 32,
|
|
|
|
[HLSL_SAMPLER_DIM_2D] = 33,
|
|
|
|
[HLSL_SAMPLER_DIM_2DARRAY] = 34,
|
|
|
|
[HLSL_SAMPLER_DIM_3D] = 35,
|
|
|
|
[HLSL_SAMPLER_DIM_BUFFER] = 36,
|
|
|
|
[HLSL_SAMPLER_DIM_STRUCTURED_BUFFER] = 40,
|
|
|
|
};
|
2024-02-09 13:42:23 -08:00
|
|
|
|
2024-02-05 18:32:37 -08:00
|
|
|
put_u32_unaligned(buffer, uav_type[type->sampler_dim]);
|
|
|
|
}
|
2024-02-27 11:31:20 -08:00
|
|
|
else if (type->class == HLSL_CLASS_DEPTH_STENCIL_VIEW)
|
|
|
|
{
|
|
|
|
put_u32_unaligned(buffer, 20);
|
|
|
|
}
|
2024-02-27 11:34:52 -08:00
|
|
|
else if (type->class == HLSL_CLASS_RENDER_TARGET_VIEW)
|
|
|
|
{
|
|
|
|
put_u32_unaligned(buffer, 19);
|
|
|
|
}
|
2024-02-06 17:41:15 -08:00
|
|
|
else if (type->class == HLSL_CLASS_PIXEL_SHADER)
|
2024-02-06 15:33:26 -08:00
|
|
|
{
|
2024-02-06 17:41:15 -08:00
|
|
|
put_u32_unaligned(buffer, 5);
|
2024-02-06 15:33:26 -08:00
|
|
|
}
|
2024-02-06 17:41:15 -08:00
|
|
|
else if (type->class == HLSL_CLASS_VERTEX_SHADER)
|
2024-02-05 18:32:37 -08:00
|
|
|
{
|
2024-02-06 17:41:15 -08:00
|
|
|
put_u32_unaligned(buffer, 6);
|
2024-02-06 06:11:47 -08:00
|
|
|
}
|
2024-06-10 04:18:43 -07:00
|
|
|
else if (type->class == HLSL_CLASS_RASTERIZER_STATE)
|
|
|
|
{
|
|
|
|
put_u32_unaligned(buffer, 4);
|
|
|
|
}
|
2024-06-10 04:05:13 -07:00
|
|
|
else if (type->class == HLSL_CLASS_DEPTH_STENCIL_STATE)
|
|
|
|
{
|
|
|
|
put_u32_unaligned(buffer, 3);
|
|
|
|
}
|
2024-02-27 11:34:52 -08:00
|
|
|
else if (hlsl_is_numeric_type(type))
|
2024-02-06 06:11:47 -08:00
|
|
|
{
|
|
|
|
numeric_desc = get_fx_4_numeric_type_description(type, fx);
|
|
|
|
put_u32_unaligned(buffer, numeric_desc);
|
|
|
|
}
|
2024-02-27 11:34:52 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
FIXME("Type %u is not supported.\n", type->class);
|
|
|
|
set_status(fx, VKD3D_ERROR_NOT_IMPLEMENTED);
|
|
|
|
}
|
2024-02-06 06:11:47 -08:00
|
|
|
|
2024-06-30 14:06:11 -07:00
|
|
|
vkd3d_free(field_offsets);
|
2024-02-06 06:11:47 -08:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
static void write_fx_4_technique(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
2023-11-10 16:14:03 -08:00
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
|
|
|
uint32_t name_offset, count = 0;
|
|
|
|
struct hlsl_ir_var *pass;
|
|
|
|
uint32_t count_offset;
|
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
name_offset = write_string(var->name, fx);
|
2023-11-10 16:14:03 -08:00
|
|
|
put_u32(buffer, name_offset);
|
|
|
|
count_offset = put_u32(buffer, 0);
|
2024-06-15 14:44:08 -07:00
|
|
|
write_fx_4_annotations(var->annotations, fx);
|
2023-11-10 16:14:03 -08:00
|
|
|
|
2024-06-15 14:44:08 -07:00
|
|
|
count = 0;
|
2023-11-10 16:14:03 -08:00
|
|
|
LIST_FOR_EACH_ENTRY(pass, &var->scope->vars, struct hlsl_ir_var, scope_entry)
|
|
|
|
{
|
|
|
|
write_pass(pass, fx);
|
|
|
|
++count;
|
|
|
|
}
|
2023-11-05 13:07:01 -08:00
|
|
|
|
2023-11-10 16:14:03 -08:00
|
|
|
set_u32(buffer, count_offset, count);
|
2023-11-05 13:07:01 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void write_techniques(struct hlsl_scope *scope, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
|
|
|
{
|
2024-01-16 03:09:41 -08:00
|
|
|
if (technique_matches_version(var, fx))
|
2023-11-05 13:07:01 -08:00
|
|
|
{
|
2024-01-16 03:17:06 -08:00
|
|
|
fx->ops->write_technique(var, fx);
|
2023-11-05 13:07:01 -08:00
|
|
|
++fx->technique_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
set_status(fx, fx->unstructured.status);
|
|
|
|
set_status(fx, fx->structured.status);
|
|
|
|
}
|
|
|
|
|
2024-01-25 09:18:40 -08:00
|
|
|
static void write_group(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
2024-01-12 05:26:39 -08:00
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
2024-01-25 09:18:40 -08:00
|
|
|
uint32_t name_offset = write_string(var ? var->name : NULL, fx);
|
2024-01-12 05:26:39 -08:00
|
|
|
uint32_t count_offset, count;
|
|
|
|
|
|
|
|
put_u32(buffer, name_offset);
|
|
|
|
count_offset = put_u32(buffer, 0); /* Technique count */
|
2024-06-15 14:44:08 -07:00
|
|
|
write_fx_4_annotations(var ? var->annotations : NULL, fx);
|
2024-01-12 05:26:39 -08:00
|
|
|
|
|
|
|
count = fx->technique_count;
|
2024-01-25 09:18:40 -08:00
|
|
|
write_techniques(var ? var->scope : fx->ctx->globals, fx);
|
2024-01-12 05:26:39 -08:00
|
|
|
set_u32(buffer, count_offset, fx->technique_count - count);
|
|
|
|
|
|
|
|
++fx->group_count;
|
|
|
|
}
|
|
|
|
|
2024-01-25 09:18:40 -08:00
|
|
|
static void write_groups(struct fx_write_context *fx)
|
2024-01-12 05:26:39 -08:00
|
|
|
{
|
2024-01-25 09:18:40 -08:00
|
|
|
struct hlsl_scope *scope = fx->ctx->globals;
|
2024-01-12 05:26:39 -08:00
|
|
|
bool needs_default_group = false;
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
|
|
|
{
|
|
|
|
if (technique_matches_version(var, fx))
|
|
|
|
{
|
|
|
|
needs_default_group = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (needs_default_group)
|
2024-01-25 09:18:40 -08:00
|
|
|
write_group(NULL, fx);
|
2024-01-12 05:26:39 -08:00
|
|
|
LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
|
|
|
{
|
|
|
|
const struct hlsl_type *type = var->data_type;
|
|
|
|
|
2024-02-05 18:35:22 -08:00
|
|
|
if (type->class == HLSL_CLASS_EFFECT_GROUP)
|
2024-01-25 09:18:40 -08:00
|
|
|
write_group(var, fx);
|
2024-01-12 05:26:39 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
static uint32_t write_fx_2_string(const char *string, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
|
|
|
|
const char *s = string ? string : "";
|
2024-03-11 10:56:50 -07:00
|
|
|
static const char tail[3];
|
2024-01-16 03:17:06 -08:00
|
|
|
uint32_t size, offset;
|
|
|
|
|
|
|
|
size = strlen(s) + 1;
|
|
|
|
offset = put_u32(buffer, size);
|
|
|
|
bytecode_put_bytes(buffer, s, size);
|
2024-03-11 10:56:50 -07:00
|
|
|
size %= 4;
|
|
|
|
if (size)
|
|
|
|
bytecode_put_bytes_unaligned(buffer, tail, 4 - size);
|
2024-01-16 03:17:06 -08:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2024-02-13 03:52:11 -08:00
|
|
|
static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *name, const struct hlsl_semantic *semantic,
|
|
|
|
struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
|
|
|
|
uint32_t semantic_offset, offset, elements_count = 0, name_offset;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
/* Resolve arrays to element type and number of elements. */
|
|
|
|
if (type->class == HLSL_CLASS_ARRAY)
|
|
|
|
{
|
|
|
|
elements_count = hlsl_get_multiarray_size(type);
|
|
|
|
type = hlsl_get_multiarray_element_type(type);
|
|
|
|
}
|
|
|
|
|
|
|
|
name_offset = write_string(name, fx);
|
2024-07-10 10:24:48 -07:00
|
|
|
semantic_offset = semantic->raw_name ? write_string(semantic->raw_name, fx) : 0;
|
2024-02-13 03:52:11 -08:00
|
|
|
|
|
|
|
offset = put_u32(buffer, hlsl_sm1_base_type(type));
|
|
|
|
put_u32(buffer, hlsl_sm1_class(type));
|
|
|
|
put_u32(buffer, name_offset);
|
|
|
|
put_u32(buffer, semantic_offset);
|
|
|
|
put_u32(buffer, elements_count);
|
|
|
|
|
|
|
|
switch (type->class)
|
|
|
|
{
|
|
|
|
case HLSL_CLASS_VECTOR:
|
|
|
|
put_u32(buffer, type->dimx);
|
|
|
|
put_u32(buffer, type->dimy);
|
|
|
|
break;
|
|
|
|
case HLSL_CLASS_SCALAR:
|
|
|
|
case HLSL_CLASS_MATRIX:
|
|
|
|
put_u32(buffer, type->dimy);
|
|
|
|
put_u32(buffer, type->dimx);
|
|
|
|
break;
|
|
|
|
case HLSL_CLASS_STRUCT:
|
|
|
|
put_u32(buffer, type->e.record.field_count);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type->class == HLSL_CLASS_STRUCT)
|
|
|
|
{
|
|
|
|
for (i = 0; i < type->e.record.field_count; ++i)
|
|
|
|
{
|
|
|
|
const struct hlsl_struct_field *field = &type->e.record.fields[i];
|
2024-04-09 14:40:56 -07:00
|
|
|
|
|
|
|
/* Validated in check_invalid_object_fields(). */
|
|
|
|
assert(hlsl_is_numeric_type(field->type));
|
2024-02-13 03:52:11 -08:00
|
|
|
write_fx_2_parameter(field->type, field->name, &field->semantic, fx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
2023-11-15 14:31:01 -08:00
|
|
|
uint32_t name_offset, count_offset, count = 0;
|
|
|
|
struct hlsl_ir_var *pass;
|
2024-01-16 03:17:06 -08:00
|
|
|
|
|
|
|
name_offset = write_string(var->name, fx);
|
|
|
|
put_u32(buffer, name_offset);
|
|
|
|
put_u32(buffer, 0); /* Annotation count. */
|
2023-11-15 14:31:01 -08:00
|
|
|
count_offset = put_u32(buffer, 0); /* Pass count. */
|
2024-01-16 03:17:06 -08:00
|
|
|
|
|
|
|
/* FIXME: annotations */
|
2023-11-15 14:31:01 -08:00
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY(pass, &var->scope->vars, struct hlsl_ir_var, scope_entry)
|
|
|
|
{
|
|
|
|
write_pass(pass, fx);
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_u32(buffer, count_offset, count);
|
2024-01-16 03:17:06 -08:00
|
|
|
}
|
|
|
|
|
2024-02-13 03:52:11 -08:00
|
|
|
static uint32_t get_fx_2_type_size(const struct hlsl_type *type)
|
|
|
|
{
|
|
|
|
uint32_t size = 0, elements_count;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (type->class == HLSL_CLASS_ARRAY)
|
|
|
|
{
|
|
|
|
elements_count = hlsl_get_multiarray_size(type);
|
|
|
|
type = hlsl_get_multiarray_element_type(type);
|
|
|
|
return get_fx_2_type_size(type) * elements_count;
|
|
|
|
}
|
|
|
|
else if (type->class == HLSL_CLASS_STRUCT)
|
|
|
|
{
|
|
|
|
for (i = 0; i < type->e.record.field_count; ++i)
|
|
|
|
{
|
|
|
|
const struct hlsl_struct_field *field = &type->e.record.fields[i];
|
|
|
|
size += get_fx_2_type_size(field->type);
|
|
|
|
}
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return type->dimx * type->dimy * sizeof(float);
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
|
|
|
|
const struct hlsl_type *type = var->data_type;
|
2024-04-09 17:01:34 -07:00
|
|
|
uint32_t offset, size, elements_count = 1;
|
2024-02-13 03:52:11 -08:00
|
|
|
|
|
|
|
size = get_fx_2_type_size(type);
|
|
|
|
|
|
|
|
if (type->class == HLSL_CLASS_ARRAY)
|
|
|
|
{
|
|
|
|
elements_count = hlsl_get_multiarray_size(type);
|
|
|
|
type = hlsl_get_multiarray_element_type(type);
|
|
|
|
}
|
|
|
|
|
2024-04-09 17:01:34 -07:00
|
|
|
/* Note that struct fields must all be numeric;
|
|
|
|
* this was validated in check_invalid_object_fields(). */
|
|
|
|
switch (type->class)
|
2024-02-13 03:52:11 -08:00
|
|
|
{
|
2024-04-09 17:01:34 -07:00
|
|
|
case HLSL_CLASS_SCALAR:
|
|
|
|
case HLSL_CLASS_VECTOR:
|
|
|
|
case HLSL_CLASS_MATRIX:
|
|
|
|
case HLSL_CLASS_STRUCT:
|
|
|
|
/* FIXME: write actual initial value */
|
2024-04-08 13:15:20 -07:00
|
|
|
if (var->default_values)
|
|
|
|
hlsl_fixme(fx->ctx, &var->loc, "Write default values.\n");
|
|
|
|
|
2024-04-09 17:01:34 -07:00
|
|
|
offset = put_u32(buffer, 0);
|
|
|
|
|
|
|
|
for (uint32_t i = 1; i < size / sizeof(uint32_t); ++i)
|
|
|
|
put_u32(buffer, 0);
|
|
|
|
break;
|
2024-02-13 03:52:11 -08:00
|
|
|
|
2024-04-09 17:01:34 -07:00
|
|
|
default:
|
|
|
|
/* Objects are given sequential ids. */
|
|
|
|
offset = put_u32(buffer, fx->object_variable_count++);
|
|
|
|
for (uint32_t i = 1; i < elements_count; ++i)
|
|
|
|
put_u32(buffer, fx->object_variable_count++);
|
|
|
|
break;
|
2024-02-13 03:52:11 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2024-04-09 14:40:56 -07:00
|
|
|
static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type *type,
|
|
|
|
const struct vkd3d_shader_location *loc)
|
2024-03-19 02:46:31 -07:00
|
|
|
{
|
2024-04-09 14:40:56 -07:00
|
|
|
switch (type->class)
|
2024-03-19 02:46:31 -07:00
|
|
|
{
|
2024-04-09 14:40:56 -07:00
|
|
|
case HLSL_CLASS_STRUCT:
|
|
|
|
/* Note that the fields must all be numeric; this was validated in
|
|
|
|
* check_invalid_object_fields(). */
|
2024-03-19 02:46:31 -07:00
|
|
|
return true;
|
2024-04-09 14:40:56 -07:00
|
|
|
|
|
|
|
case HLSL_CLASS_SCALAR:
|
|
|
|
case HLSL_CLASS_VECTOR:
|
|
|
|
case HLSL_CLASS_MATRIX:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case HLSL_CLASS_ARRAY:
|
|
|
|
return is_type_supported_fx_2(ctx, type->e.array.type, loc);
|
|
|
|
|
2024-02-05 18:25:57 -08:00
|
|
|
case HLSL_CLASS_TEXTURE:
|
|
|
|
switch (type->sampler_dim)
|
|
|
|
{
|
|
|
|
case HLSL_SAMPLER_DIM_1D:
|
|
|
|
case HLSL_SAMPLER_DIM_2D:
|
|
|
|
case HLSL_SAMPLER_DIM_3D:
|
|
|
|
case HLSL_SAMPLER_DIM_CUBE:
|
|
|
|
case HLSL_SAMPLER_DIM_GENERIC:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2024-02-06 17:41:15 -08:00
|
|
|
case HLSL_CLASS_PIXEL_SHADER:
|
2024-02-05 18:13:17 -08:00
|
|
|
case HLSL_CLASS_SAMPLER:
|
2024-02-05 18:04:02 -08:00
|
|
|
case HLSL_CLASS_STRING:
|
2024-02-06 15:33:26 -08:00
|
|
|
case HLSL_CLASS_VERTEX_SHADER:
|
2024-02-05 18:04:02 -08:00
|
|
|
hlsl_fixme(ctx, loc, "Write fx 2.0 parameter class %#x.", type->class);
|
|
|
|
return false;
|
|
|
|
|
2024-06-10 04:05:13 -07:00
|
|
|
case HLSL_CLASS_DEPTH_STENCIL_STATE:
|
2024-02-27 11:31:20 -08:00
|
|
|
case HLSL_CLASS_DEPTH_STENCIL_VIEW:
|
2024-02-05 18:32:37 -08:00
|
|
|
case HLSL_CLASS_UAV:
|
2024-04-24 02:12:08 -07:00
|
|
|
case HLSL_CLASS_RASTERIZER_STATE:
|
2024-02-27 11:34:52 -08:00
|
|
|
case HLSL_CLASS_RENDER_TARGET_VIEW:
|
2024-04-09 14:42:00 -07:00
|
|
|
case HLSL_CLASS_VOID:
|
|
|
|
return false;
|
2024-02-05 18:35:22 -08:00
|
|
|
|
|
|
|
case HLSL_CLASS_EFFECT_GROUP:
|
2024-02-06 15:08:01 -08:00
|
|
|
case HLSL_CLASS_PASS:
|
2024-02-06 15:15:48 -08:00
|
|
|
case HLSL_CLASS_TECHNIQUE:
|
2024-05-27 15:31:51 -07:00
|
|
|
case HLSL_CLASS_CONSTANT_BUFFER:
|
2024-02-05 18:35:22 -08:00
|
|
|
/* This cannot appear as an extern variable. */
|
|
|
|
break;
|
2024-03-19 02:46:31 -07:00
|
|
|
}
|
|
|
|
|
2024-04-09 14:40:56 -07:00
|
|
|
vkd3d_unreachable();
|
2024-03-19 02:46:31 -07:00
|
|
|
}
|
|
|
|
|
2024-02-13 03:52:11 -08:00
|
|
|
static void write_fx_2_parameters(struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
2024-03-18 17:09:58 -07:00
|
|
|
uint32_t desc_offset, value_offset, flags;
|
2024-03-14 05:49:14 -07:00
|
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
2024-02-13 03:52:11 -08:00
|
|
|
struct hlsl_ir_var *var;
|
2024-03-18 17:09:58 -07:00
|
|
|
enum fx_2_parameter_flags
|
|
|
|
{
|
|
|
|
IS_SHARED = 0x1,
|
|
|
|
};
|
2024-02-13 03:52:11 -08:00
|
|
|
|
2024-03-14 05:49:14 -07:00
|
|
|
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
|
2024-02-13 03:52:11 -08:00
|
|
|
{
|
2024-04-09 14:40:56 -07:00
|
|
|
if (!is_type_supported_fx_2(ctx, var->data_type, &var->loc))
|
2024-03-19 02:46:31 -07:00
|
|
|
continue;
|
|
|
|
|
2024-02-13 03:52:11 -08:00
|
|
|
desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, fx);
|
|
|
|
value_offset = write_fx_2_initial_value(var, fx);
|
|
|
|
|
2024-03-18 17:09:58 -07:00
|
|
|
flags = 0;
|
|
|
|
if (var->storage_modifiers & HLSL_STORAGE_SHARED)
|
|
|
|
flags |= IS_SHARED;
|
|
|
|
|
2024-02-13 03:52:11 -08:00
|
|
|
put_u32(buffer, desc_offset); /* Parameter description */
|
|
|
|
put_u32(buffer, value_offset); /* Value */
|
2024-03-18 17:09:58 -07:00
|
|
|
put_u32(buffer, flags); /* Flags */
|
2024-02-13 03:52:11 -08:00
|
|
|
|
|
|
|
put_u32(buffer, 0); /* Annotations count */
|
2024-03-14 05:49:14 -07:00
|
|
|
if (has_annotations(var))
|
|
|
|
hlsl_fixme(ctx, &ctx->location, "Writing annotations for parameters is not implemented.");
|
2024-02-13 03:52:11 -08:00
|
|
|
|
|
|
|
++fx->parameter_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
static const struct fx_write_context_ops fx_2_ops =
|
|
|
|
{
|
|
|
|
.write_string = write_fx_2_string,
|
|
|
|
.write_technique = write_fx_2_technique,
|
2023-11-15 14:31:01 -08:00
|
|
|
.write_pass = write_fx_2_pass,
|
2024-01-16 03:17:06 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
|
|
|
{
|
2024-07-11 05:02:31 -07:00
|
|
|
uint32_t offset, size, technique_count, pass_count, parameter_count, object_count;
|
2024-01-16 03:17:06 -08:00
|
|
|
struct vkd3d_bytecode_buffer buffer = { 0 };
|
|
|
|
struct vkd3d_bytecode_buffer *structured;
|
|
|
|
struct fx_write_context fx;
|
|
|
|
|
|
|
|
fx_write_context_init(ctx, &fx_2_ops, &fx);
|
2024-03-13 03:37:17 -07:00
|
|
|
fx.object_variable_count = 1;
|
2024-01-16 03:17:06 -08:00
|
|
|
structured = &fx.structured;
|
|
|
|
|
|
|
|
/* First entry is always zeroed and skipped. */
|
|
|
|
put_u32(&fx.unstructured, 0);
|
|
|
|
|
|
|
|
put_u32(&buffer, 0xfeff0901); /* Version. */
|
|
|
|
offset = put_u32(&buffer, 0);
|
|
|
|
|
2024-02-13 03:52:11 -08:00
|
|
|
parameter_count = put_u32(structured, 0); /* Parameter count */
|
2024-01-16 03:17:06 -08:00
|
|
|
technique_count = put_u32(structured, 0);
|
2024-07-11 05:02:31 -07:00
|
|
|
pass_count = put_u32(structured, 0);
|
2024-03-13 03:37:17 -07:00
|
|
|
object_count = put_u32(structured, 0);
|
2024-01-16 03:17:06 -08:00
|
|
|
|
2024-02-13 03:52:11 -08:00
|
|
|
write_fx_2_parameters(&fx);
|
|
|
|
set_u32(structured, parameter_count, fx.parameter_count);
|
2024-03-13 03:37:17 -07:00
|
|
|
set_u32(structured, object_count, fx.object_variable_count);
|
2024-01-16 03:17:06 -08:00
|
|
|
|
|
|
|
write_techniques(ctx->globals, &fx);
|
|
|
|
set_u32(structured, technique_count, fx.technique_count);
|
2024-07-11 05:02:31 -07:00
|
|
|
set_u32(structured, pass_count, fx.pass_count);
|
2024-01-16 03:17:06 -08:00
|
|
|
|
|
|
|
put_u32(structured, 0); /* String count */
|
|
|
|
put_u32(structured, 0); /* Resource count */
|
|
|
|
|
|
|
|
/* TODO: strings */
|
|
|
|
/* TODO: resources */
|
|
|
|
|
|
|
|
size = align(fx.unstructured.size, 4);
|
|
|
|
set_u32(&buffer, offset, size);
|
|
|
|
|
|
|
|
bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size);
|
|
|
|
bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size);
|
|
|
|
|
|
|
|
vkd3d_free(fx.unstructured.data);
|
|
|
|
vkd3d_free(fx.structured.data);
|
|
|
|
|
2024-02-22 17:11:38 -08:00
|
|
|
if (!fx.technique_count)
|
|
|
|
hlsl_error(ctx, &ctx->location, VKD3D_SHADER_ERROR_HLSL_MISSING_TECHNIQUE, "No techniques found.");
|
|
|
|
|
|
|
|
if (fx.status < 0)
|
|
|
|
ctx->result = fx.status;
|
|
|
|
|
|
|
|
if (!ctx->result)
|
2024-01-16 03:17:06 -08:00
|
|
|
{
|
|
|
|
out->code = buffer.data;
|
|
|
|
out->size = buffer.size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fx_write_context_cleanup(&fx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct fx_write_context_ops fx_4_ops =
|
|
|
|
{
|
|
|
|
.write_string = write_fx_4_string,
|
|
|
|
.write_technique = write_fx_4_technique,
|
2023-11-15 14:31:01 -08:00
|
|
|
.write_pass = write_fx_4_pass,
|
2024-06-15 14:44:08 -07:00
|
|
|
.write_annotation = write_fx_4_annotation,
|
2024-02-24 16:08:46 -08:00
|
|
|
.are_child_effects_supported = true,
|
2024-01-16 03:17:06 -08:00
|
|
|
};
|
|
|
|
|
2024-06-13 15:59:57 -07:00
|
|
|
static uint32_t write_fx_4_default_value(struct hlsl_type *value_type, struct hlsl_default_value *value,
|
|
|
|
struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
const struct hlsl_type *type = hlsl_get_multiarray_element_type(value_type);
|
|
|
|
uint32_t elements_count = hlsl_get_multiarray_size(value_type), i, j;
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
|
|
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
|
|
|
uint32_t offset = buffer->size;
|
|
|
|
unsigned int comp_count;
|
|
|
|
|
|
|
|
if (!value)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
comp_count = hlsl_type_component_count(type);
|
|
|
|
|
|
|
|
for (i = 0; i < elements_count; ++i)
|
|
|
|
{
|
|
|
|
switch (type->class)
|
|
|
|
{
|
|
|
|
case HLSL_CLASS_SCALAR:
|
|
|
|
case HLSL_CLASS_VECTOR:
|
|
|
|
case HLSL_CLASS_MATRIX:
|
|
|
|
{
|
|
|
|
switch (type->e.numeric.type)
|
|
|
|
{
|
|
|
|
case HLSL_TYPE_FLOAT:
|
|
|
|
case HLSL_TYPE_INT:
|
|
|
|
case HLSL_TYPE_UINT:
|
|
|
|
case HLSL_TYPE_BOOL:
|
|
|
|
|
|
|
|
for (j = 0; j < comp_count; ++j)
|
|
|
|
{
|
|
|
|
put_u32_unaligned(buffer, value->value.u);
|
|
|
|
value++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
hlsl_fixme(ctx, &ctx->location, "Writing default values for numeric type %u is not implemented.",
|
|
|
|
type->e.numeric.type);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case HLSL_CLASS_STRUCT:
|
|
|
|
{
|
|
|
|
struct hlsl_struct_field *fields = type->e.record.fields;
|
|
|
|
|
|
|
|
for (j = 0; j < type->e.record.field_count; ++j)
|
|
|
|
{
|
|
|
|
write_fx_4_default_value(fields[i].type, value, fx);
|
|
|
|
value += hlsl_type_component_count(fields[i].type);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
hlsl_fixme(ctx, &ctx->location, "Writing default values for class %u is not implemented.", type->class);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2024-04-21 10:06:55 -07:00
|
|
|
static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, bool shared, struct fx_write_context *fx)
|
2024-02-06 06:11:47 -08:00
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
2024-04-21 10:06:55 -07:00
|
|
|
uint32_t name_offset, type_offset, value_offset;
|
2024-02-06 06:11:47 -08:00
|
|
|
uint32_t semantic_offset, flags = 0;
|
2024-02-09 13:42:23 -08:00
|
|
|
enum fx_4_numeric_variable_flags
|
2024-02-06 06:11:47 -08:00
|
|
|
{
|
|
|
|
HAS_EXPLICIT_BIND_POINT = 0x4,
|
|
|
|
};
|
|
|
|
|
2024-06-01 15:15:48 -07:00
|
|
|
if (var->has_explicit_bind_point)
|
2024-02-06 06:11:47 -08:00
|
|
|
flags |= HAS_EXPLICIT_BIND_POINT;
|
|
|
|
|
|
|
|
type_offset = write_type(var->data_type, fx);
|
|
|
|
name_offset = write_string(var->name, fx);
|
2024-05-31 03:26:45 -07:00
|
|
|
semantic_offset = write_string(var->semantic.raw_name, fx);
|
2024-02-06 06:11:47 -08:00
|
|
|
|
|
|
|
put_u32(buffer, name_offset);
|
|
|
|
put_u32(buffer, type_offset);
|
|
|
|
|
|
|
|
semantic_offset = put_u32(buffer, semantic_offset); /* Semantic */
|
2024-06-01 15:23:12 -07:00
|
|
|
put_u32(buffer, var->buffer_offset * 4); /* Offset in the constant buffer, in bytes. */
|
2024-06-13 15:59:57 -07:00
|
|
|
value_offset = put_u32(buffer, 0);
|
2024-02-06 06:11:47 -08:00
|
|
|
put_u32(buffer, flags); /* Flags */
|
|
|
|
|
2024-04-21 10:06:55 -07:00
|
|
|
if (shared)
|
|
|
|
{
|
|
|
|
fx->shared_numeric_variable_count++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-06-13 15:59:57 -07:00
|
|
|
uint32_t offset = write_fx_4_default_value(var->data_type, var->default_values, fx);
|
|
|
|
set_u32(buffer, value_offset, offset);
|
2024-04-21 10:06:55 -07:00
|
|
|
|
2024-06-15 14:44:08 -07:00
|
|
|
write_fx_4_annotations(var->annotations, fx);
|
2024-04-21 10:06:55 -07:00
|
|
|
|
|
|
|
fx->numeric_variable_count++;
|
|
|
|
}
|
2024-02-06 06:11:47 -08:00
|
|
|
}
|
|
|
|
|
2024-06-15 14:44:08 -07:00
|
|
|
static void write_fx_4_annotation(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type);
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
|
|
|
uint32_t name_offset, type_offset, offset;
|
|
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
|
|
|
|
|
|
|
name_offset = write_string(var->name, fx);
|
|
|
|
type_offset = write_type(var->data_type, fx);
|
|
|
|
|
|
|
|
put_u32(buffer, name_offset);
|
|
|
|
put_u32(buffer, type_offset);
|
|
|
|
|
|
|
|
if (hlsl_is_numeric_type(type))
|
|
|
|
{
|
|
|
|
offset = write_fx_4_default_value(var->data_type, var->default_values, fx);
|
|
|
|
put_u32(buffer, offset);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hlsl_fixme(ctx, &var->loc, "Writing annotations for type class %u is not implemented.", type->class);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-20 15:33:41 -07:00
|
|
|
struct rhs_named_value
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
unsigned int value;
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool get_fx_4_state_enum_value(const struct rhs_named_value *pairs,
|
|
|
|
const char *name, unsigned int *value)
|
|
|
|
{
|
|
|
|
while (pairs->name)
|
|
|
|
{
|
|
|
|
if (!ascii_strcasecmp(pairs->name, name))
|
|
|
|
{
|
|
|
|
*value = pairs->value;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
pairs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t write_fx_4_state_numeric_value(struct hlsl_ir_constant *value, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
|
|
|
|
struct hlsl_type *data_type = value->node.data_type;
|
|
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
|
|
|
uint32_t i, type, offset;
|
|
|
|
unsigned int count = hlsl_type_component_count(data_type);
|
|
|
|
|
|
|
|
offset = put_u32_unaligned(buffer, count);
|
|
|
|
|
|
|
|
for (i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
if (hlsl_is_numeric_type(data_type))
|
|
|
|
{
|
|
|
|
switch (data_type->e.numeric.type)
|
|
|
|
{
|
|
|
|
case HLSL_TYPE_FLOAT:
|
|
|
|
case HLSL_TYPE_INT:
|
|
|
|
case HLSL_TYPE_UINT:
|
|
|
|
case HLSL_TYPE_BOOL:
|
|
|
|
type = fx_4_numeric_base_type[data_type->e.numeric.type];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
type = 0;
|
|
|
|
hlsl_fixme(ctx, &ctx->location, "Unsupported numeric state value type %u.", data_type->e.numeric.type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
put_u32_unaligned(buffer, type);
|
|
|
|
put_u32_unaligned(buffer, value->value.u[i].u);
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry,
|
|
|
|
struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
uint32_t value_offset = 0, assignment_type = 0, rhs_offset;
|
|
|
|
uint32_t type_offset;
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
|
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
|
|
|
struct hlsl_ir_node *value = entry->args->node;
|
|
|
|
|
|
|
|
if (entry->lhs_has_index)
|
|
|
|
hlsl_fixme(ctx, &var->loc, "Unsupported assignment to array element.");
|
|
|
|
|
|
|
|
put_u32(buffer, entry->name_id);
|
|
|
|
put_u32(buffer, 0); /* TODO: destination index */
|
|
|
|
type_offset = put_u32(buffer, 0);
|
|
|
|
rhs_offset = put_u32(buffer, 0);
|
|
|
|
|
|
|
|
switch (value->type)
|
|
|
|
{
|
|
|
|
case HLSL_IR_CONSTANT:
|
|
|
|
{
|
|
|
|
struct hlsl_ir_constant *c = hlsl_ir_constant(value);
|
|
|
|
|
|
|
|
value_offset = write_fx_4_state_numeric_value(c, fx);
|
|
|
|
assignment_type = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
hlsl_fixme(ctx, &var->loc, "Unsupported assignment type for state %s.", entry->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
set_u32(buffer, type_offset, assignment_type);
|
|
|
|
set_u32(buffer, rhs_offset, value_offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool state_block_contains_state(const char *name, unsigned int start, struct hlsl_state_block *block)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = start; i < block->count; ++i)
|
|
|
|
{
|
2024-03-19 12:06:12 -07:00
|
|
|
if (block->entries[i]->is_function_call)
|
|
|
|
continue;
|
|
|
|
|
2024-04-20 15:33:41 -07:00
|
|
|
if (!ascii_strcasecmp(block->entries[i]->name, name))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct replace_state_context
|
|
|
|
{
|
|
|
|
const struct rhs_named_value *values;
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool replace_state_block_constant(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
|
|
|
|
{
|
|
|
|
struct replace_state_context *replace_context = context;
|
|
|
|
struct hlsl_ir_stateblock_constant *state_constant;
|
|
|
|
struct hlsl_ir_node *c;
|
|
|
|
unsigned int value;
|
|
|
|
|
|
|
|
if (!replace_context->values)
|
|
|
|
return false;
|
|
|
|
if (instr->type != HLSL_IR_STATEBLOCK_CONSTANT)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
state_constant = hlsl_ir_stateblock_constant(instr);
|
|
|
|
if (!get_fx_4_state_enum_value(replace_context->values, state_constant->name, &value))
|
|
|
|
{
|
|
|
|
hlsl_error(ctx, &replace_context->var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
|
|
|
"Unrecognized state constant %s.", state_constant->name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(c = hlsl_new_uint_constant(ctx, value, &replace_context->var->loc)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
list_add_before(&state_constant->node.entry, &c->entry);
|
|
|
|
hlsl_replace_node(&state_constant->node, c);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-04-21 17:05:18 -07:00
|
|
|
static void fold_state_value(struct hlsl_ctx *ctx, struct hlsl_state_block_entry *entry)
|
|
|
|
{
|
|
|
|
bool progress;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
progress = hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, entry->instrs, NULL);
|
|
|
|
progress |= hlsl_copy_propagation_execute(ctx, entry->instrs);
|
|
|
|
} while (progress);
|
|
|
|
}
|
|
|
|
|
2024-06-10 04:05:13 -07:00
|
|
|
enum state_property_component_type
|
|
|
|
{
|
|
|
|
FX_BOOL,
|
|
|
|
FX_FLOAT,
|
|
|
|
FX_UINT,
|
|
|
|
FX_UINT8,
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline enum hlsl_base_type hlsl_type_from_fx_type(enum state_property_component_type type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case FX_BOOL:
|
|
|
|
return HLSL_TYPE_BOOL;
|
|
|
|
case FX_FLOAT:
|
|
|
|
return HLSL_TYPE_FLOAT;
|
|
|
|
case FX_UINT:
|
|
|
|
case FX_UINT8:
|
|
|
|
return HLSL_TYPE_UINT;
|
|
|
|
default:
|
|
|
|
vkd3d_unreachable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-20 15:33:41 -07:00
|
|
|
static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry,
|
|
|
|
struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
static const struct rhs_named_value filter_values[] =
|
|
|
|
{
|
|
|
|
{ "MIN_MAG_MIP_POINT", 0x00 },
|
|
|
|
{ "MIN_MAG_POINT_MIP_LINEAR", 0x01 },
|
|
|
|
{ "MIN_POINT_MAG_LINEAR_MIP_POINT", 0x04 },
|
|
|
|
{ "MIN_POINT_MAG_MIP_LINEAR", 0x05 },
|
|
|
|
{ "MIN_LINEAR_MAG_MIP_POINT", 0x10 },
|
|
|
|
{ "MIN_LINEAR_MAG_POINT_MIP_LINEAR", 0x11 },
|
|
|
|
{ "MIN_MAG_LINEAR_MIP_POINT", 0x14 },
|
|
|
|
{ "MIN_MAG_MIP_LINEAR", 0x15 },
|
|
|
|
{ "ANISOTROPIC", 0x55 },
|
|
|
|
{ "COMPARISON_MIN_MAG_MIP_POINT", 0x80 },
|
|
|
|
{ "COMPARISON_MIN_MAG_POINT_MIP_LINEAR", 0x81 },
|
|
|
|
{ "COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT", 0x84 },
|
|
|
|
{ "COMPARISON_MIN_POINT_MAG_MIP_LINEAR", 0x85 },
|
|
|
|
{ "COMPARISON_MIN_LINEAR_MAG_MIP_POINT", 0x90 },
|
|
|
|
{ "COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR", 0x91 },
|
|
|
|
{ "COMPARISON_MIN_MAG_LINEAR_MIP_POINT", 0x94 },
|
|
|
|
{ "COMPARISON_MIN_MAG_MIP_LINEAR", 0x95 },
|
|
|
|
{ "COMPARISON_ANISOTROPIC", 0xd5 },
|
|
|
|
{ NULL },
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct rhs_named_value address_values[] =
|
|
|
|
{
|
|
|
|
{ "WRAP", 1 },
|
|
|
|
{ "MIRROR", 2 },
|
|
|
|
{ "CLAMP", 3 },
|
|
|
|
{ "BORDER", 4 },
|
|
|
|
{ "MIRROR_ONCE", 5 },
|
|
|
|
{ NULL },
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct rhs_named_value compare_func_values[] =
|
|
|
|
{
|
|
|
|
{ "NEVER", 1 },
|
|
|
|
{ "LESS", 2 },
|
|
|
|
{ "EQUAL", 3 },
|
|
|
|
{ "LESS_EQUAL", 4 },
|
|
|
|
{ "GREATER", 5 },
|
|
|
|
{ "NOT_EQUAL", 6 },
|
|
|
|
{ "GREATER_EQUAL", 7 },
|
|
|
|
{ "ALWAYS", 8 },
|
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
2024-06-10 04:05:13 -07:00
|
|
|
static const struct rhs_named_value depth_write_mask_values[] =
|
|
|
|
{
|
|
|
|
{ "ZERO", 0 },
|
|
|
|
{ "ALL", 1 },
|
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct rhs_named_value comparison_values[] =
|
|
|
|
{
|
|
|
|
{ "NEVER", 1 },
|
|
|
|
{ "LESS", 2 },
|
|
|
|
{ "EQUAL", 3 },
|
|
|
|
{ "LESS_EQUAL", 4 },
|
|
|
|
{ "GREATER", 5 },
|
|
|
|
{ "NOT_EQUAL", 6 },
|
|
|
|
{ "GREATER_EQUAL", 7 },
|
|
|
|
{ "ALWAYS", 8 },
|
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct rhs_named_value stencil_op_values[] =
|
|
|
|
{
|
|
|
|
{ "KEEP", 1 },
|
|
|
|
{ "ZERO", 2 },
|
|
|
|
{ "REPLACE", 3 },
|
|
|
|
{ "INCR_SAT", 4 },
|
|
|
|
{ "DECR_SAT", 5 },
|
|
|
|
{ "INVERT", 6 },
|
|
|
|
{ "INCR", 7 },
|
|
|
|
{ "DECR", 8 },
|
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
2024-06-10 04:18:43 -07:00
|
|
|
static const struct rhs_named_value fill_values[] =
|
|
|
|
{
|
|
|
|
{ "WIREFRAME", 2 },
|
|
|
|
{ "SOLID", 3 },
|
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct rhs_named_value cull_values[] =
|
|
|
|
{
|
|
|
|
{ "NONE", 1 },
|
|
|
|
{ "FRONT", 2 },
|
|
|
|
{ "BACK", 3 },
|
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
2024-04-20 15:33:41 -07:00
|
|
|
static const struct state
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
enum hlsl_type_class container;
|
2024-04-21 17:05:18 -07:00
|
|
|
enum hlsl_type_class class;
|
2024-06-10 04:05:13 -07:00
|
|
|
enum state_property_component_type type;
|
2024-04-20 15:33:41 -07:00
|
|
|
unsigned int dimx;
|
|
|
|
uint32_t id;
|
|
|
|
const struct rhs_named_value *values;
|
|
|
|
}
|
|
|
|
states[] =
|
|
|
|
{
|
2024-06-10 04:18:43 -07:00
|
|
|
{ "FillMode", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 12, fill_values },
|
|
|
|
{ "CullMode", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 13, cull_values },
|
|
|
|
{ "FrontCounterClockwise", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 14 },
|
|
|
|
{ "DepthBias", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 15 },
|
|
|
|
{ "DepthBiasClamp", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 16 },
|
|
|
|
{ "SlopeScaledDepthBias", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 17 },
|
|
|
|
{ "DepthClipEnable", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 18 },
|
|
|
|
{ "ScissorEnable", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 19 },
|
|
|
|
{ "MultisampleEnable", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 20 },
|
|
|
|
{ "AntializedLineEnable", HLSL_CLASS_RASTERIZER_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 21 },
|
|
|
|
|
2024-06-10 04:05:13 -07:00
|
|
|
{ "DepthEnable", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 22 },
|
|
|
|
{ "DepthWriteMask", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 23, depth_write_mask_values },
|
|
|
|
{ "DepthFunc", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 24, comparison_values },
|
|
|
|
{ "StencilEnable", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 25 },
|
|
|
|
{ "StencilReadMask", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT8, 1, 26 },
|
|
|
|
{ "StencilWriteMask", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT8, 1, 27 },
|
|
|
|
{ "FrontFaceStencilFail", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 28, stencil_op_values },
|
|
|
|
{ "FrontFaceStencilDepthFail", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 29, stencil_op_values },
|
|
|
|
{ "FrontFaceStencilPass", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 30, stencil_op_values },
|
|
|
|
{ "FrontFaceStencilFunc", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 31, comparison_values },
|
|
|
|
{ "BackFaceStencilFail", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 32, stencil_op_values },
|
|
|
|
{ "BackFaceStencilDepthFail", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 33, stencil_op_values },
|
|
|
|
{ "BackFaceStencilPass", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 34, stencil_op_values },
|
|
|
|
{ "BackFaceStencilFunc", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 35, comparison_values },
|
|
|
|
|
|
|
|
{ "Filter", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 45, filter_values },
|
|
|
|
{ "AddressU", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 46, address_values },
|
|
|
|
{ "AddressV", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 47, address_values },
|
|
|
|
{ "AddressW", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 48, address_values },
|
|
|
|
{ "MipLODBias", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 49 },
|
|
|
|
{ "MaxAnisotropy", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 50 },
|
|
|
|
{ "ComparisonFunc", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 51, compare_func_values },
|
|
|
|
{ "BorderColor", HLSL_CLASS_SAMPLER, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 52 },
|
|
|
|
{ "MinLOD", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 53 },
|
|
|
|
{ "MaxLOD", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 54 },
|
2024-04-20 15:33:41 -07:00
|
|
|
/* TODO: "Texture" field */
|
|
|
|
};
|
|
|
|
const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type);
|
|
|
|
struct replace_state_context replace_context;
|
2024-04-21 17:05:18 -07:00
|
|
|
struct hlsl_type *state_type = NULL;
|
2024-04-20 15:33:41 -07:00
|
|
|
struct hlsl_ir_node *node, *cast;
|
|
|
|
const struct state *state = NULL;
|
|
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
2024-06-10 04:05:13 -07:00
|
|
|
enum hlsl_base_type base_type;
|
2024-04-20 15:33:41 -07:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(states); ++i)
|
|
|
|
{
|
|
|
|
if (type->class == states[i].container
|
|
|
|
&& !ascii_strcasecmp(entry->name, states[i].name))
|
|
|
|
{
|
|
|
|
state = &states[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!state)
|
|
|
|
{
|
|
|
|
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Unrecognized state name %s.", entry->name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (entry->args_count != 1)
|
|
|
|
{
|
|
|
|
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Unrecognized initializer for the state %s.",
|
|
|
|
entry->name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
entry->name_id = state->id;
|
|
|
|
|
|
|
|
replace_context.values = state->values;
|
|
|
|
replace_context.var = var;
|
|
|
|
|
2024-04-21 17:05:18 -07:00
|
|
|
/* Turn named constants to actual constants. */
|
2024-04-20 15:33:41 -07:00
|
|
|
hlsl_transform_ir(ctx, replace_state_block_constant, entry->instrs, &replace_context);
|
2024-04-21 17:05:18 -07:00
|
|
|
fold_state_value(ctx, entry);
|
2024-04-20 15:33:41 -07:00
|
|
|
|
2024-04-21 17:05:18 -07:00
|
|
|
/* Now cast and run folding again. */
|
2024-04-20 15:33:41 -07:00
|
|
|
|
2024-06-10 04:05:13 -07:00
|
|
|
base_type = hlsl_type_from_fx_type(state->type);
|
2024-04-21 17:05:18 -07:00
|
|
|
switch (state->class)
|
|
|
|
{
|
|
|
|
case HLSL_CLASS_VECTOR:
|
2024-06-10 04:05:13 -07:00
|
|
|
state_type = hlsl_get_vector_type(ctx, base_type, state->dimx);
|
2024-04-21 17:05:18 -07:00
|
|
|
break;
|
|
|
|
case HLSL_CLASS_SCALAR:
|
2024-06-10 04:05:13 -07:00
|
|
|
state_type = hlsl_get_scalar_type(ctx, base_type);
|
2024-04-21 17:05:18 -07:00
|
|
|
break;
|
|
|
|
case HLSL_CLASS_TEXTURE:
|
|
|
|
hlsl_fixme(ctx, &ctx->location, "Object type fields are not supported.");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
2024-04-20 15:33:41 -07:00
|
|
|
|
2024-04-21 17:05:18 -07:00
|
|
|
if (state_type)
|
2024-04-20 15:33:41 -07:00
|
|
|
{
|
2024-04-21 17:05:18 -07:00
|
|
|
node = entry->args->node;
|
|
|
|
if (!(cast = hlsl_new_cast(ctx, node, state_type, &var->loc)))
|
|
|
|
return;
|
|
|
|
list_add_after(&node->entry, &cast->entry);
|
|
|
|
|
2024-06-10 04:05:13 -07:00
|
|
|
/* FX_UINT8 values are using 32-bits in the binary. Mask higher 24 bits for those. */
|
|
|
|
if (state->type == FX_UINT8)
|
|
|
|
{
|
|
|
|
struct hlsl_ir_node *mask;
|
|
|
|
|
|
|
|
if (!(mask = hlsl_new_uint_constant(ctx, 0xff, &var->loc)))
|
|
|
|
return;
|
|
|
|
list_add_after(&cast->entry, &mask->entry);
|
|
|
|
|
|
|
|
if (!(cast = hlsl_new_binary_expr(ctx, HLSL_OP2_BIT_AND, cast, mask)))
|
|
|
|
return;
|
|
|
|
list_add_after(&mask->entry, &cast->entry);
|
|
|
|
}
|
|
|
|
|
2024-04-21 17:05:18 -07:00
|
|
|
hlsl_src_remove(entry->args);
|
|
|
|
hlsl_src_from_node(entry->args, cast);
|
|
|
|
|
|
|
|
fold_state_value(ctx, entry);
|
|
|
|
}
|
2024-04-20 15:33:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void write_fx_4_state_object_initializer(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
uint32_t elements_count = hlsl_get_multiarray_size(var->data_type), i, j;
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
|
|
|
uint32_t count_offset, count;
|
|
|
|
|
|
|
|
for (i = 0; i < elements_count; ++i)
|
|
|
|
{
|
|
|
|
struct hlsl_state_block *block;
|
|
|
|
|
|
|
|
count_offset = put_u32(buffer, 0);
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
if (var->state_blocks)
|
|
|
|
{
|
|
|
|
block = var->state_blocks[i];
|
|
|
|
|
|
|
|
for (j = 0; j < block->count; ++j)
|
|
|
|
{
|
|
|
|
struct hlsl_state_block_entry *entry = block->entries[j];
|
|
|
|
|
|
|
|
/* Skip if property is reassigned later. This will use the last assignment. */
|
|
|
|
if (state_block_contains_state(entry->name, j + 1, block))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Resolve special constant names and property names. */
|
|
|
|
resolve_fx_4_state_block_values(var, entry, fx);
|
|
|
|
|
|
|
|
write_fx_4_state_assignment(var, entry, fx);
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
set_u32(buffer, count_offset, count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-09 13:42:23 -08:00
|
|
|
static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
|
|
|
{
|
2024-02-23 15:39:37 -08:00
|
|
|
const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type);
|
|
|
|
uint32_t elements_count = hlsl_get_multiarray_size(var->data_type);
|
2024-02-09 13:42:23 -08:00
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
|
|
|
uint32_t semantic_offset, bind_point = ~0u;
|
2024-02-23 15:39:37 -08:00
|
|
|
uint32_t name_offset, type_offset, i;
|
|
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
2024-02-09 13:42:23 -08:00
|
|
|
|
|
|
|
if (var->reg_reservation.reg_type)
|
|
|
|
bind_point = var->reg_reservation.reg_index;
|
|
|
|
|
|
|
|
type_offset = write_type(var->data_type, fx);
|
|
|
|
name_offset = write_string(var->name, fx);
|
2024-05-31 03:26:45 -07:00
|
|
|
semantic_offset = write_string(var->semantic.raw_name, fx);
|
2024-02-09 13:42:23 -08:00
|
|
|
|
|
|
|
put_u32(buffer, name_offset);
|
|
|
|
put_u32(buffer, type_offset);
|
|
|
|
|
|
|
|
semantic_offset = put_u32(buffer, semantic_offset); /* Semantic */
|
|
|
|
put_u32(buffer, bind_point); /* Explicit bind point */
|
|
|
|
|
2024-02-24 16:08:46 -08:00
|
|
|
if (fx->child_effect && var->storage_modifiers & HLSL_STORAGE_SHARED)
|
|
|
|
{
|
|
|
|
++fx->shared_object_count;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-02-23 15:39:37 -08:00
|
|
|
/* Initializer */
|
2024-02-05 18:25:57 -08:00
|
|
|
switch (type->class)
|
2024-02-23 15:39:37 -08:00
|
|
|
{
|
2024-02-27 11:34:52 -08:00
|
|
|
case HLSL_CLASS_RENDER_TARGET_VIEW:
|
2024-04-20 07:19:54 -07:00
|
|
|
fx->rtv_count += elements_count;
|
|
|
|
break;
|
2024-02-05 18:25:57 -08:00
|
|
|
case HLSL_CLASS_TEXTURE:
|
2024-04-20 07:28:34 -07:00
|
|
|
fx->texture_count += elements_count;
|
|
|
|
break;
|
2024-02-05 18:32:37 -08:00
|
|
|
case HLSL_CLASS_UAV:
|
2024-04-19 02:40:14 -07:00
|
|
|
fx->uav_count += elements_count;
|
2024-02-23 15:39:37 -08:00
|
|
|
break;
|
2024-02-05 18:25:57 -08:00
|
|
|
|
2024-02-06 17:41:15 -08:00
|
|
|
case HLSL_CLASS_PIXEL_SHADER:
|
2024-02-06 15:33:26 -08:00
|
|
|
case HLSL_CLASS_VERTEX_SHADER:
|
|
|
|
/* FIXME: write shader blobs, once parser support works. */
|
|
|
|
for (i = 0; i < elements_count; ++i)
|
|
|
|
put_u32(buffer, 0);
|
2024-04-20 07:30:05 -07:00
|
|
|
fx->shader_count += elements_count;
|
2024-02-06 15:33:26 -08:00
|
|
|
break;
|
|
|
|
|
2024-05-06 14:29:15 -07:00
|
|
|
case HLSL_CLASS_DEPTH_STENCIL_VIEW:
|
|
|
|
fx->dsv_count += elements_count;
|
|
|
|
break;
|
|
|
|
|
2024-06-10 04:05:13 -07:00
|
|
|
case HLSL_CLASS_DEPTH_STENCIL_STATE:
|
|
|
|
write_fx_4_state_object_initializer(var, fx);
|
|
|
|
fx->depth_stencil_state_count += elements_count;
|
|
|
|
break;
|
|
|
|
|
2024-04-20 15:33:41 -07:00
|
|
|
case HLSL_CLASS_SAMPLER:
|
|
|
|
write_fx_4_state_object_initializer(var, fx);
|
|
|
|
fx->sampler_state_count += elements_count;
|
|
|
|
break;
|
|
|
|
|
2024-06-10 04:18:43 -07:00
|
|
|
case HLSL_CLASS_RASTERIZER_STATE:
|
|
|
|
write_fx_4_state_object_initializer(var, fx);
|
|
|
|
fx->rasterizer_state_count += elements_count;
|
|
|
|
break;
|
|
|
|
|
2024-02-23 15:39:37 -08:00
|
|
|
default:
|
2024-03-14 05:31:00 -07:00
|
|
|
hlsl_fixme(ctx, &ctx->location, "Writing initializer for object type %u is not implemented.",
|
2024-02-27 15:30:51 -08:00
|
|
|
type->e.numeric.type);
|
2024-02-23 15:39:37 -08:00
|
|
|
}
|
|
|
|
|
2024-06-15 14:44:08 -07:00
|
|
|
write_fx_4_annotations(var->annotations, fx);
|
2024-02-23 15:39:37 -08:00
|
|
|
|
|
|
|
++fx->object_variable_count;
|
2024-02-09 13:42:23 -08:00
|
|
|
}
|
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx)
|
|
|
|
{
|
|
|
|
enum fx_4_buffer_flags
|
|
|
|
{
|
|
|
|
IS_TBUFFER = 0x1,
|
|
|
|
IS_SINGLE = 0x2,
|
|
|
|
};
|
|
|
|
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
|
|
|
uint32_t count = 0, bind_point = ~0u, flags = 0, size;
|
|
|
|
uint32_t name_offset, size_offset;
|
|
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
uint32_t count_offset;
|
2024-04-21 10:06:55 -07:00
|
|
|
bool shared;
|
|
|
|
|
|
|
|
shared = fx->child_effect && b->modifiers & HLSL_STORAGE_SHARED;
|
2024-02-06 06:11:47 -08:00
|
|
|
|
|
|
|
if (b->reservation.reg_type)
|
|
|
|
bind_point = b->reservation.reg_index;
|
|
|
|
if (b->type == HLSL_BUFFER_TEXTURE)
|
|
|
|
flags |= IS_TBUFFER;
|
2024-03-10 12:01:22 -07:00
|
|
|
if (ctx->profile->major_version == 5 && b->modifiers & HLSL_MODIFIER_SINGLE)
|
|
|
|
flags |= IS_SINGLE;
|
2024-02-06 06:11:47 -08:00
|
|
|
|
|
|
|
name_offset = write_string(b->name, fx);
|
|
|
|
|
|
|
|
put_u32(buffer, name_offset); /* Name */
|
|
|
|
size_offset = put_u32(buffer, 0); /* Data size */
|
|
|
|
put_u32(buffer, flags); /* Flags */
|
|
|
|
count_offset = put_u32(buffer, 0);
|
|
|
|
put_u32(buffer, bind_point); /* Bind point */
|
|
|
|
|
2024-04-21 10:06:55 -07:00
|
|
|
if (shared)
|
|
|
|
{
|
|
|
|
++fx->shared_buffer_count;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-06-15 14:44:08 -07:00
|
|
|
write_fx_4_annotations(b->annotations, fx);
|
2024-04-21 10:06:55 -07:00
|
|
|
++fx->buffer_count;
|
|
|
|
}
|
2024-02-06 06:11:47 -08:00
|
|
|
|
|
|
|
count = 0;
|
|
|
|
size = 0;
|
|
|
|
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
|
|
|
|
{
|
|
|
|
if (var->buffer != b)
|
|
|
|
continue;
|
|
|
|
|
2024-04-21 10:06:55 -07:00
|
|
|
write_fx_4_numeric_variable(var, shared, fx);
|
2024-02-06 06:11:47 -08:00
|
|
|
size += get_fx_4_type_size(var->data_type);
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_u32(buffer, count_offset, count);
|
|
|
|
set_u32(buffer, size_offset, align(size, 16));
|
|
|
|
}
|
|
|
|
|
2024-04-21 10:06:55 -07:00
|
|
|
static void write_buffers(struct fx_write_context *fx, bool shared)
|
2024-02-06 06:11:47 -08:00
|
|
|
{
|
|
|
|
struct hlsl_buffer *buffer;
|
|
|
|
|
2024-05-30 04:59:36 -07:00
|
|
|
if (shared && !fx->child_effect)
|
|
|
|
return;
|
|
|
|
|
2024-02-06 06:11:47 -08:00
|
|
|
LIST_FOR_EACH_ENTRY(buffer, &fx->ctx->buffers, struct hlsl_buffer, entry)
|
|
|
|
{
|
2024-03-28 03:39:04 -07:00
|
|
|
if (!buffer->size && !fx->include_empty_buffers)
|
|
|
|
continue;
|
|
|
|
if (!strcmp(buffer->name, "$Params"))
|
2024-02-06 06:11:47 -08:00
|
|
|
continue;
|
2024-04-21 10:06:55 -07:00
|
|
|
if (fx->child_effect && (shared != !!(buffer->modifiers & HLSL_STORAGE_SHARED)))
|
|
|
|
continue;
|
2024-02-06 06:11:47 -08:00
|
|
|
|
|
|
|
write_fx_4_buffer(buffer, fx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-18 19:05:00 -07:00
|
|
|
static bool is_supported_object_variable(const struct hlsl_ctx *ctx, const struct hlsl_ir_var *var)
|
2024-02-09 13:42:23 -08:00
|
|
|
{
|
|
|
|
const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type);
|
|
|
|
|
2024-02-05 18:13:17 -08:00
|
|
|
switch (type->class)
|
2024-02-09 13:42:23 -08:00
|
|
|
{
|
2024-06-10 04:05:13 -07:00
|
|
|
case HLSL_CLASS_DEPTH_STENCIL_STATE:
|
2024-05-06 14:29:15 -07:00
|
|
|
case HLSL_CLASS_DEPTH_STENCIL_VIEW:
|
2024-02-06 17:41:15 -08:00
|
|
|
case HLSL_CLASS_PIXEL_SHADER:
|
2024-04-24 02:12:08 -07:00
|
|
|
case HLSL_CLASS_RASTERIZER_STATE:
|
2024-02-27 11:34:52 -08:00
|
|
|
case HLSL_CLASS_RENDER_TARGET_VIEW:
|
2024-02-05 18:13:17 -08:00
|
|
|
case HLSL_CLASS_SAMPLER:
|
2024-02-05 18:25:57 -08:00
|
|
|
case HLSL_CLASS_TEXTURE:
|
2024-04-18 19:05:00 -07:00
|
|
|
return true;
|
2024-02-05 18:32:37 -08:00
|
|
|
case HLSL_CLASS_UAV:
|
2024-04-18 19:05:00 -07:00
|
|
|
if (ctx->profile->major_version < 5)
|
|
|
|
return false;
|
|
|
|
if (type->e.resource.rasteriser_ordered)
|
|
|
|
return false;
|
|
|
|
return true;
|
2024-02-06 15:33:26 -08:00
|
|
|
case HLSL_CLASS_VERTEX_SHADER:
|
2024-02-09 13:42:23 -08:00
|
|
|
return true;
|
2024-02-05 18:13:17 -08:00
|
|
|
|
2024-02-09 13:42:23 -08:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-24 16:08:46 -08:00
|
|
|
static void write_objects(struct fx_write_context *fx, bool shared)
|
2024-02-09 13:42:23 -08:00
|
|
|
{
|
2024-04-18 19:05:00 -07:00
|
|
|
struct hlsl_ctx *ctx = fx->ctx;
|
2024-02-09 13:42:23 -08:00
|
|
|
struct hlsl_ir_var *var;
|
|
|
|
|
2024-02-24 16:08:46 -08:00
|
|
|
if (shared && !fx->child_effect)
|
|
|
|
return;
|
|
|
|
|
2024-04-18 19:05:00 -07:00
|
|
|
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
|
2024-02-09 13:42:23 -08:00
|
|
|
{
|
2024-04-18 19:05:00 -07:00
|
|
|
if (!is_supported_object_variable(ctx, var))
|
2024-02-09 13:42:23 -08:00
|
|
|
continue;
|
|
|
|
|
2024-02-24 16:08:46 -08:00
|
|
|
if (fx->child_effect && (shared != !!(var->storage_modifiers & HLSL_STORAGE_SHARED)))
|
|
|
|
continue;
|
|
|
|
|
2024-02-09 13:42:23 -08:00
|
|
|
write_fx_4_object_variable(var, fx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-05 13:07:01 -08:00
|
|
|
static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer buffer = { 0 };
|
2024-02-06 06:11:47 -08:00
|
|
|
struct fx_write_context fx;
|
2024-02-06 15:38:59 -08:00
|
|
|
uint32_t size_offset;
|
2023-11-05 13:07:01 -08:00
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
fx_write_context_init(ctx, &fx_4_ops, &fx);
|
2023-11-05 13:07:01 -08:00
|
|
|
|
|
|
|
put_u32(&fx.unstructured, 0); /* Empty string placeholder. */
|
|
|
|
|
2024-04-21 10:06:55 -07:00
|
|
|
write_buffers(&fx, false);
|
2024-02-24 16:08:46 -08:00
|
|
|
write_objects(&fx, false);
|
2024-04-21 10:06:55 -07:00
|
|
|
write_buffers(&fx, true);
|
2024-02-24 16:08:46 -08:00
|
|
|
write_objects(&fx, true);
|
2023-11-05 13:07:01 -08:00
|
|
|
|
|
|
|
write_techniques(ctx->globals, &fx);
|
|
|
|
|
|
|
|
put_u32(&buffer, ctx->profile->minor_version == 0 ? 0xfeff1001 : 0xfeff1011); /* Version. */
|
2024-02-06 06:11:47 -08:00
|
|
|
put_u32(&buffer, fx.buffer_count); /* Buffer count. */
|
|
|
|
put_u32(&buffer, fx.numeric_variable_count); /* Numeric variable count. */
|
2024-02-09 13:42:23 -08:00
|
|
|
put_u32(&buffer, fx.object_variable_count); /* Object variable count. */
|
2024-04-21 10:06:55 -07:00
|
|
|
put_u32(&buffer, fx.shared_buffer_count);
|
|
|
|
put_u32(&buffer, fx.shared_numeric_variable_count);
|
|
|
|
put_u32(&buffer, fx.shared_object_count);
|
2023-11-05 13:07:01 -08:00
|
|
|
put_u32(&buffer, fx.technique_count);
|
|
|
|
size_offset = put_u32(&buffer, 0); /* Unstructured size. */
|
|
|
|
put_u32(&buffer, 0); /* String count. */
|
2024-04-20 07:28:34 -07:00
|
|
|
put_u32(&buffer, fx.texture_count);
|
2024-06-10 04:05:13 -07:00
|
|
|
put_u32(&buffer, fx.depth_stencil_state_count);
|
2023-11-05 13:07:01 -08:00
|
|
|
put_u32(&buffer, 0); /* Blend state count. */
|
2024-06-10 04:18:43 -07:00
|
|
|
put_u32(&buffer, fx.rasterizer_state_count);
|
2024-04-20 15:33:41 -07:00
|
|
|
put_u32(&buffer, fx.sampler_state_count);
|
2024-04-20 07:19:54 -07:00
|
|
|
put_u32(&buffer, fx.rtv_count);
|
2024-05-06 14:29:15 -07:00
|
|
|
put_u32(&buffer, fx.dsv_count);
|
2024-04-20 07:30:05 -07:00
|
|
|
put_u32(&buffer, fx.shader_count);
|
2023-11-05 13:07:01 -08:00
|
|
|
put_u32(&buffer, 0); /* Inline shader count. */
|
|
|
|
|
2024-02-06 15:38:59 -08:00
|
|
|
set_u32(&buffer, size_offset, fx.unstructured.size);
|
2023-11-05 13:07:01 -08:00
|
|
|
|
|
|
|
bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size);
|
2024-02-06 15:38:59 -08:00
|
|
|
bytecode_put_bytes_unaligned(&buffer, fx.structured.data, fx.structured.size);
|
2023-11-05 13:07:01 -08:00
|
|
|
|
|
|
|
vkd3d_free(fx.unstructured.data);
|
|
|
|
vkd3d_free(fx.structured.data);
|
|
|
|
|
|
|
|
set_status(&fx, buffer.status);
|
|
|
|
|
2024-02-22 17:11:38 -08:00
|
|
|
if (fx.status < 0)
|
|
|
|
ctx->result = fx.status;
|
|
|
|
|
|
|
|
if (!ctx->result)
|
2023-11-05 13:07:01 -08:00
|
|
|
{
|
|
|
|
out->code = buffer.data;
|
|
|
|
out->size = buffer.size;
|
|
|
|
}
|
|
|
|
|
2024-01-12 05:33:05 -08:00
|
|
|
return fx_write_context_cleanup(&fx);
|
2023-11-05 13:07:01 -08:00
|
|
|
}
|
|
|
|
|
2024-01-12 05:26:39 -08:00
|
|
|
static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
|
|
|
{
|
|
|
|
struct vkd3d_bytecode_buffer buffer = { 0 };
|
2024-02-06 06:11:47 -08:00
|
|
|
struct fx_write_context fx;
|
2024-02-06 15:38:59 -08:00
|
|
|
uint32_t size_offset;
|
2024-01-12 05:26:39 -08:00
|
|
|
|
2024-01-16 03:17:06 -08:00
|
|
|
fx_write_context_init(ctx, &fx_4_ops, &fx);
|
2024-01-12 05:26:39 -08:00
|
|
|
|
|
|
|
put_u32(&fx.unstructured, 0); /* Empty string placeholder. */
|
|
|
|
|
2024-04-21 10:06:55 -07:00
|
|
|
write_buffers(&fx, false);
|
2024-02-24 16:08:46 -08:00
|
|
|
write_objects(&fx, false);
|
2024-01-12 05:26:39 -08:00
|
|
|
/* TODO: interface variables */
|
|
|
|
|
2024-01-25 09:18:40 -08:00
|
|
|
write_groups(&fx);
|
2024-01-12 05:26:39 -08:00
|
|
|
|
|
|
|
put_u32(&buffer, 0xfeff2001); /* Version. */
|
2024-02-06 06:11:47 -08:00
|
|
|
put_u32(&buffer, fx.buffer_count); /* Buffer count. */
|
|
|
|
put_u32(&buffer, fx.numeric_variable_count); /* Numeric variable count. */
|
2024-02-09 13:42:23 -08:00
|
|
|
put_u32(&buffer, fx.object_variable_count); /* Object variable count. */
|
2024-04-21 10:06:55 -07:00
|
|
|
put_u32(&buffer, fx.shared_buffer_count);
|
|
|
|
put_u32(&buffer, fx.shared_numeric_variable_count);
|
|
|
|
put_u32(&buffer, fx.shared_object_count);
|
2024-01-12 05:26:39 -08:00
|
|
|
put_u32(&buffer, fx.technique_count);
|
|
|
|
size_offset = put_u32(&buffer, 0); /* Unstructured size. */
|
|
|
|
put_u32(&buffer, 0); /* String count. */
|
2024-04-20 07:28:34 -07:00
|
|
|
put_u32(&buffer, fx.texture_count);
|
2024-06-10 04:05:13 -07:00
|
|
|
put_u32(&buffer, fx.depth_stencil_state_count);
|
2024-01-12 05:26:39 -08:00
|
|
|
put_u32(&buffer, 0); /* Blend state count. */
|
2024-06-10 04:18:43 -07:00
|
|
|
put_u32(&buffer, fx.rasterizer_state_count);
|
2024-04-20 15:33:41 -07:00
|
|
|
put_u32(&buffer, fx.sampler_state_count);
|
2024-04-20 07:19:54 -07:00
|
|
|
put_u32(&buffer, fx.rtv_count);
|
2024-05-06 14:29:15 -07:00
|
|
|
put_u32(&buffer, fx.dsv_count);
|
2024-04-20 07:30:05 -07:00
|
|
|
put_u32(&buffer, fx.shader_count);
|
2024-01-12 05:26:39 -08:00
|
|
|
put_u32(&buffer, 0); /* Inline shader count. */
|
|
|
|
put_u32(&buffer, fx.group_count); /* Group count. */
|
2024-04-19 02:40:14 -07:00
|
|
|
put_u32(&buffer, fx.uav_count);
|
2024-01-12 05:26:39 -08:00
|
|
|
put_u32(&buffer, 0); /* Interface variables count. */
|
|
|
|
put_u32(&buffer, 0); /* Interface variable element count. */
|
|
|
|
put_u32(&buffer, 0); /* Class instance elements count. */
|
|
|
|
|
2024-02-06 15:38:59 -08:00
|
|
|
set_u32(&buffer, size_offset, fx.unstructured.size);
|
2024-01-12 05:26:39 -08:00
|
|
|
|
|
|
|
bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size);
|
2024-02-06 15:38:59 -08:00
|
|
|
bytecode_put_bytes_unaligned(&buffer, fx.structured.data, fx.structured.size);
|
2024-01-12 05:26:39 -08:00
|
|
|
|
|
|
|
vkd3d_free(fx.unstructured.data);
|
|
|
|
vkd3d_free(fx.structured.data);
|
|
|
|
|
|
|
|
set_status(&fx, buffer.status);
|
|
|
|
|
2024-02-22 17:11:38 -08:00
|
|
|
if (fx.status < 0)
|
|
|
|
ctx->result = fx.status;
|
|
|
|
|
|
|
|
if (!ctx->result)
|
2024-01-12 05:26:39 -08:00
|
|
|
{
|
|
|
|
out->code = buffer.data;
|
|
|
|
out->size = buffer.size;
|
|
|
|
}
|
|
|
|
|
2024-01-12 05:33:05 -08:00
|
|
|
return fx_write_context_cleanup(&fx);
|
2024-01-12 05:26:39 -08:00
|
|
|
}
|
|
|
|
|
2023-11-05 13:07:01 -08:00
|
|
|
int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
|
|
|
{
|
|
|
|
if (ctx->profile->major_version == 2)
|
|
|
|
{
|
2024-01-16 03:17:06 -08:00
|
|
|
return hlsl_fx_2_write(ctx, out);
|
2023-11-05 13:07:01 -08:00
|
|
|
}
|
|
|
|
else if (ctx->profile->major_version == 4)
|
|
|
|
{
|
|
|
|
return hlsl_fx_4_write(ctx, out);
|
|
|
|
}
|
|
|
|
else if (ctx->profile->major_version == 5)
|
|
|
|
{
|
2024-01-12 05:26:39 -08:00
|
|
|
return hlsl_fx_5_write(ctx, out);
|
2023-11-05 13:07:01 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vkd3d_unreachable();
|
|
|
|
}
|
|
|
|
}
|