2017-09-12 23:17:51 -04:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2017 Connor Abbott
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
* Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "nir_serialize.h"
|
|
|
|
|
#include "nir_control_flow.h"
|
2022-05-17 10:16:55 -05:00
|
|
|
#include "nir_xfb_info.h"
|
2017-09-12 23:17:51 -04:00
|
|
|
#include "util/u_dynarray.h"
|
2019-10-25 02:39:54 -04:00
|
|
|
#include "util/u_math.h"
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2019-11-19 08:19:34 +10:00
|
|
|
#define NIR_SERIALIZE_FUNC_HAS_IMPL ((void *)(intptr_t)1)
|
2019-10-30 18:14:37 -04:00
|
|
|
#define MAX_OBJECT_IDS (1 << 20)
|
2019-10-25 01:02:54 -04:00
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
typedef struct {
|
|
|
|
|
size_t blob_offset;
|
|
|
|
|
nir_ssa_def *src;
|
|
|
|
|
nir_block *block;
|
|
|
|
|
} write_phi_fixup;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
const nir_shader *nir;
|
|
|
|
|
|
|
|
|
|
struct blob *blob;
|
|
|
|
|
|
|
|
|
|
/* maps pointer to index */
|
|
|
|
|
struct hash_table *remap_table;
|
|
|
|
|
|
|
|
|
|
/* the next index to assign to a NIR in-memory object */
|
2019-10-25 01:02:54 -04:00
|
|
|
uint32_t next_idx;
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
/* Array of write_phi_fixup structs representing phi sources that need to
|
|
|
|
|
* be resolved in the second pass.
|
|
|
|
|
*/
|
|
|
|
|
struct util_dynarray phi_fixups;
|
2019-11-04 18:09:26 -05:00
|
|
|
|
2019-11-04 20:11:11 -05:00
|
|
|
/* The last serialized type. */
|
|
|
|
|
const struct glsl_type *last_type;
|
|
|
|
|
const struct glsl_type *last_interface_type;
|
2019-11-04 21:31:40 -05:00
|
|
|
struct nir_variable_data last_var_data;
|
2019-11-04 20:11:11 -05:00
|
|
|
|
2019-11-05 22:14:28 -05:00
|
|
|
/* For skipping equal ALU headers (typical after scalarization). */
|
|
|
|
|
nir_instr_type last_instr_type;
|
|
|
|
|
uintptr_t last_alu_header_offset;
|
2022-02-03 17:16:36 +01:00
|
|
|
uint32_t last_alu_header;
|
2019-11-05 22:14:28 -05:00
|
|
|
|
2019-11-04 18:09:26 -05:00
|
|
|
/* Don't write optional data such as variable names. */
|
|
|
|
|
bool strip;
|
2017-09-12 23:17:51 -04:00
|
|
|
} write_ctx;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
nir_shader *nir;
|
|
|
|
|
|
|
|
|
|
struct blob_reader *blob;
|
|
|
|
|
|
|
|
|
|
/* the next index to assign to a NIR in-memory object */
|
2019-10-25 01:02:54 -04:00
|
|
|
uint32_t next_idx;
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
/* The length of the index -> object table */
|
2019-10-25 01:02:54 -04:00
|
|
|
uint32_t idx_table_len;
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
/* map from index to deserialized pointer */
|
|
|
|
|
void **idx_table;
|
|
|
|
|
|
|
|
|
|
/* List of phi sources. */
|
|
|
|
|
struct list_head phi_srcs;
|
|
|
|
|
|
2019-11-04 20:11:11 -05:00
|
|
|
/* The last deserialized type. */
|
|
|
|
|
const struct glsl_type *last_type;
|
|
|
|
|
const struct glsl_type *last_interface_type;
|
2019-11-04 21:31:40 -05:00
|
|
|
struct nir_variable_data last_var_data;
|
2017-09-12 23:17:51 -04:00
|
|
|
} read_ctx;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_add_object(write_ctx *ctx, const void *obj)
|
|
|
|
|
{
|
2019-10-25 01:02:54 -04:00
|
|
|
uint32_t index = ctx->next_idx++;
|
|
|
|
|
assert(index != MAX_OBJECT_IDS);
|
|
|
|
|
_mesa_hash_table_insert(ctx->remap_table, obj, (void *)(uintptr_t) index);
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
2019-10-25 01:02:54 -04:00
|
|
|
static uint32_t
|
2017-09-12 23:17:51 -04:00
|
|
|
write_lookup_object(write_ctx *ctx, const void *obj)
|
|
|
|
|
{
|
|
|
|
|
struct hash_entry *entry = _mesa_hash_table_search(ctx->remap_table, obj);
|
|
|
|
|
assert(entry);
|
2019-10-25 01:02:54 -04:00
|
|
|
return (uint32_t)(uintptr_t) entry->data;
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
read_add_object(read_ctx *ctx, void *obj)
|
|
|
|
|
{
|
|
|
|
|
assert(ctx->next_idx < ctx->idx_table_len);
|
|
|
|
|
ctx->idx_table[ctx->next_idx++] = obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *
|
2019-10-25 01:02:54 -04:00
|
|
|
read_lookup_object(read_ctx *ctx, uint32_t idx)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
|
|
|
|
assert(idx < ctx->idx_table_len);
|
|
|
|
|
return ctx->idx_table[idx];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *
|
|
|
|
|
read_object(read_ctx *ctx)
|
|
|
|
|
{
|
2019-10-25 01:02:54 -04:00
|
|
|
return read_lookup_object(ctx, blob_read_uint32(ctx->blob));
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
static uint32_t
|
|
|
|
|
encode_bit_size_3bits(uint8_t bit_size)
|
|
|
|
|
{
|
|
|
|
|
/* Encode values of 0, 1, 2, 4, 8, 16, 32, 64 in 3 bits. */
|
|
|
|
|
assert(bit_size <= 64 && util_is_power_of_two_or_zero(bit_size));
|
|
|
|
|
if (bit_size)
|
|
|
|
|
return util_logbase2(bit_size) + 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint8_t
|
|
|
|
|
decode_bit_size_3bits(uint8_t bit_size)
|
|
|
|
|
{
|
|
|
|
|
if (bit_size)
|
|
|
|
|
return 1 << (bit_size - 1);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-21 20:24:08 -05:00
|
|
|
#define NUM_COMPONENTS_IS_SEPARATE_7 7
|
|
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
static uint8_t
|
|
|
|
|
encode_num_components_in_3bits(uint8_t num_components)
|
|
|
|
|
{
|
|
|
|
|
if (num_components <= 4)
|
|
|
|
|
return num_components;
|
|
|
|
|
if (num_components == 8)
|
|
|
|
|
return 5;
|
|
|
|
|
if (num_components == 16)
|
|
|
|
|
return 6;
|
|
|
|
|
|
2019-11-21 20:24:08 -05:00
|
|
|
/* special value indicating that num_components is in the next uint32 */
|
|
|
|
|
return NUM_COMPONENTS_IS_SEPARATE_7;
|
2019-10-25 02:39:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint8_t
|
|
|
|
|
decode_num_components_in_3bits(uint8_t value)
|
|
|
|
|
{
|
|
|
|
|
if (value <= 4)
|
|
|
|
|
return value;
|
|
|
|
|
if (value == 5)
|
|
|
|
|
return 8;
|
|
|
|
|
if (value == 6)
|
|
|
|
|
return 16;
|
|
|
|
|
|
|
|
|
|
unreachable("invalid num_components encoding");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
static void
|
|
|
|
|
write_constant(write_ctx *ctx, const nir_constant *c)
|
|
|
|
|
{
|
|
|
|
|
blob_write_bytes(ctx->blob, c->values, sizeof(c->values));
|
|
|
|
|
blob_write_uint32(ctx->blob, c->num_elements);
|
|
|
|
|
for (unsigned i = 0; i < c->num_elements; i++)
|
|
|
|
|
write_constant(ctx, c->elements[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_constant *
|
|
|
|
|
read_constant(read_ctx *ctx, nir_variable *nvar)
|
|
|
|
|
{
|
|
|
|
|
nir_constant *c = ralloc(nvar, nir_constant);
|
|
|
|
|
|
|
|
|
|
blob_copy_bytes(ctx->blob, (uint8_t *)c->values, sizeof(c->values));
|
|
|
|
|
c->num_elements = blob_read_uint32(ctx->blob);
|
2018-07-24 11:01:20 -07:00
|
|
|
c->elements = ralloc_array(nvar, nir_constant *, c->num_elements);
|
2017-09-12 23:17:51 -04:00
|
|
|
for (unsigned i = 0; i < c->num_elements; i++)
|
|
|
|
|
c->elements[i] = read_constant(ctx, nvar);
|
|
|
|
|
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-04 19:42:42 -05:00
|
|
|
enum var_data_encoding {
|
|
|
|
|
var_encode_full,
|
|
|
|
|
var_encode_shader_temp,
|
|
|
|
|
var_encode_function_temp,
|
2019-11-04 21:31:40 -05:00
|
|
|
var_encode_location_diff,
|
2019-11-04 19:42:42 -05:00
|
|
|
};
|
|
|
|
|
|
2019-10-25 14:33:04 -04:00
|
|
|
union packed_var {
|
|
|
|
|
uint32_t u32;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned has_name:1;
|
|
|
|
|
unsigned has_constant_initializer:1;
|
2019-12-10 15:37:53 -05:00
|
|
|
unsigned has_pointer_initializer:1;
|
2019-10-25 14:33:04 -04:00
|
|
|
unsigned has_interface_type:1;
|
2019-11-04 19:42:42 -05:00
|
|
|
unsigned num_state_slots:7;
|
|
|
|
|
unsigned data_encoding:2;
|
2019-11-04 20:11:11 -05:00
|
|
|
unsigned type_same_as_last:1;
|
|
|
|
|
unsigned interface_type_same_as_last:1;
|
2022-04-20 18:28:28 +03:00
|
|
|
unsigned ray_query:1;
|
2019-10-25 14:33:04 -04:00
|
|
|
unsigned num_members:16;
|
|
|
|
|
} u;
|
|
|
|
|
};
|
|
|
|
|
|
2019-11-04 21:31:40 -05:00
|
|
|
union packed_var_data_diff {
|
|
|
|
|
uint32_t u32;
|
|
|
|
|
struct {
|
|
|
|
|
int location:13;
|
|
|
|
|
int location_frac:3;
|
|
|
|
|
int driver_location:16;
|
|
|
|
|
} u;
|
|
|
|
|
};
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
static void
|
|
|
|
|
write_variable(write_ctx *ctx, const nir_variable *var)
|
|
|
|
|
{
|
|
|
|
|
write_add_object(ctx, var);
|
2019-10-25 14:33:04 -04:00
|
|
|
|
2019-11-04 19:42:42 -05:00
|
|
|
assert(var->num_state_slots < (1 << 7));
|
2019-10-25 14:33:04 -04:00
|
|
|
|
|
|
|
|
STATIC_ASSERT(sizeof(union packed_var) == 4);
|
|
|
|
|
union packed_var flags;
|
|
|
|
|
flags.u32 = 0;
|
|
|
|
|
|
2019-11-04 18:09:26 -05:00
|
|
|
flags.u.has_name = !ctx->strip && var->name;
|
2019-10-25 14:33:04 -04:00
|
|
|
flags.u.has_constant_initializer = !!(var->constant_initializer);
|
2019-12-10 15:37:53 -05:00
|
|
|
flags.u.has_pointer_initializer = !!(var->pointer_initializer);
|
2019-10-25 14:33:04 -04:00
|
|
|
flags.u.has_interface_type = !!(var->interface_type);
|
2019-11-04 20:11:11 -05:00
|
|
|
flags.u.type_same_as_last = var->type == ctx->last_type;
|
|
|
|
|
flags.u.interface_type_same_as_last =
|
|
|
|
|
var->interface_type && var->interface_type == ctx->last_interface_type;
|
2019-10-25 14:33:04 -04:00
|
|
|
flags.u.num_state_slots = var->num_state_slots;
|
|
|
|
|
flags.u.num_members = var->num_members;
|
|
|
|
|
|
2019-11-04 21:31:40 -05:00
|
|
|
struct nir_variable_data data = var->data;
|
|
|
|
|
|
|
|
|
|
/* When stripping, we expect that the location is no longer needed,
|
|
|
|
|
* which is typically after shaders are linked.
|
|
|
|
|
*/
|
|
|
|
|
if (ctx->strip &&
|
2020-08-29 21:58:37 +02:00
|
|
|
data.mode != nir_var_system_value &&
|
2019-11-04 21:31:40 -05:00
|
|
|
data.mode != nir_var_shader_in &&
|
|
|
|
|
data.mode != nir_var_shader_out)
|
|
|
|
|
data.location = 0;
|
|
|
|
|
|
2019-11-04 19:42:42 -05:00
|
|
|
/* Temporary variables don't serialize var->data. */
|
2019-11-04 21:31:40 -05:00
|
|
|
if (data.mode == nir_var_shader_temp)
|
2019-11-04 19:42:42 -05:00
|
|
|
flags.u.data_encoding = var_encode_shader_temp;
|
2019-11-04 21:31:40 -05:00
|
|
|
else if (data.mode == nir_var_function_temp)
|
2019-11-04 19:42:42 -05:00
|
|
|
flags.u.data_encoding = var_encode_function_temp;
|
2019-11-04 21:31:40 -05:00
|
|
|
else {
|
|
|
|
|
struct nir_variable_data tmp = data;
|
|
|
|
|
|
|
|
|
|
tmp.location = ctx->last_var_data.location;
|
|
|
|
|
tmp.location_frac = ctx->last_var_data.location_frac;
|
|
|
|
|
tmp.driver_location = ctx->last_var_data.driver_location;
|
|
|
|
|
|
|
|
|
|
/* See if we can encode only the difference in locations from the last
|
|
|
|
|
* variable.
|
|
|
|
|
*/
|
|
|
|
|
if (memcmp(&ctx->last_var_data, &tmp, sizeof(tmp)) == 0 &&
|
|
|
|
|
abs((int)data.location -
|
|
|
|
|
(int)ctx->last_var_data.location) < (1 << 12) &&
|
|
|
|
|
abs((int)data.driver_location -
|
|
|
|
|
(int)ctx->last_var_data.driver_location) < (1 << 15))
|
|
|
|
|
flags.u.data_encoding = var_encode_location_diff;
|
|
|
|
|
else
|
|
|
|
|
flags.u.data_encoding = var_encode_full;
|
|
|
|
|
}
|
2019-11-04 19:42:42 -05:00
|
|
|
|
2022-04-20 18:28:28 +03:00
|
|
|
flags.u.ray_query = var->data.ray_query;
|
|
|
|
|
|
2019-10-25 14:33:04 -04:00
|
|
|
blob_write_uint32(ctx->blob, flags.u32);
|
|
|
|
|
|
2019-11-04 20:11:11 -05:00
|
|
|
if (!flags.u.type_same_as_last) {
|
|
|
|
|
encode_type_to_blob(ctx->blob, var->type);
|
|
|
|
|
ctx->last_type = var->type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (var->interface_type && !flags.u.interface_type_same_as_last) {
|
|
|
|
|
encode_type_to_blob(ctx->blob, var->interface_type);
|
|
|
|
|
ctx->last_interface_type = var->interface_type;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-04 18:09:26 -05:00
|
|
|
if (flags.u.has_name)
|
2018-02-28 13:01:56 +01:00
|
|
|
blob_write_string(ctx->blob, var->name);
|
2019-11-04 18:09:26 -05:00
|
|
|
|
2019-11-04 21:31:40 -05:00
|
|
|
if (flags.u.data_encoding == var_encode_full ||
|
|
|
|
|
flags.u.data_encoding == var_encode_location_diff) {
|
|
|
|
|
if (flags.u.data_encoding == var_encode_full) {
|
|
|
|
|
blob_write_bytes(ctx->blob, &data, sizeof(data));
|
|
|
|
|
} else {
|
|
|
|
|
/* Serialize only the difference in locations from the last variable.
|
|
|
|
|
*/
|
|
|
|
|
union packed_var_data_diff diff;
|
2019-11-04 18:09:26 -05:00
|
|
|
|
2019-11-04 21:31:40 -05:00
|
|
|
diff.u.location = data.location - ctx->last_var_data.location;
|
|
|
|
|
diff.u.location_frac = data.location_frac -
|
|
|
|
|
ctx->last_var_data.location_frac;
|
|
|
|
|
diff.u.driver_location = data.driver_location -
|
|
|
|
|
ctx->last_var_data.driver_location;
|
2019-11-04 18:09:26 -05:00
|
|
|
|
2019-11-04 21:31:40 -05:00
|
|
|
blob_write_uint32(ctx->blob, diff.u32);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx->last_var_data = data;
|
2019-11-04 19:42:42 -05:00
|
|
|
}
|
2019-11-04 18:09:26 -05:00
|
|
|
|
2019-03-08 13:05:53 +01:00
|
|
|
for (unsigned i = 0; i < var->num_state_slots; i++) {
|
2019-10-25 12:01:27 -04:00
|
|
|
blob_write_bytes(ctx->blob, &var->state_slots[i],
|
|
|
|
|
sizeof(var->state_slots[i]));
|
2019-03-08 13:05:53 +01:00
|
|
|
}
|
2017-09-12 23:17:51 -04:00
|
|
|
if (var->constant_initializer)
|
|
|
|
|
write_constant(ctx, var->constant_initializer);
|
2019-12-10 15:37:53 -05:00
|
|
|
if (var->pointer_initializer)
|
2023-04-07 18:34:17 +09:00
|
|
|
blob_write_uint32(ctx->blob,
|
|
|
|
|
write_lookup_object(ctx, var->pointer_initializer));
|
2018-03-21 16:48:35 -07:00
|
|
|
if (var->num_members > 0) {
|
|
|
|
|
blob_write_bytes(ctx->blob, (uint8_t *) var->members,
|
|
|
|
|
var->num_members * sizeof(*var->members));
|
|
|
|
|
}
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_variable *
|
|
|
|
|
read_variable(read_ctx *ctx)
|
|
|
|
|
{
|
|
|
|
|
nir_variable *var = rzalloc(ctx->nir, nir_variable);
|
|
|
|
|
read_add_object(ctx, var);
|
|
|
|
|
|
2019-10-25 14:33:04 -04:00
|
|
|
union packed_var flags;
|
|
|
|
|
flags.u32 = blob_read_uint32(ctx->blob);
|
|
|
|
|
|
2019-11-04 20:11:11 -05:00
|
|
|
if (flags.u.type_same_as_last) {
|
|
|
|
|
var->type = ctx->last_type;
|
|
|
|
|
} else {
|
|
|
|
|
var->type = decode_type_from_blob(ctx->blob);
|
|
|
|
|
ctx->last_type = var->type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flags.u.has_interface_type) {
|
|
|
|
|
if (flags.u.interface_type_same_as_last) {
|
|
|
|
|
var->interface_type = ctx->last_interface_type;
|
|
|
|
|
} else {
|
|
|
|
|
var->interface_type = decode_type_from_blob(ctx->blob);
|
|
|
|
|
ctx->last_interface_type = var->interface_type;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-25 14:33:04 -04:00
|
|
|
if (flags.u.has_name) {
|
2017-09-12 23:17:51 -04:00
|
|
|
const char *name = blob_read_string(ctx->blob);
|
|
|
|
|
var->name = ralloc_strdup(var, name);
|
|
|
|
|
} else {
|
|
|
|
|
var->name = NULL;
|
|
|
|
|
}
|
2019-11-04 19:42:42 -05:00
|
|
|
|
|
|
|
|
if (flags.u.data_encoding == var_encode_shader_temp)
|
|
|
|
|
var->data.mode = nir_var_shader_temp;
|
|
|
|
|
else if (flags.u.data_encoding == var_encode_function_temp)
|
|
|
|
|
var->data.mode = nir_var_function_temp;
|
2019-11-04 21:31:40 -05:00
|
|
|
else if (flags.u.data_encoding == var_encode_full) {
|
2019-11-04 19:42:42 -05:00
|
|
|
blob_copy_bytes(ctx->blob, (uint8_t *) &var->data, sizeof(var->data));
|
2019-11-04 21:31:40 -05:00
|
|
|
ctx->last_var_data = var->data;
|
|
|
|
|
} else { /* var_encode_location_diff */
|
|
|
|
|
union packed_var_data_diff diff;
|
|
|
|
|
diff.u32 = blob_read_uint32(ctx->blob);
|
|
|
|
|
|
|
|
|
|
var->data = ctx->last_var_data;
|
|
|
|
|
var->data.location += diff.u.location;
|
|
|
|
|
var->data.location_frac += diff.u.location_frac;
|
|
|
|
|
var->data.driver_location += diff.u.driver_location;
|
|
|
|
|
|
|
|
|
|
ctx->last_var_data = var->data;
|
|
|
|
|
}
|
2019-11-04 19:42:42 -05:00
|
|
|
|
2022-04-20 18:28:28 +03:00
|
|
|
var->data.ray_query = flags.u.ray_query;
|
|
|
|
|
|
2019-10-25 14:33:04 -04:00
|
|
|
var->num_state_slots = flags.u.num_state_slots;
|
2019-03-08 13:05:53 +01:00
|
|
|
if (var->num_state_slots != 0) {
|
|
|
|
|
var->state_slots = ralloc_array(var, nir_state_slot,
|
|
|
|
|
var->num_state_slots);
|
|
|
|
|
for (unsigned i = 0; i < var->num_state_slots; i++) {
|
2019-10-25 12:01:27 -04:00
|
|
|
blob_copy_bytes(ctx->blob, &var->state_slots[i],
|
|
|
|
|
sizeof(var->state_slots[i]));
|
2019-03-08 13:05:53 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-10-25 14:33:04 -04:00
|
|
|
if (flags.u.has_constant_initializer)
|
2017-09-12 23:17:51 -04:00
|
|
|
var->constant_initializer = read_constant(ctx, var);
|
|
|
|
|
else
|
|
|
|
|
var->constant_initializer = NULL;
|
2019-12-10 15:37:53 -05:00
|
|
|
|
|
|
|
|
if (flags.u.has_pointer_initializer)
|
|
|
|
|
var->pointer_initializer = read_object(ctx);
|
|
|
|
|
else
|
|
|
|
|
var->pointer_initializer = NULL;
|
|
|
|
|
|
2019-10-25 14:33:04 -04:00
|
|
|
var->num_members = flags.u.num_members;
|
2018-03-21 16:48:35 -07:00
|
|
|
if (var->num_members > 0) {
|
|
|
|
|
var->members = ralloc_array(var, struct nir_variable_data,
|
|
|
|
|
var->num_members);
|
|
|
|
|
blob_copy_bytes(ctx->blob, (uint8_t *) var->members,
|
|
|
|
|
var->num_members * sizeof(*var->members));
|
|
|
|
|
}
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
return var;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_var_list(write_ctx *ctx, const struct exec_list *src)
|
|
|
|
|
{
|
|
|
|
|
blob_write_uint32(ctx->blob, exec_list_length(src));
|
|
|
|
|
foreach_list_typed(nir_variable, var, node, src) {
|
|
|
|
|
write_variable(ctx, var);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
read_var_list(read_ctx *ctx, struct exec_list *dst)
|
|
|
|
|
{
|
|
|
|
|
exec_list_make_empty(dst);
|
|
|
|
|
unsigned num_vars = blob_read_uint32(ctx->blob);
|
|
|
|
|
for (unsigned i = 0; i < num_vars; i++) {
|
|
|
|
|
nir_variable *var = read_variable(ctx);
|
|
|
|
|
exec_list_push_tail(dst, &var->node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_register(write_ctx *ctx, const nir_register *reg)
|
|
|
|
|
{
|
|
|
|
|
write_add_object(ctx, reg);
|
|
|
|
|
blob_write_uint32(ctx->blob, reg->num_components);
|
|
|
|
|
blob_write_uint32(ctx->blob, reg->bit_size);
|
|
|
|
|
blob_write_uint32(ctx->blob, reg->num_array_elems);
|
|
|
|
|
blob_write_uint32(ctx->blob, reg->index);
|
2021-11-19 22:01:05 -05:00
|
|
|
blob_write_uint8(ctx->blob, reg->divergent);
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_register *
|
|
|
|
|
read_register(read_ctx *ctx)
|
|
|
|
|
{
|
|
|
|
|
nir_register *reg = ralloc(ctx->nir, nir_register);
|
|
|
|
|
read_add_object(ctx, reg);
|
|
|
|
|
reg->num_components = blob_read_uint32(ctx->blob);
|
|
|
|
|
reg->bit_size = blob_read_uint32(ctx->blob);
|
|
|
|
|
reg->num_array_elems = blob_read_uint32(ctx->blob);
|
|
|
|
|
reg->index = blob_read_uint32(ctx->blob);
|
2021-11-19 22:01:05 -05:00
|
|
|
reg->divergent = blob_read_uint8(ctx->blob);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
list_inithead(®->uses);
|
|
|
|
|
list_inithead(®->defs);
|
|
|
|
|
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_reg_list(write_ctx *ctx, const struct exec_list *src)
|
|
|
|
|
{
|
|
|
|
|
blob_write_uint32(ctx->blob, exec_list_length(src));
|
|
|
|
|
foreach_list_typed(nir_register, reg, node, src)
|
|
|
|
|
write_register(ctx, reg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
read_reg_list(read_ctx *ctx, struct exec_list *dst)
|
|
|
|
|
{
|
|
|
|
|
exec_list_make_empty(dst);
|
|
|
|
|
unsigned num_regs = blob_read_uint32(ctx->blob);
|
|
|
|
|
for (unsigned i = 0; i < num_regs; i++) {
|
|
|
|
|
nir_register *reg = read_register(ctx);
|
|
|
|
|
exec_list_push_tail(dst, ®->node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-30 18:14:37 -04:00
|
|
|
union packed_src {
|
|
|
|
|
uint32_t u32;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned is_ssa:1; /* <-- Header */
|
|
|
|
|
unsigned is_indirect:1;
|
|
|
|
|
unsigned object_idx:20;
|
|
|
|
|
unsigned _footer:10; /* <-- Footer */
|
|
|
|
|
} any;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned _header:22; /* <-- Header */
|
|
|
|
|
unsigned negate:1; /* <-- Footer */
|
|
|
|
|
unsigned abs:1;
|
|
|
|
|
unsigned swizzle_x:2;
|
|
|
|
|
unsigned swizzle_y:2;
|
|
|
|
|
unsigned swizzle_z:2;
|
|
|
|
|
unsigned swizzle_w:2;
|
|
|
|
|
} alu;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned _header:22; /* <-- Header */
|
|
|
|
|
unsigned src_type:5; /* <-- Footer */
|
|
|
|
|
unsigned _pad:5;
|
|
|
|
|
} tex;
|
|
|
|
|
};
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
static void
|
2019-10-30 18:14:37 -04:00
|
|
|
write_src_full(write_ctx *ctx, const nir_src *src, union packed_src header)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
|
|
|
|
/* Since sources are very frequent, we try to save some space when storing
|
|
|
|
|
* them. In particular, we store whether the source is a register and
|
|
|
|
|
* whether the register has an indirect index in the low two bits. We can
|
|
|
|
|
* assume that the high two bits of the index are zero, since otherwise our
|
|
|
|
|
* address space would've been exhausted allocating the remap table!
|
|
|
|
|
*/
|
2019-10-30 18:14:37 -04:00
|
|
|
header.any.is_ssa = src->is_ssa;
|
2017-09-12 23:17:51 -04:00
|
|
|
if (src->is_ssa) {
|
2019-10-30 18:14:37 -04:00
|
|
|
header.any.object_idx = write_lookup_object(ctx, src->ssa);
|
|
|
|
|
blob_write_uint32(ctx->blob, header.u32);
|
2017-09-12 23:17:51 -04:00
|
|
|
} else {
|
2019-10-30 18:14:37 -04:00
|
|
|
header.any.object_idx = write_lookup_object(ctx, src->reg.reg);
|
|
|
|
|
header.any.is_indirect = !!src->reg.indirect;
|
|
|
|
|
blob_write_uint32(ctx->blob, header.u32);
|
2017-09-12 23:17:51 -04:00
|
|
|
blob_write_uint32(ctx->blob, src->reg.base_offset);
|
|
|
|
|
if (src->reg.indirect) {
|
2019-10-30 18:14:37 -04:00
|
|
|
union packed_src header = {0};
|
|
|
|
|
write_src_full(ctx, src->reg.indirect, header);
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2019-10-30 18:14:37 -04:00
|
|
|
write_src(write_ctx *ctx, const nir_src *src)
|
|
|
|
|
{
|
|
|
|
|
union packed_src header = {0};
|
|
|
|
|
write_src_full(ctx, src, header);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static union packed_src
|
2021-09-08 15:28:53 +01:00
|
|
|
read_src(read_ctx *ctx, nir_src *src)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
2019-10-30 18:14:37 -04:00
|
|
|
STATIC_ASSERT(sizeof(union packed_src) == 4);
|
|
|
|
|
union packed_src header;
|
|
|
|
|
header.u32 = blob_read_uint32(ctx->blob);
|
|
|
|
|
|
|
|
|
|
src->is_ssa = header.any.is_ssa;
|
2017-09-12 23:17:51 -04:00
|
|
|
if (src->is_ssa) {
|
2019-10-30 18:14:37 -04:00
|
|
|
src->ssa = read_lookup_object(ctx, header.any.object_idx);
|
2017-09-12 23:17:51 -04:00
|
|
|
} else {
|
2019-10-30 18:14:37 -04:00
|
|
|
src->reg.reg = read_lookup_object(ctx, header.any.object_idx);
|
2017-09-12 23:17:51 -04:00
|
|
|
src->reg.base_offset = blob_read_uint32(ctx->blob);
|
2019-10-30 18:14:37 -04:00
|
|
|
if (header.any.is_indirect) {
|
2021-09-08 15:24:10 +01:00
|
|
|
src->reg.indirect = gc_alloc(ctx->nir->gctx, nir_src, 1);
|
2021-09-08 15:28:53 +01:00
|
|
|
read_src(ctx, src->reg.indirect);
|
2017-09-12 23:17:51 -04:00
|
|
|
} else {
|
|
|
|
|
src->reg.indirect = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-10-30 18:14:37 -04:00
|
|
|
return header;
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
union packed_dest {
|
|
|
|
|
uint8_t u8;
|
|
|
|
|
struct {
|
|
|
|
|
uint8_t is_ssa:1;
|
|
|
|
|
uint8_t num_components:3;
|
|
|
|
|
uint8_t bit_size:3;
|
2021-11-19 22:01:05 -05:00
|
|
|
uint8_t divergent:1;
|
2019-10-25 02:39:54 -04:00
|
|
|
} ssa;
|
|
|
|
|
struct {
|
|
|
|
|
uint8_t is_ssa:1;
|
|
|
|
|
uint8_t is_indirect:1;
|
|
|
|
|
uint8_t _pad:6;
|
|
|
|
|
} reg;
|
|
|
|
|
};
|
|
|
|
|
|
2019-11-04 23:29:33 -05:00
|
|
|
enum intrinsic_const_indices_encoding {
|
2021-10-20 17:36:27 +03:00
|
|
|
/* Use packed_const_indices to store tightly packed indices.
|
2019-11-04 23:29:33 -05:00
|
|
|
*
|
|
|
|
|
* The common case for load_ubo is 0, 0, 0, which is trivially represented.
|
|
|
|
|
* The common cases for load_interpolated_input also fit here, e.g.: 7, 3
|
|
|
|
|
*/
|
2021-10-20 17:36:27 +03:00
|
|
|
const_indices_all_combined,
|
2019-11-04 23:29:33 -05:00
|
|
|
|
|
|
|
|
const_indices_8bit, /* 8 bits per element */
|
|
|
|
|
const_indices_16bit, /* 16 bits per element */
|
|
|
|
|
const_indices_32bit, /* 32 bits per element */
|
|
|
|
|
};
|
|
|
|
|
|
2019-11-04 22:25:15 -05:00
|
|
|
enum load_const_packing {
|
|
|
|
|
/* Constants are not packed and are stored in following dwords. */
|
|
|
|
|
load_const_full,
|
|
|
|
|
|
|
|
|
|
/* packed_value contains high 19 bits, low bits are 0,
|
|
|
|
|
* good for floating-point decimals
|
|
|
|
|
*/
|
|
|
|
|
load_const_scalar_hi_19bits,
|
|
|
|
|
|
|
|
|
|
/* packed_value contains low 19 bits, high bits are sign-extended */
|
|
|
|
|
load_const_scalar_lo_19bits_sext,
|
|
|
|
|
};
|
|
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
union packed_instr {
|
|
|
|
|
uint32_t u32;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned instr_type:4; /* always present */
|
|
|
|
|
unsigned _pad:20;
|
|
|
|
|
unsigned dest:8; /* always last */
|
|
|
|
|
} any;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned instr_type:4;
|
|
|
|
|
unsigned exact:1;
|
|
|
|
|
unsigned no_signed_wrap:1;
|
|
|
|
|
unsigned no_unsigned_wrap:1;
|
|
|
|
|
unsigned saturate:1;
|
2019-11-07 00:28:01 -05:00
|
|
|
/* Reg: writemask; SSA: swizzles for 2 srcs */
|
|
|
|
|
unsigned writemask_or_two_swizzles:4;
|
2019-10-25 02:39:54 -04:00
|
|
|
unsigned op:9;
|
2019-11-05 00:09:29 -05:00
|
|
|
unsigned packed_src_ssa_16bit:1;
|
2019-11-05 22:14:28 -05:00
|
|
|
/* Scalarized ALUs always have the same header. */
|
|
|
|
|
unsigned num_followup_alu_sharing_header:2;
|
2019-10-25 02:39:54 -04:00
|
|
|
unsigned dest:8;
|
|
|
|
|
} alu;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned instr_type:4;
|
|
|
|
|
unsigned deref_type:3;
|
2019-11-04 20:11:11 -05:00
|
|
|
unsigned cast_type_same_as_last:1;
|
2021-10-15 13:25:50 -05:00
|
|
|
unsigned modes:5; /* See (de|en)code_deref_modes() */
|
2022-05-26 21:12:33 +02:00
|
|
|
unsigned _pad:9;
|
|
|
|
|
unsigned in_bounds:1;
|
2019-11-05 18:10:40 -05:00
|
|
|
unsigned packed_src_ssa_16bit:1; /* deref_var redefines this */
|
2019-10-25 02:39:54 -04:00
|
|
|
unsigned dest:8;
|
|
|
|
|
} deref;
|
2019-11-05 17:53:32 -05:00
|
|
|
struct {
|
|
|
|
|
unsigned instr_type:4;
|
|
|
|
|
unsigned deref_type:3;
|
|
|
|
|
unsigned _pad:1;
|
|
|
|
|
unsigned object_idx:16; /* if 0, the object ID is a separate uint32 */
|
|
|
|
|
unsigned dest:8;
|
|
|
|
|
} deref_var;
|
2019-10-25 02:39:54 -04:00
|
|
|
struct {
|
|
|
|
|
unsigned instr_type:4;
|
2021-10-20 17:36:27 +03:00
|
|
|
unsigned intrinsic:10;
|
2019-11-04 23:29:33 -05:00
|
|
|
unsigned const_indices_encoding:2;
|
2021-10-20 17:36:27 +03:00
|
|
|
unsigned packed_const_indices:8;
|
2019-10-25 02:39:54 -04:00
|
|
|
unsigned dest:8;
|
|
|
|
|
} intrinsic;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned instr_type:4;
|
|
|
|
|
unsigned last_component:4;
|
|
|
|
|
unsigned bit_size:3;
|
2019-11-04 22:25:15 -05:00
|
|
|
unsigned packing:2; /* enum load_const_packing */
|
|
|
|
|
unsigned packed_value:19; /* meaning determined by packing */
|
2019-10-25 02:39:54 -04:00
|
|
|
} load_const;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned instr_type:4;
|
|
|
|
|
unsigned last_component:4;
|
|
|
|
|
unsigned bit_size:3;
|
|
|
|
|
unsigned _pad:21;
|
|
|
|
|
} undef;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned instr_type:4;
|
|
|
|
|
unsigned num_srcs:4;
|
2022-06-23 16:32:12 +02:00
|
|
|
unsigned op:5;
|
|
|
|
|
unsigned _pad:11;
|
2022-06-23 18:53:31 +02:00
|
|
|
unsigned dest:8;
|
2019-10-25 02:39:54 -04:00
|
|
|
} tex;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned instr_type:4;
|
|
|
|
|
unsigned num_srcs:20;
|
|
|
|
|
unsigned dest:8;
|
|
|
|
|
} phi;
|
|
|
|
|
struct {
|
|
|
|
|
unsigned instr_type:4;
|
|
|
|
|
unsigned type:2;
|
|
|
|
|
unsigned _pad:26;
|
|
|
|
|
} jump;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Write "lo24" as low 24 bits in the first uint32. */
|
2017-09-12 23:17:51 -04:00
|
|
|
static void
|
2019-11-05 22:14:28 -05:00
|
|
|
write_dest(write_ctx *ctx, const nir_dest *dst, union packed_instr header,
|
|
|
|
|
nir_instr_type instr_type)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
2019-10-25 02:39:54 -04:00
|
|
|
STATIC_ASSERT(sizeof(union packed_dest) == 1);
|
|
|
|
|
union packed_dest dest;
|
|
|
|
|
dest.u8 = 0;
|
|
|
|
|
|
|
|
|
|
dest.ssa.is_ssa = dst->is_ssa;
|
2017-09-12 23:17:51 -04:00
|
|
|
if (dst->is_ssa) {
|
2019-10-25 02:39:54 -04:00
|
|
|
dest.ssa.num_components =
|
|
|
|
|
encode_num_components_in_3bits(dst->ssa.num_components);
|
|
|
|
|
dest.ssa.bit_size = encode_bit_size_3bits(dst->ssa.bit_size);
|
2021-11-19 22:01:05 -05:00
|
|
|
dest.ssa.divergent = dst->ssa.divergent;
|
2017-09-12 23:17:51 -04:00
|
|
|
} else {
|
2019-10-25 02:39:54 -04:00
|
|
|
dest.reg.is_indirect = !!(dst->reg.indirect);
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
2019-10-25 02:39:54 -04:00
|
|
|
header.any.dest = dest.u8;
|
2019-11-05 22:14:28 -05:00
|
|
|
|
|
|
|
|
/* Check if the current ALU instruction has the same header as the previous
|
|
|
|
|
* instruction that is also ALU. If it is, we don't have to write
|
|
|
|
|
* the current header. This is a typical occurence after scalarization.
|
|
|
|
|
*/
|
|
|
|
|
if (instr_type == nir_instr_type_alu) {
|
|
|
|
|
bool equal_header = false;
|
|
|
|
|
|
|
|
|
|
if (ctx->last_instr_type == nir_instr_type_alu) {
|
|
|
|
|
assert(ctx->last_alu_header_offset);
|
2020-09-15 12:26:34 +02:00
|
|
|
union packed_instr last_header;
|
2022-02-03 17:16:36 +01:00
|
|
|
last_header.u32 = ctx->last_alu_header;
|
2019-11-05 22:14:28 -05:00
|
|
|
|
|
|
|
|
/* Clear the field that counts ALUs with equal headers. */
|
|
|
|
|
union packed_instr clean_header;
|
2020-09-15 12:26:34 +02:00
|
|
|
clean_header.u32 = last_header.u32;
|
2019-11-05 22:14:28 -05:00
|
|
|
clean_header.alu.num_followup_alu_sharing_header = 0;
|
|
|
|
|
|
|
|
|
|
/* There can be at most 4 consecutive ALU instructions
|
|
|
|
|
* sharing the same header.
|
|
|
|
|
*/
|
2020-09-15 12:26:34 +02:00
|
|
|
if (last_header.alu.num_followup_alu_sharing_header < 3 &&
|
2019-11-05 22:14:28 -05:00
|
|
|
header.u32 == clean_header.u32) {
|
2020-09-15 12:26:34 +02:00
|
|
|
last_header.alu.num_followup_alu_sharing_header++;
|
2022-02-03 17:16:36 +01:00
|
|
|
blob_overwrite_uint32(ctx->blob, ctx->last_alu_header_offset,
|
|
|
|
|
last_header.u32);
|
|
|
|
|
ctx->last_alu_header = last_header.u32;
|
2019-11-05 22:14:28 -05:00
|
|
|
equal_header = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!equal_header) {
|
2022-02-03 17:16:36 +01:00
|
|
|
ctx->last_alu_header_offset = blob_reserve_uint32(ctx->blob);
|
|
|
|
|
blob_overwrite_uint32(ctx->blob, ctx->last_alu_header_offset, header.u32);
|
|
|
|
|
ctx->last_alu_header = header.u32;
|
2019-11-05 22:14:28 -05:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
blob_write_uint32(ctx->blob, header.u32);
|
|
|
|
|
}
|
2019-10-25 02:39:54 -04:00
|
|
|
|
2019-11-21 20:24:08 -05:00
|
|
|
if (dest.ssa.is_ssa &&
|
|
|
|
|
dest.ssa.num_components == NUM_COMPONENTS_IS_SEPARATE_7)
|
|
|
|
|
blob_write_uint32(ctx->blob, dst->ssa.num_components);
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
if (dst->is_ssa) {
|
|
|
|
|
write_add_object(ctx, &dst->ssa);
|
|
|
|
|
} else {
|
2019-10-25 01:02:54 -04:00
|
|
|
blob_write_uint32(ctx->blob, write_lookup_object(ctx, dst->reg.reg));
|
2017-09-12 23:17:51 -04:00
|
|
|
blob_write_uint32(ctx->blob, dst->reg.base_offset);
|
|
|
|
|
if (dst->reg.indirect)
|
|
|
|
|
write_src(ctx, dst->reg.indirect);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2019-10-25 02:39:54 -04:00
|
|
|
read_dest(read_ctx *ctx, nir_dest *dst, nir_instr *instr,
|
|
|
|
|
union packed_instr header)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
2019-10-25 02:39:54 -04:00
|
|
|
union packed_dest dest;
|
|
|
|
|
dest.u8 = header.any.dest;
|
|
|
|
|
|
|
|
|
|
if (dest.ssa.is_ssa) {
|
|
|
|
|
unsigned bit_size = decode_bit_size_3bits(dest.ssa.bit_size);
|
2019-11-21 20:24:08 -05:00
|
|
|
unsigned num_components;
|
|
|
|
|
if (dest.ssa.num_components == NUM_COMPONENTS_IS_SEPARATE_7)
|
|
|
|
|
num_components = blob_read_uint32(ctx->blob);
|
|
|
|
|
else
|
|
|
|
|
num_components = decode_num_components_in_3bits(dest.ssa.num_components);
|
nir: Drop unused name from nir_ssa_dest_init
Since 624e799cc34 ("nir: Drop nir_ssa_def::name and nir_register::name"), SSA
defs don't have names, making the name argument unused. Drop it from the
signature and fix the call sites. This was done with the help of the following
Coccinelle semantic patch:
@@
expression A, B, C, D, E;
@@
-nir_ssa_dest_init(A, B, C, D, E);
+nir_ssa_dest_init(A, B, C, D);
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Emma Anholt <emma@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23078>
2023-05-17 09:08:22 -04:00
|
|
|
nir_ssa_dest_init(instr, dst, num_components, bit_size);
|
2021-11-19 22:01:05 -05:00
|
|
|
dst->ssa.divergent = dest.ssa.divergent;
|
2017-09-12 23:17:51 -04:00
|
|
|
read_add_object(ctx, &dst->ssa);
|
|
|
|
|
} else {
|
|
|
|
|
dst->reg.reg = read_object(ctx);
|
|
|
|
|
dst->reg.base_offset = blob_read_uint32(ctx->blob);
|
2019-10-25 02:39:54 -04:00
|
|
|
if (dest.reg.is_indirect) {
|
2021-09-08 15:24:10 +01:00
|
|
|
dst->reg.indirect = gc_alloc(ctx->nir->gctx, nir_src, 1);
|
2021-09-08 15:28:53 +01:00
|
|
|
read_src(ctx, dst->reg.indirect);
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 00:09:29 -05:00
|
|
|
static bool
|
|
|
|
|
are_object_ids_16bit(write_ctx *ctx)
|
|
|
|
|
{
|
|
|
|
|
/* Check the highest object ID, because they are monotonic. */
|
|
|
|
|
return ctx->next_idx < (1 << 16);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
is_alu_src_ssa_16bit(write_ctx *ctx, const nir_alu_instr *alu)
|
|
|
|
|
{
|
|
|
|
|
unsigned num_srcs = nir_op_infos[alu->op].num_inputs;
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < num_srcs; i++) {
|
|
|
|
|
if (!alu->src[i].src.is_ssa || alu->src[i].abs || alu->src[i].negate)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
unsigned src_components = nir_ssa_alu_instr_src_components(alu, i);
|
|
|
|
|
|
|
|
|
|
for (unsigned chan = 0; chan < src_components; chan++) {
|
2019-11-07 00:28:01 -05:00
|
|
|
/* The swizzles for src0.x and src1.x are stored
|
|
|
|
|
* in writemask_or_two_swizzles for SSA ALUs.
|
|
|
|
|
*/
|
2019-12-02 15:22:49 +01:00
|
|
|
if (alu->dest.dest.is_ssa && i < 2 && chan == 0 &&
|
|
|
|
|
alu->src[i].swizzle[chan] < 4)
|
2019-11-07 00:28:01 -05:00
|
|
|
continue;
|
|
|
|
|
|
2019-11-05 00:09:29 -05:00
|
|
|
if (alu->src[i].swizzle[chan] != chan)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return are_object_ids_16bit(ctx);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
static void
|
|
|
|
|
write_alu(write_ctx *ctx, const nir_alu_instr *alu)
|
|
|
|
|
{
|
2019-11-05 00:09:29 -05:00
|
|
|
unsigned num_srcs = nir_op_infos[alu->op].num_inputs;
|
2019-11-11 22:33:49 -05:00
|
|
|
unsigned dst_components = nir_dest_num_components(alu->dest.dest);
|
2019-11-11 22:28:17 -05:00
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
/* 9 bits for nir_op */
|
|
|
|
|
STATIC_ASSERT(nir_num_opcodes <= 512);
|
|
|
|
|
union packed_instr header;
|
|
|
|
|
header.u32 = 0;
|
|
|
|
|
|
|
|
|
|
header.alu.instr_type = alu->instr.type;
|
|
|
|
|
header.alu.exact = alu->exact;
|
|
|
|
|
header.alu.no_signed_wrap = alu->no_signed_wrap;
|
|
|
|
|
header.alu.no_unsigned_wrap = alu->no_unsigned_wrap;
|
|
|
|
|
header.alu.saturate = alu->dest.saturate;
|
|
|
|
|
header.alu.op = alu->op;
|
2019-11-05 00:09:29 -05:00
|
|
|
header.alu.packed_src_ssa_16bit = is_alu_src_ssa_16bit(ctx, alu);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2019-11-07 00:28:01 -05:00
|
|
|
if (header.alu.packed_src_ssa_16bit &&
|
|
|
|
|
alu->dest.dest.is_ssa) {
|
|
|
|
|
/* For packed srcs of SSA ALUs, this field stores the swizzles. */
|
|
|
|
|
header.alu.writemask_or_two_swizzles = alu->src[0].swizzle[0];
|
|
|
|
|
if (num_srcs > 1)
|
|
|
|
|
header.alu.writemask_or_two_swizzles |= alu->src[1].swizzle[0] << 2;
|
2019-11-11 22:33:49 -05:00
|
|
|
} else if (!alu->dest.dest.is_ssa && dst_components <= 4) {
|
|
|
|
|
/* For vec4 registers, this field is a writemask. */
|
2019-11-07 00:28:01 -05:00
|
|
|
header.alu.writemask_or_two_swizzles = alu->dest.write_mask;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 22:14:28 -05:00
|
|
|
write_dest(ctx, &alu->dest.dest, header, alu->instr.type);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2019-11-11 22:33:49 -05:00
|
|
|
if (!alu->dest.dest.is_ssa && dst_components > 4)
|
|
|
|
|
blob_write_uint32(ctx->blob, alu->dest.write_mask);
|
|
|
|
|
|
2019-11-05 00:09:29 -05:00
|
|
|
if (header.alu.packed_src_ssa_16bit) {
|
|
|
|
|
for (unsigned i = 0; i < num_srcs; i++) {
|
|
|
|
|
assert(alu->src[i].src.is_ssa);
|
|
|
|
|
unsigned idx = write_lookup_object(ctx, alu->src[i].src.ssa);
|
|
|
|
|
assert(idx < (1 << 16));
|
|
|
|
|
blob_write_uint16(ctx->blob, idx);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (unsigned i = 0; i < num_srcs; i++) {
|
2019-12-02 15:22:49 +01:00
|
|
|
unsigned src_channels = nir_ssa_alu_instr_src_components(alu, i);
|
|
|
|
|
unsigned src_components = nir_src_num_components(alu->src[i].src);
|
2019-11-05 00:09:29 -05:00
|
|
|
union packed_src src;
|
2019-12-02 15:22:49 +01:00
|
|
|
bool packed = src_components <= 4 && src_channels <= 4;
|
2019-11-05 00:09:29 -05:00
|
|
|
src.u32 = 0;
|
|
|
|
|
|
|
|
|
|
src.alu.negate = alu->src[i].negate;
|
|
|
|
|
src.alu.abs = alu->src[i].abs;
|
2019-11-11 22:28:17 -05:00
|
|
|
|
2019-12-02 15:22:49 +01:00
|
|
|
if (packed) {
|
2019-11-11 22:28:17 -05:00
|
|
|
src.alu.swizzle_x = alu->src[i].swizzle[0];
|
|
|
|
|
src.alu.swizzle_y = alu->src[i].swizzle[1];
|
|
|
|
|
src.alu.swizzle_z = alu->src[i].swizzle[2];
|
|
|
|
|
src.alu.swizzle_w = alu->src[i].swizzle[3];
|
|
|
|
|
}
|
2019-11-05 00:09:29 -05:00
|
|
|
|
|
|
|
|
write_src_full(ctx, &alu->src[i].src, src);
|
2019-11-11 22:28:17 -05:00
|
|
|
|
|
|
|
|
/* Store swizzles for vec8 and vec16. */
|
2019-12-02 15:22:49 +01:00
|
|
|
if (!packed) {
|
|
|
|
|
for (unsigned o = 0; o < src_channels; o += 8) {
|
2019-11-11 22:28:17 -05:00
|
|
|
unsigned value = 0;
|
|
|
|
|
|
2019-12-02 15:22:49 +01:00
|
|
|
for (unsigned j = 0; j < 8 && o + j < src_channels; j++) {
|
2019-12-11 16:01:15 +01:00
|
|
|
value |= (uint32_t)alu->src[i].swizzle[o + j] <<
|
2019-11-11 22:28:17 -05:00
|
|
|
(4 * j); /* 4 bits per swizzle */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
blob_write_uint32(ctx->blob, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-05 00:09:29 -05:00
|
|
|
}
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_alu_instr *
|
2019-10-25 02:39:54 -04:00
|
|
|
read_alu(read_ctx *ctx, union packed_instr header)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
2019-11-05 00:09:29 -05:00
|
|
|
unsigned num_srcs = nir_op_infos[header.alu.op].num_inputs;
|
2019-10-25 02:39:54 -04:00
|
|
|
nir_alu_instr *alu = nir_alu_instr_create(ctx->nir, header.alu.op);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
alu->exact = header.alu.exact;
|
|
|
|
|
alu->no_signed_wrap = header.alu.no_signed_wrap;
|
|
|
|
|
alu->no_unsigned_wrap = header.alu.no_unsigned_wrap;
|
|
|
|
|
alu->dest.saturate = header.alu.saturate;
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
read_dest(ctx, &alu->dest.dest, &alu->instr, header);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2019-11-11 22:33:49 -05:00
|
|
|
unsigned dst_components = nir_dest_num_components(alu->dest.dest);
|
|
|
|
|
|
|
|
|
|
if (alu->dest.dest.is_ssa) {
|
|
|
|
|
alu->dest.write_mask = u_bit_consecutive(0, dst_components);
|
|
|
|
|
} else if (dst_components <= 4) {
|
|
|
|
|
alu->dest.write_mask = header.alu.writemask_or_two_swizzles;
|
|
|
|
|
} else {
|
|
|
|
|
alu->dest.write_mask = blob_read_uint32(ctx->blob);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 00:09:29 -05:00
|
|
|
if (header.alu.packed_src_ssa_16bit) {
|
|
|
|
|
for (unsigned i = 0; i < num_srcs; i++) {
|
|
|
|
|
nir_alu_src *src = &alu->src[i];
|
|
|
|
|
src->src.is_ssa = true;
|
|
|
|
|
src->src.ssa = read_lookup_object(ctx, blob_read_uint16(ctx->blob));
|
2019-10-30 18:14:37 -04:00
|
|
|
|
2019-11-05 00:09:29 -05:00
|
|
|
memset(&src->swizzle, 0, sizeof(src->swizzle));
|
|
|
|
|
|
|
|
|
|
unsigned src_components = nir_ssa_alu_instr_src_components(alu, i);
|
|
|
|
|
|
|
|
|
|
for (unsigned chan = 0; chan < src_components; chan++)
|
|
|
|
|
src->swizzle[chan] = chan;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (unsigned i = 0; i < num_srcs; i++) {
|
2021-09-08 15:28:53 +01:00
|
|
|
union packed_src src = read_src(ctx, &alu->src[i].src);
|
2019-12-02 15:22:49 +01:00
|
|
|
unsigned src_channels = nir_ssa_alu_instr_src_components(alu, i);
|
|
|
|
|
unsigned src_components = nir_src_num_components(alu->src[i].src);
|
|
|
|
|
bool packed = src_components <= 4 && src_channels <= 4;
|
2019-11-05 00:09:29 -05:00
|
|
|
|
|
|
|
|
alu->src[i].negate = src.alu.negate;
|
|
|
|
|
alu->src[i].abs = src.alu.abs;
|
2019-11-11 22:28:17 -05:00
|
|
|
|
|
|
|
|
memset(&alu->src[i].swizzle, 0, sizeof(alu->src[i].swizzle));
|
|
|
|
|
|
2019-12-02 15:22:49 +01:00
|
|
|
if (packed) {
|
2019-11-11 22:28:17 -05:00
|
|
|
alu->src[i].swizzle[0] = src.alu.swizzle_x;
|
|
|
|
|
alu->src[i].swizzle[1] = src.alu.swizzle_y;
|
|
|
|
|
alu->src[i].swizzle[2] = src.alu.swizzle_z;
|
|
|
|
|
alu->src[i].swizzle[3] = src.alu.swizzle_w;
|
|
|
|
|
} else {
|
|
|
|
|
/* Load swizzles for vec8 and vec16. */
|
2019-12-02 15:22:49 +01:00
|
|
|
for (unsigned o = 0; o < src_channels; o += 8) {
|
2019-11-11 22:28:17 -05:00
|
|
|
unsigned value = blob_read_uint32(ctx->blob);
|
|
|
|
|
|
2019-12-02 15:22:49 +01:00
|
|
|
for (unsigned j = 0; j < 8 && o + j < src_channels; j++) {
|
|
|
|
|
alu->src[i].swizzle[o + j] =
|
2019-11-11 22:28:17 -05:00
|
|
|
(value >> (4 * j)) & 0xf; /* 4 bits per swizzle */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-05 00:09:29 -05:00
|
|
|
}
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
2019-11-07 00:28:01 -05:00
|
|
|
if (header.alu.packed_src_ssa_16bit &&
|
|
|
|
|
alu->dest.dest.is_ssa) {
|
|
|
|
|
alu->src[0].swizzle[0] = header.alu.writemask_or_two_swizzles & 0x3;
|
|
|
|
|
if (num_srcs > 1)
|
|
|
|
|
alu->src[1].swizzle[0] = header.alu.writemask_or_two_swizzles >> 2;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
return alu;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-15 13:25:50 -05:00
|
|
|
#define MODE_ENC_GENERIC_BIT (1 << 4)
|
|
|
|
|
|
|
|
|
|
static nir_variable_mode
|
|
|
|
|
decode_deref_modes(unsigned modes)
|
|
|
|
|
{
|
|
|
|
|
if (modes & MODE_ENC_GENERIC_BIT) {
|
|
|
|
|
modes &= ~MODE_ENC_GENERIC_BIT;
|
|
|
|
|
return modes << (ffs(nir_var_mem_generic) - 1);
|
|
|
|
|
} else {
|
|
|
|
|
return 1 << modes;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static unsigned
|
|
|
|
|
encode_deref_modes(nir_variable_mode modes)
|
|
|
|
|
{
|
|
|
|
|
/* Mode sets on derefs generally come in two forms. For certain OpenCL
|
|
|
|
|
* cases, we can have more than one of the generic modes set. In this
|
|
|
|
|
* case, we need the full bitfield. Fortunately, there are only 4 of
|
|
|
|
|
* these. For all other modes, we can only have one mode at a time so we
|
|
|
|
|
* can compress them by only storing the bit position. This, plus one bit
|
|
|
|
|
* to select encoding, lets us pack the entire bitfield in 5 bits.
|
|
|
|
|
*/
|
|
|
|
|
STATIC_ASSERT((nir_var_all & ~nir_var_mem_generic) <
|
|
|
|
|
(1 << MODE_ENC_GENERIC_BIT));
|
|
|
|
|
|
|
|
|
|
unsigned enc;
|
|
|
|
|
if (modes == 0 || (modes & nir_var_mem_generic)) {
|
|
|
|
|
assert(!(modes & ~nir_var_mem_generic));
|
|
|
|
|
enc = modes >> (ffs(nir_var_mem_generic) - 1);
|
|
|
|
|
assert(enc < MODE_ENC_GENERIC_BIT);
|
|
|
|
|
enc |= MODE_ENC_GENERIC_BIT;
|
|
|
|
|
} else {
|
|
|
|
|
assert(util_is_power_of_two_nonzero(modes));
|
|
|
|
|
enc = ffs(modes) - 1;
|
|
|
|
|
assert(enc < MODE_ENC_GENERIC_BIT);
|
|
|
|
|
}
|
|
|
|
|
assert(modes == decode_deref_modes(enc));
|
|
|
|
|
return enc;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-14 21:45:38 -07:00
|
|
|
static void
|
|
|
|
|
write_deref(write_ctx *ctx, const nir_deref_instr *deref)
|
|
|
|
|
{
|
2019-10-25 02:39:54 -04:00
|
|
|
assert(deref->deref_type < 8);
|
2018-03-14 21:45:38 -07:00
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
union packed_instr header;
|
|
|
|
|
header.u32 = 0;
|
2018-03-14 21:45:38 -07:00
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
header.deref.instr_type = deref->instr.type;
|
|
|
|
|
header.deref.deref_type = deref->deref_type;
|
|
|
|
|
|
2019-11-05 17:39:38 -05:00
|
|
|
if (deref->deref_type == nir_deref_type_cast) {
|
2021-10-15 13:25:50 -05:00
|
|
|
header.deref.modes = encode_deref_modes(deref->modes);
|
2019-11-04 20:11:11 -05:00
|
|
|
header.deref.cast_type_same_as_last = deref->type == ctx->last_type;
|
2019-11-05 17:39:38 -05:00
|
|
|
}
|
2019-11-04 20:11:11 -05:00
|
|
|
|
2019-11-05 17:53:32 -05:00
|
|
|
unsigned var_idx = 0;
|
|
|
|
|
if (deref->deref_type == nir_deref_type_var) {
|
|
|
|
|
var_idx = write_lookup_object(ctx, deref->var);
|
|
|
|
|
if (var_idx && var_idx < (1 << 16))
|
|
|
|
|
header.deref_var.object_idx = var_idx;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 18:10:40 -05:00
|
|
|
if (deref->deref_type == nir_deref_type_array ||
|
|
|
|
|
deref->deref_type == nir_deref_type_ptr_as_array) {
|
|
|
|
|
header.deref.packed_src_ssa_16bit =
|
|
|
|
|
deref->parent.is_ssa && deref->arr.index.is_ssa &&
|
|
|
|
|
are_object_ids_16bit(ctx);
|
2022-05-26 21:12:33 +02:00
|
|
|
|
|
|
|
|
header.deref.in_bounds = deref->arr.in_bounds;
|
2019-11-05 18:10:40 -05:00
|
|
|
}
|
|
|
|
|
|
2019-11-05 22:14:28 -05:00
|
|
|
write_dest(ctx, &deref->dest, header, deref->instr.type);
|
2018-03-14 21:45:38 -07:00
|
|
|
|
2019-11-05 18:24:27 -05:00
|
|
|
switch (deref->deref_type) {
|
|
|
|
|
case nir_deref_type_var:
|
2019-11-05 17:53:32 -05:00
|
|
|
if (!header.deref_var.object_idx)
|
|
|
|
|
blob_write_uint32(ctx->blob, var_idx);
|
2019-11-05 18:24:27 -05:00
|
|
|
break;
|
2018-03-14 21:45:38 -07:00
|
|
|
|
|
|
|
|
case nir_deref_type_struct:
|
2019-11-05 18:24:27 -05:00
|
|
|
write_src(ctx, &deref->parent);
|
2018-03-14 21:45:38 -07:00
|
|
|
blob_write_uint32(ctx->blob, deref->strct.index);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case nir_deref_type_array:
|
2018-11-28 12:26:52 -06:00
|
|
|
case nir_deref_type_ptr_as_array:
|
2019-11-05 18:10:40 -05:00
|
|
|
if (header.deref.packed_src_ssa_16bit) {
|
|
|
|
|
blob_write_uint16(ctx->blob,
|
|
|
|
|
write_lookup_object(ctx, deref->parent.ssa));
|
|
|
|
|
blob_write_uint16(ctx->blob,
|
|
|
|
|
write_lookup_object(ctx, deref->arr.index.ssa));
|
|
|
|
|
} else {
|
|
|
|
|
write_src(ctx, &deref->parent);
|
|
|
|
|
write_src(ctx, &deref->arr.index);
|
|
|
|
|
}
|
2018-03-14 21:45:38 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case nir_deref_type_cast:
|
2019-11-05 18:24:27 -05:00
|
|
|
write_src(ctx, &deref->parent);
|
2018-11-28 12:26:52 -06:00
|
|
|
blob_write_uint32(ctx->blob, deref->cast.ptr_stride);
|
2020-08-24 09:51:04 -05:00
|
|
|
blob_write_uint32(ctx->blob, deref->cast.align_mul);
|
|
|
|
|
blob_write_uint32(ctx->blob, deref->cast.align_offset);
|
2019-11-04 20:11:11 -05:00
|
|
|
if (!header.deref.cast_type_same_as_last) {
|
|
|
|
|
encode_type_to_blob(ctx->blob, deref->type);
|
|
|
|
|
ctx->last_type = deref->type;
|
|
|
|
|
}
|
2018-11-28 12:26:52 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case nir_deref_type_array_wildcard:
|
2019-11-05 18:24:27 -05:00
|
|
|
write_src(ctx, &deref->parent);
|
2018-03-14 21:45:38 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
unreachable("Invalid deref type");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_deref_instr *
|
2019-10-25 02:39:54 -04:00
|
|
|
read_deref(read_ctx *ctx, union packed_instr header)
|
2018-03-14 21:45:38 -07:00
|
|
|
{
|
2019-10-25 02:39:54 -04:00
|
|
|
nir_deref_type deref_type = header.deref.deref_type;
|
2018-03-14 21:45:38 -07:00
|
|
|
nir_deref_instr *deref = nir_deref_instr_create(ctx->nir, deref_type);
|
|
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
read_dest(ctx, &deref->dest, &deref->instr, header);
|
2018-03-14 21:45:38 -07:00
|
|
|
|
2019-11-05 18:24:27 -05:00
|
|
|
nir_deref_instr *parent;
|
|
|
|
|
|
|
|
|
|
switch (deref->deref_type) {
|
|
|
|
|
case nir_deref_type_var:
|
2019-11-05 17:53:32 -05:00
|
|
|
if (header.deref_var.object_idx)
|
|
|
|
|
deref->var = read_lookup_object(ctx, header.deref_var.object_idx);
|
|
|
|
|
else
|
|
|
|
|
deref->var = read_object(ctx);
|
|
|
|
|
|
2019-11-04 20:11:11 -05:00
|
|
|
deref->type = deref->var->type;
|
2019-11-05 18:24:27 -05:00
|
|
|
break;
|
2018-03-14 21:45:38 -07:00
|
|
|
|
|
|
|
|
case nir_deref_type_struct:
|
2021-09-08 15:28:53 +01:00
|
|
|
read_src(ctx, &deref->parent);
|
2019-11-04 20:11:11 -05:00
|
|
|
parent = nir_src_as_deref(deref->parent);
|
2018-03-14 21:45:38 -07:00
|
|
|
deref->strct.index = blob_read_uint32(ctx->blob);
|
2019-11-04 20:11:11 -05:00
|
|
|
deref->type = glsl_get_struct_field(parent->type, deref->strct.index);
|
2018-03-14 21:45:38 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case nir_deref_type_array:
|
2018-11-28 12:26:52 -06:00
|
|
|
case nir_deref_type_ptr_as_array:
|
2019-11-05 18:10:40 -05:00
|
|
|
if (header.deref.packed_src_ssa_16bit) {
|
|
|
|
|
deref->parent.is_ssa = true;
|
|
|
|
|
deref->parent.ssa = read_lookup_object(ctx, blob_read_uint16(ctx->blob));
|
|
|
|
|
deref->arr.index.is_ssa = true;
|
|
|
|
|
deref->arr.index.ssa = read_lookup_object(ctx, blob_read_uint16(ctx->blob));
|
|
|
|
|
} else {
|
2021-09-08 15:28:53 +01:00
|
|
|
read_src(ctx, &deref->parent);
|
|
|
|
|
read_src(ctx, &deref->arr.index);
|
2019-11-05 18:10:40 -05:00
|
|
|
}
|
|
|
|
|
|
2022-05-26 21:12:33 +02:00
|
|
|
deref->arr.in_bounds = header.deref.in_bounds;
|
|
|
|
|
|
2019-11-04 20:11:11 -05:00
|
|
|
parent = nir_src_as_deref(deref->parent);
|
|
|
|
|
if (deref->deref_type == nir_deref_type_array)
|
|
|
|
|
deref->type = glsl_get_array_element(parent->type);
|
|
|
|
|
else
|
|
|
|
|
deref->type = parent->type;
|
2018-03-14 21:45:38 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case nir_deref_type_cast:
|
2021-09-08 15:28:53 +01:00
|
|
|
read_src(ctx, &deref->parent);
|
2018-11-28 12:26:52 -06:00
|
|
|
deref->cast.ptr_stride = blob_read_uint32(ctx->blob);
|
2020-08-24 09:51:04 -05:00
|
|
|
deref->cast.align_mul = blob_read_uint32(ctx->blob);
|
|
|
|
|
deref->cast.align_offset = blob_read_uint32(ctx->blob);
|
2019-11-04 20:11:11 -05:00
|
|
|
if (header.deref.cast_type_same_as_last) {
|
|
|
|
|
deref->type = ctx->last_type;
|
|
|
|
|
} else {
|
|
|
|
|
deref->type = decode_type_from_blob(ctx->blob);
|
|
|
|
|
ctx->last_type = deref->type;
|
|
|
|
|
}
|
2018-11-28 12:26:52 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case nir_deref_type_array_wildcard:
|
2021-09-08 15:28:53 +01:00
|
|
|
read_src(ctx, &deref->parent);
|
2019-11-04 20:11:11 -05:00
|
|
|
parent = nir_src_as_deref(deref->parent);
|
|
|
|
|
deref->type = glsl_get_array_element(parent->type);
|
2018-03-14 21:45:38 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
unreachable("Invalid deref type");
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 18:24:27 -05:00
|
|
|
if (deref_type == nir_deref_type_var) {
|
2020-10-30 12:14:05 -05:00
|
|
|
deref->modes = deref->var->data.mode;
|
2019-11-05 18:24:27 -05:00
|
|
|
} else if (deref->deref_type == nir_deref_type_cast) {
|
2021-10-15 13:25:50 -05:00
|
|
|
deref->modes = decode_deref_modes(header.deref.modes);
|
2019-11-05 17:39:38 -05:00
|
|
|
} else {
|
|
|
|
|
assert(deref->parent.is_ssa);
|
2020-10-30 12:14:05 -05:00
|
|
|
deref->modes = nir_instr_as_deref(deref->parent.ssa->parent_instr)->modes;
|
2019-11-05 17:39:38 -05:00
|
|
|
}
|
|
|
|
|
|
2018-03-14 21:45:38 -07:00
|
|
|
return deref;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
static void
|
|
|
|
|
write_intrinsic(write_ctx *ctx, const nir_intrinsic_instr *intrin)
|
|
|
|
|
{
|
2021-10-20 17:36:27 +03:00
|
|
|
/* 10 bits for nir_intrinsic_op */
|
|
|
|
|
STATIC_ASSERT(nir_num_intrinsics <= 1024);
|
2017-09-12 23:17:51 -04:00
|
|
|
unsigned num_srcs = nir_intrinsic_infos[intrin->intrinsic].num_srcs;
|
|
|
|
|
unsigned num_indices = nir_intrinsic_infos[intrin->intrinsic].num_indices;
|
2021-10-20 17:36:27 +03:00
|
|
|
assert(intrin->intrinsic < 1024);
|
2019-10-25 02:39:54 -04:00
|
|
|
|
|
|
|
|
union packed_instr header;
|
|
|
|
|
header.u32 = 0;
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
header.intrinsic.instr_type = intrin->instr.type;
|
|
|
|
|
header.intrinsic.intrinsic = intrin->intrinsic;
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2019-11-04 23:29:33 -05:00
|
|
|
/* Analyze constant indices to decide how to encode them. */
|
|
|
|
|
if (num_indices) {
|
|
|
|
|
unsigned max_bits = 0;
|
|
|
|
|
for (unsigned i = 0; i < num_indices; i++) {
|
|
|
|
|
unsigned max = util_last_bit(intrin->const_index[i]);
|
|
|
|
|
max_bits = MAX2(max_bits, max);
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-20 17:36:27 +03:00
|
|
|
if (max_bits * num_indices <= 8) {
|
|
|
|
|
header.intrinsic.const_indices_encoding = const_indices_all_combined;
|
2019-11-04 23:29:33 -05:00
|
|
|
|
2021-10-20 17:36:27 +03:00
|
|
|
/* Pack all const indices into 8 bits. */
|
|
|
|
|
unsigned bit_size = 8 / num_indices;
|
2019-11-04 23:29:33 -05:00
|
|
|
for (unsigned i = 0; i < num_indices; i++) {
|
|
|
|
|
header.intrinsic.packed_const_indices |=
|
|
|
|
|
intrin->const_index[i] << (i * bit_size);
|
|
|
|
|
}
|
|
|
|
|
} else if (max_bits <= 8)
|
|
|
|
|
header.intrinsic.const_indices_encoding = const_indices_8bit;
|
|
|
|
|
else if (max_bits <= 16)
|
|
|
|
|
header.intrinsic.const_indices_encoding = const_indices_16bit;
|
|
|
|
|
else
|
|
|
|
|
header.intrinsic.const_indices_encoding = const_indices_32bit;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
if (nir_intrinsic_infos[intrin->intrinsic].has_dest)
|
2019-11-05 22:14:28 -05:00
|
|
|
write_dest(ctx, &intrin->dest, header, intrin->instr.type);
|
2019-10-25 02:39:54 -04:00
|
|
|
else
|
|
|
|
|
blob_write_uint32(ctx->blob, header.u32);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < num_srcs; i++)
|
|
|
|
|
write_src(ctx, &intrin->src[i]);
|
|
|
|
|
|
2019-11-04 23:29:33 -05:00
|
|
|
if (num_indices) {
|
|
|
|
|
switch (header.intrinsic.const_indices_encoding) {
|
|
|
|
|
case const_indices_8bit:
|
|
|
|
|
for (unsigned i = 0; i < num_indices; i++)
|
|
|
|
|
blob_write_uint8(ctx->blob, intrin->const_index[i]);
|
|
|
|
|
break;
|
|
|
|
|
case const_indices_16bit:
|
|
|
|
|
for (unsigned i = 0; i < num_indices; i++)
|
|
|
|
|
blob_write_uint16(ctx->blob, intrin->const_index[i]);
|
|
|
|
|
break;
|
|
|
|
|
case const_indices_32bit:
|
|
|
|
|
for (unsigned i = 0; i < num_indices; i++)
|
|
|
|
|
blob_write_uint32(ctx->blob, intrin->const_index[i]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_intrinsic_instr *
|
2019-10-25 02:39:54 -04:00
|
|
|
read_intrinsic(read_ctx *ctx, union packed_instr header)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
2019-10-25 02:39:54 -04:00
|
|
|
nir_intrinsic_op op = header.intrinsic.intrinsic;
|
2017-09-12 23:17:51 -04:00
|
|
|
nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(ctx->nir, op);
|
|
|
|
|
|
|
|
|
|
unsigned num_srcs = nir_intrinsic_infos[op].num_srcs;
|
|
|
|
|
unsigned num_indices = nir_intrinsic_infos[op].num_indices;
|
|
|
|
|
|
|
|
|
|
if (nir_intrinsic_infos[op].has_dest)
|
2019-10-25 02:39:54 -04:00
|
|
|
read_dest(ctx, &intrin->dest, &intrin->instr, header);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < num_srcs; i++)
|
2021-09-08 15:28:53 +01:00
|
|
|
read_src(ctx, &intrin->src[i]);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2019-11-21 19:45:46 -05:00
|
|
|
/* Vectorized instrinsics have num_components same as dst or src that has
|
|
|
|
|
* 0 components in the info. Find it.
|
|
|
|
|
*/
|
|
|
|
|
if (nir_intrinsic_infos[op].has_dest &&
|
|
|
|
|
nir_intrinsic_infos[op].dest_components == 0) {
|
|
|
|
|
intrin->num_components = nir_dest_num_components(intrin->dest);
|
|
|
|
|
} else {
|
|
|
|
|
for (unsigned i = 0; i < num_srcs; i++) {
|
|
|
|
|
if (nir_intrinsic_infos[op].src_components[i] == 0) {
|
|
|
|
|
intrin->num_components = nir_src_num_components(intrin->src[i]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-04 23:29:33 -05:00
|
|
|
if (num_indices) {
|
|
|
|
|
switch (header.intrinsic.const_indices_encoding) {
|
2021-10-20 17:36:27 +03:00
|
|
|
case const_indices_all_combined: {
|
|
|
|
|
unsigned bit_size = 8 / num_indices;
|
2019-11-04 23:29:33 -05:00
|
|
|
unsigned bit_mask = u_bit_consecutive(0, bit_size);
|
|
|
|
|
for (unsigned i = 0; i < num_indices; i++) {
|
|
|
|
|
intrin->const_index[i] =
|
|
|
|
|
(header.intrinsic.packed_const_indices >> (i * bit_size)) &
|
|
|
|
|
bit_mask;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case const_indices_8bit:
|
|
|
|
|
for (unsigned i = 0; i < num_indices; i++)
|
|
|
|
|
intrin->const_index[i] = blob_read_uint8(ctx->blob);
|
|
|
|
|
break;
|
|
|
|
|
case const_indices_16bit:
|
|
|
|
|
for (unsigned i = 0; i < num_indices; i++)
|
|
|
|
|
intrin->const_index[i] = blob_read_uint16(ctx->blob);
|
|
|
|
|
break;
|
|
|
|
|
case const_indices_32bit:
|
|
|
|
|
for (unsigned i = 0; i < num_indices; i++)
|
|
|
|
|
intrin->const_index[i] = blob_read_uint32(ctx->blob);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
return intrin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_load_const(write_ctx *ctx, const nir_load_const_instr *lc)
|
|
|
|
|
{
|
2019-10-25 02:39:54 -04:00
|
|
|
assert(lc->def.num_components >= 1 && lc->def.num_components <= 16);
|
|
|
|
|
union packed_instr header;
|
|
|
|
|
header.u32 = 0;
|
|
|
|
|
|
|
|
|
|
header.load_const.instr_type = lc->instr.type;
|
|
|
|
|
header.load_const.last_component = lc->def.num_components - 1;
|
|
|
|
|
header.load_const.bit_size = encode_bit_size_3bits(lc->def.bit_size);
|
2019-11-04 22:25:15 -05:00
|
|
|
header.load_const.packing = load_const_full;
|
|
|
|
|
|
|
|
|
|
/* Try to pack 1-component constants into the 19 free bits in the header. */
|
|
|
|
|
if (lc->def.num_components == 1) {
|
|
|
|
|
switch (lc->def.bit_size) {
|
|
|
|
|
case 64:
|
|
|
|
|
if ((lc->value[0].u64 & 0x1fffffffffffull) == 0) {
|
|
|
|
|
/* packed_value contains high 19 bits, low bits are 0 */
|
|
|
|
|
header.load_const.packing = load_const_scalar_hi_19bits;
|
|
|
|
|
header.load_const.packed_value = lc->value[0].u64 >> 45;
|
2022-07-01 13:50:58 -05:00
|
|
|
} else if (util_mask_sign_extend(lc->value[0].i64, 19) == lc->value[0].i64) {
|
2019-11-04 22:25:15 -05:00
|
|
|
/* packed_value contains low 19 bits, high bits are sign-extended */
|
|
|
|
|
header.load_const.packing = load_const_scalar_lo_19bits_sext;
|
|
|
|
|
header.load_const.packed_value = lc->value[0].u64;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 32:
|
|
|
|
|
if ((lc->value[0].u32 & 0x1fff) == 0) {
|
|
|
|
|
header.load_const.packing = load_const_scalar_hi_19bits;
|
|
|
|
|
header.load_const.packed_value = lc->value[0].u32 >> 13;
|
2022-07-01 13:50:58 -05:00
|
|
|
} else if (util_mask_sign_extend(lc->value[0].i32, 19) == lc->value[0].i32) {
|
2019-11-04 22:25:15 -05:00
|
|
|
header.load_const.packing = load_const_scalar_lo_19bits_sext;
|
|
|
|
|
header.load_const.packed_value = lc->value[0].u32;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 16:
|
|
|
|
|
header.load_const.packing = load_const_scalar_lo_19bits_sext;
|
|
|
|
|
header.load_const.packed_value = lc->value[0].u16;
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
header.load_const.packing = load_const_scalar_lo_19bits_sext;
|
|
|
|
|
header.load_const.packed_value = lc->value[0].u8;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
header.load_const.packing = load_const_scalar_lo_19bits_sext;
|
|
|
|
|
header.load_const.packed_value = lc->value[0].b;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("invalid bit_size");
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-10-25 02:39:54 -04:00
|
|
|
|
|
|
|
|
blob_write_uint32(ctx->blob, header.u32);
|
2019-11-04 22:15:17 -05:00
|
|
|
|
2019-11-04 22:25:15 -05:00
|
|
|
if (header.load_const.packing == load_const_full) {
|
|
|
|
|
switch (lc->def.bit_size) {
|
|
|
|
|
case 64:
|
|
|
|
|
blob_write_bytes(ctx->blob, lc->value,
|
|
|
|
|
sizeof(*lc->value) * lc->def.num_components);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 32:
|
|
|
|
|
for (unsigned i = 0; i < lc->def.num_components; i++)
|
|
|
|
|
blob_write_uint32(ctx->blob, lc->value[i].u32);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 16:
|
|
|
|
|
for (unsigned i = 0; i < lc->def.num_components; i++)
|
|
|
|
|
blob_write_uint16(ctx->blob, lc->value[i].u16);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
assert(lc->def.bit_size <= 8);
|
|
|
|
|
for (unsigned i = 0; i < lc->def.num_components; i++)
|
|
|
|
|
blob_write_uint8(ctx->blob, lc->value[i].u8);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-11-04 22:15:17 -05:00
|
|
|
}
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
write_add_object(ctx, &lc->def);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_load_const_instr *
|
2019-10-25 02:39:54 -04:00
|
|
|
read_load_const(read_ctx *ctx, union packed_instr header)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
|
|
|
|
nir_load_const_instr *lc =
|
2019-10-25 02:39:54 -04:00
|
|
|
nir_load_const_instr_create(ctx->nir, header.load_const.last_component + 1,
|
|
|
|
|
decode_bit_size_3bits(header.load_const.bit_size));
|
2022-07-07 12:44:10 +02:00
|
|
|
lc->def.divergent = false;
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2019-11-04 22:25:15 -05:00
|
|
|
switch (header.load_const.packing) {
|
|
|
|
|
case load_const_scalar_hi_19bits:
|
|
|
|
|
switch (lc->def.bit_size) {
|
|
|
|
|
case 64:
|
|
|
|
|
lc->value[0].u64 = (uint64_t)header.load_const.packed_value << 45;
|
|
|
|
|
break;
|
|
|
|
|
case 32:
|
|
|
|
|
lc->value[0].u32 = (uint64_t)header.load_const.packed_value << 13;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("invalid bit_size");
|
|
|
|
|
}
|
2019-11-04 22:15:17 -05:00
|
|
|
break;
|
|
|
|
|
|
2019-11-04 22:25:15 -05:00
|
|
|
case load_const_scalar_lo_19bits_sext:
|
|
|
|
|
switch (lc->def.bit_size) {
|
|
|
|
|
case 64:
|
|
|
|
|
lc->value[0].i64 = ((int64_t)header.load_const.packed_value << 45) >> 45;
|
|
|
|
|
break;
|
|
|
|
|
case 32:
|
|
|
|
|
lc->value[0].i32 = ((int32_t)header.load_const.packed_value << 13) >> 13;
|
|
|
|
|
break;
|
|
|
|
|
case 16:
|
|
|
|
|
lc->value[0].u16 = header.load_const.packed_value;
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
lc->value[0].u8 = header.load_const.packed_value;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
lc->value[0].b = header.load_const.packed_value;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("invalid bit_size");
|
|
|
|
|
}
|
2019-11-04 22:15:17 -05:00
|
|
|
break;
|
|
|
|
|
|
2019-11-04 22:25:15 -05:00
|
|
|
case load_const_full:
|
|
|
|
|
switch (lc->def.bit_size) {
|
|
|
|
|
case 64:
|
|
|
|
|
blob_copy_bytes(ctx->blob, lc->value, sizeof(*lc->value) * lc->def.num_components);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 32:
|
|
|
|
|
for (unsigned i = 0; i < lc->def.num_components; i++)
|
|
|
|
|
lc->value[i].u32 = blob_read_uint32(ctx->blob);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 16:
|
|
|
|
|
for (unsigned i = 0; i < lc->def.num_components; i++)
|
|
|
|
|
lc->value[i].u16 = blob_read_uint16(ctx->blob);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
assert(lc->def.bit_size <= 8);
|
|
|
|
|
for (unsigned i = 0; i < lc->def.num_components; i++)
|
|
|
|
|
lc->value[i].u8 = blob_read_uint8(ctx->blob);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-11-04 22:15:17 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
read_add_object(ctx, &lc->def);
|
|
|
|
|
return lc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_ssa_undef(write_ctx *ctx, const nir_ssa_undef_instr *undef)
|
|
|
|
|
{
|
2019-10-25 02:39:54 -04:00
|
|
|
assert(undef->def.num_components >= 1 && undef->def.num_components <= 16);
|
|
|
|
|
|
|
|
|
|
union packed_instr header;
|
|
|
|
|
header.u32 = 0;
|
|
|
|
|
|
|
|
|
|
header.undef.instr_type = undef->instr.type;
|
|
|
|
|
header.undef.last_component = undef->def.num_components - 1;
|
|
|
|
|
header.undef.bit_size = encode_bit_size_3bits(undef->def.bit_size);
|
|
|
|
|
|
|
|
|
|
blob_write_uint32(ctx->blob, header.u32);
|
2017-09-12 23:17:51 -04:00
|
|
|
write_add_object(ctx, &undef->def);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_ssa_undef_instr *
|
2019-10-25 02:39:54 -04:00
|
|
|
read_ssa_undef(read_ctx *ctx, union packed_instr header)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
|
|
|
|
nir_ssa_undef_instr *undef =
|
2019-10-25 02:39:54 -04:00
|
|
|
nir_ssa_undef_instr_create(ctx->nir, header.undef.last_component + 1,
|
|
|
|
|
decode_bit_size_3bits(header.undef.bit_size));
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2022-07-07 12:44:10 +02:00
|
|
|
undef->def.divergent = false;
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
read_add_object(ctx, &undef->def);
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
union packed_tex_data {
|
|
|
|
|
uint32_t u32;
|
|
|
|
|
struct {
|
2020-05-01 15:04:06 -07:00
|
|
|
unsigned sampler_dim:4;
|
2020-05-14 14:50:52 -05:00
|
|
|
unsigned dest_type:8;
|
2017-09-12 23:17:51 -04:00
|
|
|
unsigned coord_components:3;
|
|
|
|
|
unsigned is_array:1;
|
|
|
|
|
unsigned is_shadow:1;
|
|
|
|
|
unsigned is_new_style_shadow:1;
|
2020-11-20 15:10:42 +00:00
|
|
|
unsigned is_sparse:1;
|
2017-09-12 23:17:51 -04:00
|
|
|
unsigned component:2;
|
2020-01-01 14:42:58 +01:00
|
|
|
unsigned texture_non_uniform:1;
|
|
|
|
|
unsigned sampler_non_uniform:1;
|
2021-01-13 10:28:59 +01:00
|
|
|
unsigned array_is_lowered_cube:1;
|
2023-04-13 14:13:35 +01:00
|
|
|
unsigned is_gather_implicit_lod:1;
|
|
|
|
|
unsigned unused:5; /* Mark unused for valgrind. */
|
2017-11-03 12:58:25 +10:00
|
|
|
} u;
|
2017-09-12 23:17:51 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_tex(write_ctx *ctx, const nir_tex_instr *tex)
|
|
|
|
|
{
|
2019-10-25 02:39:54 -04:00
|
|
|
assert(tex->num_srcs < 16);
|
2022-06-23 16:32:12 +02:00
|
|
|
assert(tex->op < 32);
|
2019-10-25 02:39:54 -04:00
|
|
|
|
|
|
|
|
union packed_instr header;
|
|
|
|
|
header.u32 = 0;
|
|
|
|
|
|
|
|
|
|
header.tex.instr_type = tex->instr.type;
|
|
|
|
|
header.tex.num_srcs = tex->num_srcs;
|
|
|
|
|
header.tex.op = tex->op;
|
|
|
|
|
|
2019-11-05 22:14:28 -05:00
|
|
|
write_dest(ctx, &tex->dest, header, tex->instr.type);
|
2019-10-25 02:39:54 -04:00
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
blob_write_uint32(ctx->blob, tex->texture_index);
|
|
|
|
|
blob_write_uint32(ctx->blob, tex->sampler_index);
|
2019-10-25 02:39:54 -04:00
|
|
|
if (tex->op == nir_texop_tg4)
|
|
|
|
|
blob_write_bytes(ctx->blob, tex->tg4_offsets, sizeof(tex->tg4_offsets));
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
STATIC_ASSERT(sizeof(union packed_tex_data) == sizeof(uint32_t));
|
|
|
|
|
union packed_tex_data packed = {
|
2017-11-03 12:58:25 +10:00
|
|
|
.u.sampler_dim = tex->sampler_dim,
|
|
|
|
|
.u.dest_type = tex->dest_type,
|
|
|
|
|
.u.coord_components = tex->coord_components,
|
|
|
|
|
.u.is_array = tex->is_array,
|
|
|
|
|
.u.is_shadow = tex->is_shadow,
|
|
|
|
|
.u.is_new_style_shadow = tex->is_new_style_shadow,
|
2020-11-20 15:10:42 +00:00
|
|
|
.u.is_sparse = tex->is_sparse,
|
2017-11-03 12:58:25 +10:00
|
|
|
.u.component = tex->component,
|
2020-01-01 14:42:58 +01:00
|
|
|
.u.texture_non_uniform = tex->texture_non_uniform,
|
|
|
|
|
.u.sampler_non_uniform = tex->sampler_non_uniform,
|
2021-01-13 10:28:59 +01:00
|
|
|
.u.array_is_lowered_cube = tex->array_is_lowered_cube,
|
2023-04-13 14:13:35 +01:00
|
|
|
.u.is_gather_implicit_lod = tex->is_gather_implicit_lod,
|
2017-09-12 23:17:51 -04:00
|
|
|
};
|
|
|
|
|
blob_write_uint32(ctx->blob, packed.u32);
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < tex->num_srcs; i++) {
|
2019-10-30 18:14:37 -04:00
|
|
|
union packed_src src;
|
|
|
|
|
src.u32 = 0;
|
|
|
|
|
src.tex.src_type = tex->src[i].src_type;
|
|
|
|
|
write_src_full(ctx, &tex->src[i].src, src);
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_tex_instr *
|
2019-10-25 02:39:54 -04:00
|
|
|
read_tex(read_ctx *ctx, union packed_instr header)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
2019-10-25 02:39:54 -04:00
|
|
|
nir_tex_instr *tex = nir_tex_instr_create(ctx->nir, header.tex.num_srcs);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
read_dest(ctx, &tex->dest, &tex->instr, header);
|
|
|
|
|
|
|
|
|
|
tex->op = header.tex.op;
|
2017-09-12 23:17:51 -04:00
|
|
|
tex->texture_index = blob_read_uint32(ctx->blob);
|
|
|
|
|
tex->sampler_index = blob_read_uint32(ctx->blob);
|
2019-10-25 02:39:54 -04:00
|
|
|
if (tex->op == nir_texop_tg4)
|
|
|
|
|
blob_copy_bytes(ctx->blob, tex->tg4_offsets, sizeof(tex->tg4_offsets));
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
union packed_tex_data packed;
|
|
|
|
|
packed.u32 = blob_read_uint32(ctx->blob);
|
2017-11-03 12:58:25 +10:00
|
|
|
tex->sampler_dim = packed.u.sampler_dim;
|
|
|
|
|
tex->dest_type = packed.u.dest_type;
|
|
|
|
|
tex->coord_components = packed.u.coord_components;
|
|
|
|
|
tex->is_array = packed.u.is_array;
|
|
|
|
|
tex->is_shadow = packed.u.is_shadow;
|
|
|
|
|
tex->is_new_style_shadow = packed.u.is_new_style_shadow;
|
2020-11-20 15:10:42 +00:00
|
|
|
tex->is_sparse = packed.u.is_sparse;
|
2017-11-03 12:58:25 +10:00
|
|
|
tex->component = packed.u.component;
|
2020-01-01 14:42:58 +01:00
|
|
|
tex->texture_non_uniform = packed.u.texture_non_uniform;
|
|
|
|
|
tex->sampler_non_uniform = packed.u.sampler_non_uniform;
|
2021-01-13 10:28:59 +01:00
|
|
|
tex->array_is_lowered_cube = packed.u.array_is_lowered_cube;
|
2023-04-13 14:13:35 +01:00
|
|
|
tex->is_gather_implicit_lod = packed.u.is_gather_implicit_lod;
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < tex->num_srcs; i++) {
|
2021-09-08 15:28:53 +01:00
|
|
|
union packed_src src = read_src(ctx, &tex->src[i].src);
|
2019-10-30 18:14:37 -04:00
|
|
|
tex->src[i].src_type = src.tex.src_type;
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_phi(write_ctx *ctx, const nir_phi_instr *phi)
|
|
|
|
|
{
|
2019-10-25 02:39:54 -04:00
|
|
|
union packed_instr header;
|
|
|
|
|
header.u32 = 0;
|
|
|
|
|
|
|
|
|
|
header.phi.instr_type = phi->instr.type;
|
|
|
|
|
header.phi.num_srcs = exec_list_length(&phi->srcs);
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
/* Phi nodes are special, since they may reference SSA definitions and
|
2019-10-25 01:02:54 -04:00
|
|
|
* basic blocks that don't exist yet. We leave two empty uint32_t's here,
|
2017-09-12 23:17:51 -04:00
|
|
|
* and then store enough information so that a later fixup pass can fill
|
|
|
|
|
* them in correctly.
|
|
|
|
|
*/
|
2019-11-05 22:14:28 -05:00
|
|
|
write_dest(ctx, &phi->dest, header, phi->instr.type);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
nir_foreach_phi_src(src, phi) {
|
|
|
|
|
assert(src->src.is_ssa);
|
2019-10-25 01:02:54 -04:00
|
|
|
size_t blob_offset = blob_reserve_uint32(ctx->blob);
|
|
|
|
|
ASSERTED size_t blob_offset2 = blob_reserve_uint32(ctx->blob);
|
|
|
|
|
assert(blob_offset + sizeof(uint32_t) == blob_offset2);
|
2017-09-12 23:17:51 -04:00
|
|
|
write_phi_fixup fixup = {
|
|
|
|
|
.blob_offset = blob_offset,
|
|
|
|
|
.src = src->src.ssa,
|
|
|
|
|
.block = src->pred,
|
|
|
|
|
};
|
|
|
|
|
util_dynarray_append(&ctx->phi_fixups, write_phi_fixup, fixup);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_fixup_phis(write_ctx *ctx)
|
|
|
|
|
{
|
|
|
|
|
util_dynarray_foreach(&ctx->phi_fixups, write_phi_fixup, fixup) {
|
2022-02-03 17:16:36 +01:00
|
|
|
blob_overwrite_uint32(ctx->blob, fixup->blob_offset,
|
|
|
|
|
write_lookup_object(ctx, fixup->src));
|
|
|
|
|
blob_overwrite_uint32(ctx->blob, fixup->blob_offset + sizeof(uint32_t),
|
|
|
|
|
write_lookup_object(ctx, fixup->block));
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
util_dynarray_clear(&ctx->phi_fixups);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_phi_instr *
|
2019-10-25 02:39:54 -04:00
|
|
|
read_phi(read_ctx *ctx, nir_block *blk, union packed_instr header)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
|
|
|
|
nir_phi_instr *phi = nir_phi_instr_create(ctx->nir);
|
|
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
read_dest(ctx, &phi->dest, &phi->instr, header);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
/* For similar reasons as before, we just store the index directly into the
|
|
|
|
|
* pointer, and let a later pass resolve the phi sources.
|
|
|
|
|
*
|
|
|
|
|
* In order to ensure that the copied sources (which are just the indices
|
|
|
|
|
* from the blob for now) don't get inserted into the old shader's use-def
|
|
|
|
|
* lists, we have to add the phi instruction *before* we set up its
|
|
|
|
|
* sources.
|
|
|
|
|
*/
|
|
|
|
|
nir_instr_insert_after_block(blk, &phi->instr);
|
|
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
for (unsigned i = 0; i < header.phi.num_srcs; i++) {
|
2021-07-07 13:24:45 -07:00
|
|
|
nir_ssa_def *def = (nir_ssa_def *)(uintptr_t) blob_read_uint32(ctx->blob);
|
|
|
|
|
nir_block *pred = (nir_block *)(uintptr_t) blob_read_uint32(ctx->blob);
|
|
|
|
|
nir_phi_src *src = nir_phi_instr_add_src(phi, pred, nir_src_for_ssa(def));
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
/* Since we're not letting nir_insert_instr handle use/def stuff for us,
|
|
|
|
|
* we have to set the parent_instr manually. It doesn't really matter
|
|
|
|
|
* when we do it, so we might as well do it here.
|
|
|
|
|
*/
|
|
|
|
|
src->src.parent_instr = &phi->instr;
|
|
|
|
|
|
|
|
|
|
/* Stash it in the list of phi sources. We'll walk this list and fix up
|
|
|
|
|
* sources at the very end of read_function_impl.
|
|
|
|
|
*/
|
|
|
|
|
list_add(&src->src.use_link, &ctx->phi_srcs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return phi;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
read_fixup_phis(read_ctx *ctx)
|
|
|
|
|
{
|
|
|
|
|
list_for_each_entry_safe(nir_phi_src, src, &ctx->phi_srcs, src.use_link) {
|
|
|
|
|
src->pred = read_lookup_object(ctx, (uintptr_t)src->pred);
|
|
|
|
|
src->src.ssa = read_lookup_object(ctx, (uintptr_t)src->src.ssa);
|
|
|
|
|
|
|
|
|
|
/* Remove from this list */
|
|
|
|
|
list_del(&src->src.use_link);
|
|
|
|
|
|
|
|
|
|
list_addtail(&src->src.use_link, &src->src.ssa->uses);
|
|
|
|
|
}
|
2019-10-28 21:27:52 +11:00
|
|
|
assert(list_is_empty(&ctx->phi_srcs));
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_jump(write_ctx *ctx, const nir_jump_instr *jmp)
|
|
|
|
|
{
|
2020-09-24 18:55:09 -05:00
|
|
|
/* These aren't handled because they require special block linking */
|
|
|
|
|
assert(jmp->type != nir_jump_goto && jmp->type != nir_jump_goto_if);
|
|
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
assert(jmp->type < 4);
|
|
|
|
|
|
|
|
|
|
union packed_instr header;
|
|
|
|
|
header.u32 = 0;
|
|
|
|
|
|
|
|
|
|
header.jump.instr_type = jmp->instr.type;
|
|
|
|
|
header.jump.type = jmp->type;
|
|
|
|
|
|
|
|
|
|
blob_write_uint32(ctx->blob, header.u32);
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_jump_instr *
|
2019-10-25 02:39:54 -04:00
|
|
|
read_jump(read_ctx *ctx, union packed_instr header)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
2020-09-24 18:55:09 -05:00
|
|
|
/* These aren't handled because they require special block linking */
|
|
|
|
|
assert(header.jump.type != nir_jump_goto &&
|
|
|
|
|
header.jump.type != nir_jump_goto_if);
|
|
|
|
|
|
2019-10-25 02:39:54 -04:00
|
|
|
nir_jump_instr *jmp = nir_jump_instr_create(ctx->nir, header.jump.type);
|
2017-09-12 23:17:51 -04:00
|
|
|
return jmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_call(write_ctx *ctx, const nir_call_instr *call)
|
|
|
|
|
{
|
2019-10-25 01:02:54 -04:00
|
|
|
blob_write_uint32(ctx->blob, write_lookup_object(ctx, call->callee));
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < call->num_params; i++)
|
2018-03-22 16:41:18 -07:00
|
|
|
write_src(ctx, &call->params[i]);
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_call_instr *
|
|
|
|
|
read_call(read_ctx *ctx)
|
|
|
|
|
{
|
|
|
|
|
nir_function *callee = read_object(ctx);
|
|
|
|
|
nir_call_instr *call = nir_call_instr_create(ctx->nir, callee);
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < call->num_params; i++)
|
2021-09-08 15:28:53 +01:00
|
|
|
read_src(ctx, &call->params[i]);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
return call;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_instr(write_ctx *ctx, const nir_instr *instr)
|
|
|
|
|
{
|
2019-10-25 02:39:54 -04:00
|
|
|
/* We have only 4 bits for the instruction type. */
|
|
|
|
|
assert(instr->type < 16);
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
switch (instr->type) {
|
|
|
|
|
case nir_instr_type_alu:
|
|
|
|
|
write_alu(ctx, nir_instr_as_alu(instr));
|
|
|
|
|
break;
|
2018-03-14 21:45:38 -07:00
|
|
|
case nir_instr_type_deref:
|
|
|
|
|
write_deref(ctx, nir_instr_as_deref(instr));
|
|
|
|
|
break;
|
2017-09-12 23:17:51 -04:00
|
|
|
case nir_instr_type_intrinsic:
|
|
|
|
|
write_intrinsic(ctx, nir_instr_as_intrinsic(instr));
|
|
|
|
|
break;
|
|
|
|
|
case nir_instr_type_load_const:
|
|
|
|
|
write_load_const(ctx, nir_instr_as_load_const(instr));
|
|
|
|
|
break;
|
|
|
|
|
case nir_instr_type_ssa_undef:
|
|
|
|
|
write_ssa_undef(ctx, nir_instr_as_ssa_undef(instr));
|
|
|
|
|
break;
|
|
|
|
|
case nir_instr_type_tex:
|
|
|
|
|
write_tex(ctx, nir_instr_as_tex(instr));
|
|
|
|
|
break;
|
|
|
|
|
case nir_instr_type_phi:
|
|
|
|
|
write_phi(ctx, nir_instr_as_phi(instr));
|
|
|
|
|
break;
|
|
|
|
|
case nir_instr_type_jump:
|
|
|
|
|
write_jump(ctx, nir_instr_as_jump(instr));
|
|
|
|
|
break;
|
|
|
|
|
case nir_instr_type_call:
|
2019-10-25 02:39:54 -04:00
|
|
|
blob_write_uint32(ctx->blob, instr->type);
|
2017-09-12 23:17:51 -04:00
|
|
|
write_call(ctx, nir_instr_as_call(instr));
|
|
|
|
|
break;
|
|
|
|
|
case nir_instr_type_parallel_copy:
|
|
|
|
|
unreachable("Cannot write parallel copies");
|
|
|
|
|
default:
|
|
|
|
|
unreachable("bad instr type");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 22:14:28 -05:00
|
|
|
/* Return the number of instructions read. */
|
|
|
|
|
static unsigned
|
2017-09-12 23:17:51 -04:00
|
|
|
read_instr(read_ctx *ctx, nir_block *block)
|
|
|
|
|
{
|
2019-10-25 02:39:54 -04:00
|
|
|
STATIC_ASSERT(sizeof(union packed_instr) == 4);
|
|
|
|
|
union packed_instr header;
|
|
|
|
|
header.u32 = blob_read_uint32(ctx->blob);
|
2017-09-12 23:17:51 -04:00
|
|
|
nir_instr *instr;
|
2019-10-25 02:39:54 -04:00
|
|
|
|
|
|
|
|
switch (header.any.instr_type) {
|
2017-09-12 23:17:51 -04:00
|
|
|
case nir_instr_type_alu:
|
2019-11-05 22:14:28 -05:00
|
|
|
for (unsigned i = 0; i <= header.alu.num_followup_alu_sharing_header; i++)
|
|
|
|
|
nir_instr_insert_after_block(block, &read_alu(ctx, header)->instr);
|
|
|
|
|
return header.alu.num_followup_alu_sharing_header + 1;
|
2018-03-14 21:45:38 -07:00
|
|
|
case nir_instr_type_deref:
|
2019-10-25 02:39:54 -04:00
|
|
|
instr = &read_deref(ctx, header)->instr;
|
2018-03-14 21:45:38 -07:00
|
|
|
break;
|
2017-09-12 23:17:51 -04:00
|
|
|
case nir_instr_type_intrinsic:
|
2019-10-25 02:39:54 -04:00
|
|
|
instr = &read_intrinsic(ctx, header)->instr;
|
2017-09-12 23:17:51 -04:00
|
|
|
break;
|
|
|
|
|
case nir_instr_type_load_const:
|
2019-10-25 02:39:54 -04:00
|
|
|
instr = &read_load_const(ctx, header)->instr;
|
2017-09-12 23:17:51 -04:00
|
|
|
break;
|
|
|
|
|
case nir_instr_type_ssa_undef:
|
2019-10-25 02:39:54 -04:00
|
|
|
instr = &read_ssa_undef(ctx, header)->instr;
|
2017-09-12 23:17:51 -04:00
|
|
|
break;
|
|
|
|
|
case nir_instr_type_tex:
|
2019-10-25 02:39:54 -04:00
|
|
|
instr = &read_tex(ctx, header)->instr;
|
2017-09-12 23:17:51 -04:00
|
|
|
break;
|
|
|
|
|
case nir_instr_type_phi:
|
|
|
|
|
/* Phi instructions are a bit of a special case when reading because we
|
|
|
|
|
* don't want inserting the instruction to automatically handle use/defs
|
|
|
|
|
* for us. Instead, we need to wait until all the blocks/instructions
|
|
|
|
|
* are read so that we can set their sources up.
|
|
|
|
|
*/
|
2019-10-25 02:39:54 -04:00
|
|
|
read_phi(ctx, block, header);
|
2019-11-05 22:14:28 -05:00
|
|
|
return 1;
|
2017-09-12 23:17:51 -04:00
|
|
|
case nir_instr_type_jump:
|
2019-10-25 02:39:54 -04:00
|
|
|
instr = &read_jump(ctx, header)->instr;
|
2017-09-12 23:17:51 -04:00
|
|
|
break;
|
|
|
|
|
case nir_instr_type_call:
|
|
|
|
|
instr = &read_call(ctx)->instr;
|
|
|
|
|
break;
|
|
|
|
|
case nir_instr_type_parallel_copy:
|
|
|
|
|
unreachable("Cannot read parallel copies");
|
|
|
|
|
default:
|
|
|
|
|
unreachable("bad instr type");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nir_instr_insert_after_block(block, instr);
|
2019-11-05 22:14:28 -05:00
|
|
|
return 1;
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_block(write_ctx *ctx, const nir_block *block)
|
|
|
|
|
{
|
|
|
|
|
write_add_object(ctx, block);
|
|
|
|
|
blob_write_uint32(ctx->blob, exec_list_length(&block->instr_list));
|
2019-11-05 22:14:28 -05:00
|
|
|
|
|
|
|
|
ctx->last_instr_type = ~0;
|
|
|
|
|
ctx->last_alu_header_offset = 0;
|
|
|
|
|
|
|
|
|
|
nir_foreach_instr(instr, block) {
|
2017-09-12 23:17:51 -04:00
|
|
|
write_instr(ctx, instr);
|
2019-11-05 22:14:28 -05:00
|
|
|
ctx->last_instr_type = instr->type;
|
|
|
|
|
}
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
read_block(read_ctx *ctx, struct exec_list *cf_list)
|
|
|
|
|
{
|
|
|
|
|
/* Don't actually create a new block. Just use the one from the tail of
|
|
|
|
|
* the list. NIR guarantees that the tail of the list is a block and that
|
|
|
|
|
* no two blocks are side-by-side in the IR; It should be empty.
|
|
|
|
|
*/
|
|
|
|
|
nir_block *block =
|
|
|
|
|
exec_node_data(nir_block, exec_list_get_tail(cf_list), cf_node.node);
|
|
|
|
|
|
|
|
|
|
read_add_object(ctx, block);
|
|
|
|
|
unsigned num_instrs = blob_read_uint32(ctx->blob);
|
2019-11-05 22:14:28 -05:00
|
|
|
for (unsigned i = 0; i < num_instrs;) {
|
|
|
|
|
i += read_instr(ctx, block);
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_cf_list(write_ctx *ctx, const struct exec_list *cf_list);
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
read_cf_list(read_ctx *ctx, struct exec_list *cf_list);
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_if(write_ctx *ctx, nir_if *nif)
|
|
|
|
|
{
|
|
|
|
|
write_src(ctx, &nif->condition);
|
2021-09-08 18:09:18 +01:00
|
|
|
blob_write_uint8(ctx->blob, nif->control);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
write_cf_list(ctx, &nif->then_list);
|
|
|
|
|
write_cf_list(ctx, &nif->else_list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
read_if(read_ctx *ctx, struct exec_list *cf_list)
|
|
|
|
|
{
|
|
|
|
|
nir_if *nif = nir_if_create(ctx->nir);
|
|
|
|
|
|
2021-09-08 15:28:53 +01:00
|
|
|
read_src(ctx, &nif->condition);
|
2021-09-08 18:09:18 +01:00
|
|
|
nif->control = blob_read_uint8(ctx->blob);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
nir_cf_node_insert_end(cf_list, &nif->cf_node);
|
|
|
|
|
|
|
|
|
|
read_cf_list(ctx, &nif->then_list);
|
|
|
|
|
read_cf_list(ctx, &nif->else_list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_loop(write_ctx *ctx, nir_loop *loop)
|
|
|
|
|
{
|
2021-09-08 18:09:18 +01:00
|
|
|
blob_write_uint8(ctx->blob, loop->control);
|
2021-11-19 22:01:05 -05:00
|
|
|
blob_write_uint8(ctx->blob, loop->divergent);
|
2021-12-01 17:34:48 +01:00
|
|
|
bool has_continue_construct = nir_loop_has_continue_construct(loop);
|
|
|
|
|
blob_write_uint8(ctx->blob, has_continue_construct);
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
write_cf_list(ctx, &loop->body);
|
2021-12-01 17:34:48 +01:00
|
|
|
if (has_continue_construct) {
|
|
|
|
|
write_cf_list(ctx, &loop->continue_list);
|
|
|
|
|
}
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
read_loop(read_ctx *ctx, struct exec_list *cf_list)
|
|
|
|
|
{
|
|
|
|
|
nir_loop *loop = nir_loop_create(ctx->nir);
|
|
|
|
|
|
|
|
|
|
nir_cf_node_insert_end(cf_list, &loop->cf_node);
|
|
|
|
|
|
2021-09-08 18:09:18 +01:00
|
|
|
loop->control = blob_read_uint8(ctx->blob);
|
2021-11-19 22:01:05 -05:00
|
|
|
loop->divergent = blob_read_uint8(ctx->blob);
|
2021-12-01 17:34:48 +01:00
|
|
|
bool has_continue_construct = blob_read_uint8(ctx->blob);
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
read_cf_list(ctx, &loop->body);
|
2021-12-01 17:34:48 +01:00
|
|
|
if (has_continue_construct) {
|
|
|
|
|
nir_loop_add_continue_construct(loop);
|
|
|
|
|
read_cf_list(ctx, &loop->continue_list);
|
|
|
|
|
}
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_cf_node(write_ctx *ctx, nir_cf_node *cf)
|
|
|
|
|
{
|
|
|
|
|
blob_write_uint32(ctx->blob, cf->type);
|
|
|
|
|
|
|
|
|
|
switch (cf->type) {
|
|
|
|
|
case nir_cf_node_block:
|
|
|
|
|
write_block(ctx, nir_cf_node_as_block(cf));
|
|
|
|
|
break;
|
|
|
|
|
case nir_cf_node_if:
|
|
|
|
|
write_if(ctx, nir_cf_node_as_if(cf));
|
|
|
|
|
break;
|
|
|
|
|
case nir_cf_node_loop:
|
|
|
|
|
write_loop(ctx, nir_cf_node_as_loop(cf));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("bad cf type");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
read_cf_node(read_ctx *ctx, struct exec_list *list)
|
|
|
|
|
{
|
|
|
|
|
nir_cf_node_type type = blob_read_uint32(ctx->blob);
|
|
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
case nir_cf_node_block:
|
|
|
|
|
read_block(ctx, list);
|
|
|
|
|
break;
|
|
|
|
|
case nir_cf_node_if:
|
|
|
|
|
read_if(ctx, list);
|
|
|
|
|
break;
|
|
|
|
|
case nir_cf_node_loop:
|
|
|
|
|
read_loop(ctx, list);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("bad cf type");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_cf_list(write_ctx *ctx, const struct exec_list *cf_list)
|
|
|
|
|
{
|
|
|
|
|
blob_write_uint32(ctx->blob, exec_list_length(cf_list));
|
|
|
|
|
foreach_list_typed(nir_cf_node, cf, node, cf_list) {
|
|
|
|
|
write_cf_node(ctx, cf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
read_cf_list(read_ctx *ctx, struct exec_list *cf_list)
|
|
|
|
|
{
|
|
|
|
|
uint32_t num_cf_nodes = blob_read_uint32(ctx->blob);
|
|
|
|
|
for (unsigned i = 0; i < num_cf_nodes; i++)
|
|
|
|
|
read_cf_node(ctx, cf_list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_function_impl(write_ctx *ctx, const nir_function_impl *fi)
|
|
|
|
|
{
|
2019-10-23 20:42:40 +02:00
|
|
|
blob_write_uint8(ctx->blob, fi->structured);
|
2021-09-24 18:12:24 +02:00
|
|
|
blob_write_uint8(ctx->blob, !!fi->preamble);
|
|
|
|
|
|
|
|
|
|
if (fi->preamble)
|
|
|
|
|
blob_write_uint32(ctx->blob, write_lookup_object(ctx, fi->preamble));
|
2019-10-23 20:42:40 +02:00
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
write_var_list(ctx, &fi->locals);
|
|
|
|
|
write_reg_list(ctx, &fi->registers);
|
|
|
|
|
blob_write_uint32(ctx->blob, fi->reg_alloc);
|
|
|
|
|
|
|
|
|
|
write_cf_list(ctx, &fi->body);
|
|
|
|
|
write_fixup_phis(ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_function_impl *
|
|
|
|
|
read_function_impl(read_ctx *ctx, nir_function *fxn)
|
|
|
|
|
{
|
|
|
|
|
nir_function_impl *fi = nir_function_impl_create_bare(ctx->nir);
|
|
|
|
|
fi->function = fxn;
|
|
|
|
|
|
2019-10-23 20:42:40 +02:00
|
|
|
fi->structured = blob_read_uint8(ctx->blob);
|
2021-09-24 18:12:24 +02:00
|
|
|
bool preamble = blob_read_uint8(ctx->blob);
|
|
|
|
|
|
|
|
|
|
if (preamble)
|
|
|
|
|
fi->preamble = read_object(ctx);
|
2019-10-23 20:42:40 +02:00
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
read_var_list(ctx, &fi->locals);
|
|
|
|
|
read_reg_list(ctx, &fi->registers);
|
|
|
|
|
fi->reg_alloc = blob_read_uint32(ctx->blob);
|
|
|
|
|
|
|
|
|
|
read_cf_list(ctx, &fi->body);
|
|
|
|
|
read_fixup_phis(ctx);
|
|
|
|
|
|
|
|
|
|
fi->valid_metadata = 0;
|
|
|
|
|
|
|
|
|
|
return fi;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_function(write_ctx *ctx, const nir_function *fxn)
|
|
|
|
|
{
|
2021-09-24 18:12:24 +02:00
|
|
|
uint32_t flags = 0;
|
|
|
|
|
if (fxn->is_entrypoint)
|
|
|
|
|
flags |= 0x1;
|
|
|
|
|
if (fxn->is_preamble)
|
2019-11-19 08:16:22 +10:00
|
|
|
flags |= 0x2;
|
2021-09-24 18:12:24 +02:00
|
|
|
if (fxn->name)
|
2019-11-19 08:19:34 +10:00
|
|
|
flags |= 0x4;
|
2021-09-24 18:12:24 +02:00
|
|
|
if (fxn->impl)
|
|
|
|
|
flags |= 0x8;
|
2019-11-19 08:16:22 +10:00
|
|
|
blob_write_uint32(ctx->blob, flags);
|
2017-09-12 23:17:51 -04:00
|
|
|
if (fxn->name)
|
|
|
|
|
blob_write_string(ctx->blob, fxn->name);
|
|
|
|
|
|
|
|
|
|
write_add_object(ctx, fxn);
|
|
|
|
|
|
|
|
|
|
blob_write_uint32(ctx->blob, fxn->num_params);
|
|
|
|
|
for (unsigned i = 0; i < fxn->num_params; i++) {
|
2018-03-22 16:41:18 -07:00
|
|
|
uint32_t val =
|
|
|
|
|
((uint32_t)fxn->params[i].num_components) |
|
|
|
|
|
((uint32_t)fxn->params[i].bit_size) << 8;
|
|
|
|
|
blob_write_uint32(ctx->blob, val);
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* At first glance, it looks like we should write the function_impl here.
|
|
|
|
|
* However, call instructions need to be able to reference at least the
|
|
|
|
|
* function and those will get processed as we write the function_impls.
|
|
|
|
|
* We stop here and write function_impls as a second pass.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
read_function(read_ctx *ctx)
|
|
|
|
|
{
|
2019-11-19 08:16:22 +10:00
|
|
|
uint32_t flags = blob_read_uint32(ctx->blob);
|
2021-09-24 18:12:24 +02:00
|
|
|
bool has_name = flags & 0x4;
|
2017-09-12 23:17:51 -04:00
|
|
|
char *name = has_name ? blob_read_string(ctx->blob) : NULL;
|
|
|
|
|
|
|
|
|
|
nir_function *fxn = nir_function_create(ctx->nir, name);
|
|
|
|
|
|
|
|
|
|
read_add_object(ctx, fxn);
|
|
|
|
|
|
|
|
|
|
fxn->num_params = blob_read_uint32(ctx->blob);
|
2018-03-22 16:41:18 -07:00
|
|
|
fxn->params = ralloc_array(fxn, nir_parameter, fxn->num_params);
|
2017-09-12 23:17:51 -04:00
|
|
|
for (unsigned i = 0; i < fxn->num_params; i++) {
|
2018-03-22 16:41:18 -07:00
|
|
|
uint32_t val = blob_read_uint32(ctx->blob);
|
|
|
|
|
fxn->params[i].num_components = val & 0xff;
|
|
|
|
|
fxn->params[i].bit_size = (val >> 8) & 0xff;
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
2018-09-06 11:12:24 -07:00
|
|
|
|
2019-11-19 08:16:22 +10:00
|
|
|
fxn->is_entrypoint = flags & 0x1;
|
2021-09-24 18:12:24 +02:00
|
|
|
fxn->is_preamble = flags & 0x2;
|
|
|
|
|
if (flags & 0x8)
|
2019-11-19 08:19:34 +10:00
|
|
|
fxn->impl = NIR_SERIALIZE_FUNC_HAS_IMPL;
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
2022-05-17 10:16:55 -05:00
|
|
|
static void
|
|
|
|
|
write_xfb_info(write_ctx *ctx, const nir_xfb_info *xfb)
|
|
|
|
|
{
|
|
|
|
|
if (xfb == NULL) {
|
|
|
|
|
blob_write_uint32(ctx->blob, 0);
|
|
|
|
|
} else {
|
|
|
|
|
size_t size = nir_xfb_info_size(xfb->output_count);
|
|
|
|
|
assert(size <= UINT32_MAX);
|
|
|
|
|
blob_write_uint32(ctx->blob, size);
|
|
|
|
|
blob_write_bytes(ctx->blob, xfb, size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static nir_xfb_info *
|
|
|
|
|
read_xfb_info(read_ctx *ctx)
|
|
|
|
|
{
|
|
|
|
|
uint32_t size = blob_read_uint32(ctx->blob);
|
|
|
|
|
if (size == 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
struct nir_xfb_info *xfb = ralloc_size(ctx->nir, size);
|
|
|
|
|
blob_copy_bytes(ctx->blob, (void *)xfb, size);
|
|
|
|
|
|
|
|
|
|
return xfb;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-04 18:09:26 -05:00
|
|
|
/**
|
|
|
|
|
* Serialize NIR into a binary blob.
|
|
|
|
|
*
|
|
|
|
|
* \param strip Don't serialize information only useful for debugging,
|
|
|
|
|
* such as variable names, making cache hits from similar
|
|
|
|
|
* shaders more likely.
|
|
|
|
|
*/
|
2017-09-12 23:17:51 -04:00
|
|
|
void
|
2019-10-09 13:27:07 -04:00
|
|
|
nir_serialize(struct blob *blob, const nir_shader *nir, bool strip)
|
2017-09-12 23:17:51 -04:00
|
|
|
{
|
2019-11-04 21:29:56 -05:00
|
|
|
write_ctx ctx = {0};
|
2019-01-11 11:50:53 -08:00
|
|
|
ctx.remap_table = _mesa_pointer_hash_table_create(NULL);
|
2017-09-12 23:17:51 -04:00
|
|
|
ctx.blob = blob;
|
|
|
|
|
ctx.nir = nir;
|
2019-11-04 18:09:26 -05:00
|
|
|
ctx.strip = strip;
|
2017-09-12 23:17:51 -04:00
|
|
|
util_dynarray_init(&ctx.phi_fixups, NULL);
|
|
|
|
|
|
2019-10-25 01:02:54 -04:00
|
|
|
size_t idx_size_offset = blob_reserve_uint32(blob);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
struct shader_info info = nir->info;
|
|
|
|
|
uint32_t strings = 0;
|
2019-11-04 18:09:26 -05:00
|
|
|
if (!strip && info.name)
|
2017-09-12 23:17:51 -04:00
|
|
|
strings |= 0x1;
|
2019-11-04 18:09:26 -05:00
|
|
|
if (!strip && info.label)
|
2017-09-12 23:17:51 -04:00
|
|
|
strings |= 0x2;
|
|
|
|
|
blob_write_uint32(blob, strings);
|
2019-11-04 18:09:26 -05:00
|
|
|
if (!strip && info.name)
|
2017-09-12 23:17:51 -04:00
|
|
|
blob_write_string(blob, info.name);
|
2019-11-04 18:09:26 -05:00
|
|
|
if (!strip && info.label)
|
2017-09-12 23:17:51 -04:00
|
|
|
blob_write_string(blob, info.label);
|
|
|
|
|
info.name = info.label = NULL;
|
|
|
|
|
blob_write_bytes(blob, (uint8_t *) &info, sizeof(info));
|
|
|
|
|
|
2020-07-20 16:30:37 -05:00
|
|
|
write_var_list(&ctx, &nir->variables);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
blob_write_uint32(blob, nir->num_inputs);
|
|
|
|
|
blob_write_uint32(blob, nir->num_uniforms);
|
|
|
|
|
blob_write_uint32(blob, nir->num_outputs);
|
2016-12-02 11:36:42 -08:00
|
|
|
blob_write_uint32(blob, nir->scratch_size);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
blob_write_uint32(blob, exec_list_length(&nir->functions));
|
|
|
|
|
nir_foreach_function(fxn, nir) {
|
|
|
|
|
write_function(&ctx, fxn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nir_foreach_function(fxn, nir) {
|
2019-11-19 08:19:34 +10:00
|
|
|
if (fxn->impl)
|
|
|
|
|
write_function_impl(&ctx, fxn->impl);
|
2017-09-12 23:17:51 -04:00
|
|
|
}
|
|
|
|
|
|
2018-06-28 19:16:19 -07:00
|
|
|
blob_write_uint32(blob, nir->constant_data_size);
|
|
|
|
|
if (nir->constant_data_size > 0)
|
|
|
|
|
blob_write_bytes(blob, nir->constant_data, nir->constant_data_size);
|
|
|
|
|
|
2022-05-17 10:16:55 -05:00
|
|
|
write_xfb_info(&ctx, nir->xfb_info);
|
|
|
|
|
|
2022-07-01 14:35:23 +02:00
|
|
|
if (nir->info.stage == MESA_SHADER_KERNEL) {
|
|
|
|
|
blob_write_uint32(blob, nir->printf_info_count);
|
|
|
|
|
for (int i = 0; i < nir->printf_info_count; i++) {
|
|
|
|
|
u_printf_info *info = &nir->printf_info[i];
|
|
|
|
|
blob_write_uint32(blob, info->num_args);
|
|
|
|
|
blob_write_uint32(blob, info->string_size);
|
|
|
|
|
blob_write_bytes(blob, info->arg_sizes,
|
|
|
|
|
info->num_args * sizeof(*info->arg_sizes));
|
|
|
|
|
/* we can't use blob_write_string, because it contains multiple NULL
|
|
|
|
|
* terminated strings */
|
|
|
|
|
blob_write_bytes(blob, info->strings,
|
|
|
|
|
info->string_size * sizeof(*info->strings));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-03 17:16:36 +01:00
|
|
|
blob_overwrite_uint32(blob, idx_size_offset, ctx.next_idx);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
_mesa_hash_table_destroy(ctx.remap_table, NULL);
|
|
|
|
|
util_dynarray_fini(&ctx.phi_fixups);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nir_shader *
|
|
|
|
|
nir_deserialize(void *mem_ctx,
|
|
|
|
|
const struct nir_shader_compiler_options *options,
|
|
|
|
|
struct blob_reader *blob)
|
|
|
|
|
{
|
2019-11-04 21:29:56 -05:00
|
|
|
read_ctx ctx = {0};
|
2017-09-12 23:17:51 -04:00
|
|
|
ctx.blob = blob;
|
|
|
|
|
list_inithead(&ctx.phi_srcs);
|
2019-10-25 01:02:54 -04:00
|
|
|
ctx.idx_table_len = blob_read_uint32(blob);
|
2017-09-12 23:17:51 -04:00
|
|
|
ctx.idx_table = calloc(ctx.idx_table_len, sizeof(uintptr_t));
|
|
|
|
|
|
|
|
|
|
uint32_t strings = blob_read_uint32(blob);
|
|
|
|
|
char *name = (strings & 0x1) ? blob_read_string(blob) : NULL;
|
|
|
|
|
char *label = (strings & 0x2) ? blob_read_string(blob) : NULL;
|
|
|
|
|
|
|
|
|
|
struct shader_info info;
|
|
|
|
|
blob_copy_bytes(blob, (uint8_t *) &info, sizeof(info));
|
|
|
|
|
|
|
|
|
|
ctx.nir = nir_shader_create(mem_ctx, info.stage, options, NULL);
|
|
|
|
|
|
|
|
|
|
info.name = name ? ralloc_strdup(ctx.nir, name) : NULL;
|
|
|
|
|
info.label = label ? ralloc_strdup(ctx.nir, label) : NULL;
|
|
|
|
|
|
|
|
|
|
ctx.nir->info = info;
|
|
|
|
|
|
2020-07-20 16:30:37 -05:00
|
|
|
read_var_list(&ctx, &ctx.nir->variables);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
ctx.nir->num_inputs = blob_read_uint32(blob);
|
|
|
|
|
ctx.nir->num_uniforms = blob_read_uint32(blob);
|
|
|
|
|
ctx.nir->num_outputs = blob_read_uint32(blob);
|
2016-12-02 11:36:42 -08:00
|
|
|
ctx.nir->scratch_size = blob_read_uint32(blob);
|
2017-09-12 23:17:51 -04:00
|
|
|
|
|
|
|
|
unsigned num_functions = blob_read_uint32(blob);
|
|
|
|
|
for (unsigned i = 0; i < num_functions; i++)
|
|
|
|
|
read_function(&ctx);
|
|
|
|
|
|
2019-11-19 08:19:34 +10:00
|
|
|
nir_foreach_function(fxn, ctx.nir) {
|
|
|
|
|
if (fxn->impl == NIR_SERIALIZE_FUNC_HAS_IMPL)
|
|
|
|
|
fxn->impl = read_function_impl(&ctx, fxn);
|
|
|
|
|
}
|
2017-09-12 23:17:51 -04:00
|
|
|
|
2018-06-28 19:16:19 -07:00
|
|
|
ctx.nir->constant_data_size = blob_read_uint32(blob);
|
|
|
|
|
if (ctx.nir->constant_data_size > 0) {
|
|
|
|
|
ctx.nir->constant_data =
|
|
|
|
|
ralloc_size(ctx.nir, ctx.nir->constant_data_size);
|
|
|
|
|
blob_copy_bytes(blob, ctx.nir->constant_data,
|
|
|
|
|
ctx.nir->constant_data_size);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-17 10:16:55 -05:00
|
|
|
ctx.nir->xfb_info = read_xfb_info(&ctx);
|
|
|
|
|
|
2022-07-01 14:35:23 +02:00
|
|
|
if (ctx.nir->info.stage == MESA_SHADER_KERNEL) {
|
|
|
|
|
ctx.nir->printf_info_count = blob_read_uint32(blob);
|
|
|
|
|
ctx.nir->printf_info =
|
|
|
|
|
ralloc_array(ctx.nir, u_printf_info, ctx.nir->printf_info_count);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < ctx.nir->printf_info_count; i++) {
|
|
|
|
|
u_printf_info *info = &ctx.nir->printf_info[i];
|
|
|
|
|
info->num_args = blob_read_uint32(blob);
|
|
|
|
|
info->string_size = blob_read_uint32(blob);
|
|
|
|
|
info->arg_sizes = ralloc_array(ctx.nir, unsigned, info->num_args);
|
|
|
|
|
blob_copy_bytes(blob, info->arg_sizes,
|
|
|
|
|
info->num_args * sizeof(*info->arg_sizes));
|
|
|
|
|
info->strings = ralloc_array(ctx.nir, char, info->string_size);
|
|
|
|
|
blob_copy_bytes(blob, info->strings,
|
|
|
|
|
info->string_size * sizeof(*info->strings));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
free(ctx.idx_table);
|
|
|
|
|
|
2021-07-13 16:31:52 -07:00
|
|
|
nir_validate_shader(ctx.nir, "after deserialize");
|
|
|
|
|
|
2017-09-12 23:17:51 -04:00
|
|
|
return ctx.nir;
|
|
|
|
|
}
|
2017-09-14 16:49:53 -07:00
|
|
|
|
2019-06-04 17:50:22 -05:00
|
|
|
void
|
|
|
|
|
nir_shader_serialize_deserialize(nir_shader *shader)
|
2017-09-14 16:49:53 -07:00
|
|
|
{
|
2019-06-04 17:50:22 -05:00
|
|
|
const struct nir_shader_compiler_options *options = shader->options;
|
2017-09-14 16:49:53 -07:00
|
|
|
|
|
|
|
|
struct blob writer;
|
|
|
|
|
blob_init(&writer);
|
2019-10-09 13:27:07 -04:00
|
|
|
nir_serialize(&writer, shader, false);
|
2019-06-04 17:50:22 -05:00
|
|
|
|
|
|
|
|
/* Delete all of dest's ralloc children but leave dest alone */
|
|
|
|
|
void *dead_ctx = ralloc_context(NULL);
|
|
|
|
|
ralloc_adopt(dead_ctx, shader);
|
|
|
|
|
ralloc_free(dead_ctx);
|
|
|
|
|
|
|
|
|
|
dead_ctx = ralloc_context(NULL);
|
2017-09-14 16:49:53 -07:00
|
|
|
|
|
|
|
|
struct blob_reader reader;
|
|
|
|
|
blob_reader_init(&reader, writer.data, writer.size);
|
2019-06-04 17:50:22 -05:00
|
|
|
nir_shader *copy = nir_deserialize(dead_ctx, options, &reader);
|
2017-09-14 16:49:53 -07:00
|
|
|
|
|
|
|
|
blob_finish(&writer);
|
|
|
|
|
|
2019-06-04 17:50:22 -05:00
|
|
|
nir_shader_replace(shader, copy);
|
|
|
|
|
ralloc_free(dead_ctx);
|
2017-09-14 16:49:53 -07:00
|
|
|
}
|