1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © Microsoft Corporation
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker *
11*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker * Software.
14*61046927SAndroid Build Coastguard Worker *
15*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker */
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker #include "dxil_container.h"
25*61046927SAndroid Build Coastguard Worker #include "dxil_module.h"
26*61046927SAndroid Build Coastguard Worker
27*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
28*61046927SAndroid Build Coastguard Worker
29*61046927SAndroid Build Coastguard Worker #include <assert.h>
30*61046927SAndroid Build Coastguard Worker
31*61046927SAndroid Build Coastguard Worker const uint32_t DXIL_DXBC = DXIL_FOURCC('D', 'X', 'B', 'C');
32*61046927SAndroid Build Coastguard Worker
33*61046927SAndroid Build Coastguard Worker void
dxil_container_init(struct dxil_container * c)34*61046927SAndroid Build Coastguard Worker dxil_container_init(struct dxil_container *c)
35*61046927SAndroid Build Coastguard Worker {
36*61046927SAndroid Build Coastguard Worker blob_init(&c->parts);
37*61046927SAndroid Build Coastguard Worker c->num_parts = 0;
38*61046927SAndroid Build Coastguard Worker }
39*61046927SAndroid Build Coastguard Worker
40*61046927SAndroid Build Coastguard Worker void
dxil_container_finish(struct dxil_container * c)41*61046927SAndroid Build Coastguard Worker dxil_container_finish(struct dxil_container *c)
42*61046927SAndroid Build Coastguard Worker {
43*61046927SAndroid Build Coastguard Worker blob_finish(&c->parts);
44*61046927SAndroid Build Coastguard Worker }
45*61046927SAndroid Build Coastguard Worker
46*61046927SAndroid Build Coastguard Worker static bool
add_part_header(struct dxil_container * c,enum dxil_part_fourcc fourcc,uint32_t part_size)47*61046927SAndroid Build Coastguard Worker add_part_header(struct dxil_container *c,
48*61046927SAndroid Build Coastguard Worker enum dxil_part_fourcc fourcc,
49*61046927SAndroid Build Coastguard Worker uint32_t part_size)
50*61046927SAndroid Build Coastguard Worker {
51*61046927SAndroid Build Coastguard Worker assert(c->parts.size < UINT_MAX);
52*61046927SAndroid Build Coastguard Worker unsigned offset = (unsigned)c->parts.size;
53*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, &fourcc, sizeof(fourcc)) ||
54*61046927SAndroid Build Coastguard Worker !blob_write_bytes(&c->parts, &part_size, sizeof(part_size)))
55*61046927SAndroid Build Coastguard Worker return false;
56*61046927SAndroid Build Coastguard Worker
57*61046927SAndroid Build Coastguard Worker assert(c->num_parts < DXIL_MAX_PARTS);
58*61046927SAndroid Build Coastguard Worker c->part_offsets[c->num_parts++] = offset;
59*61046927SAndroid Build Coastguard Worker return true;
60*61046927SAndroid Build Coastguard Worker }
61*61046927SAndroid Build Coastguard Worker
62*61046927SAndroid Build Coastguard Worker static bool
add_part(struct dxil_container * c,enum dxil_part_fourcc fourcc,const void * part_data,uint32_t part_size)63*61046927SAndroid Build Coastguard Worker add_part(struct dxil_container *c,
64*61046927SAndroid Build Coastguard Worker enum dxil_part_fourcc fourcc,
65*61046927SAndroid Build Coastguard Worker const void *part_data, uint32_t part_size)
66*61046927SAndroid Build Coastguard Worker {
67*61046927SAndroid Build Coastguard Worker return add_part_header(c, fourcc, part_size) &&
68*61046927SAndroid Build Coastguard Worker blob_write_bytes(&c->parts, part_data, part_size);
69*61046927SAndroid Build Coastguard Worker }
70*61046927SAndroid Build Coastguard Worker
71*61046927SAndroid Build Coastguard Worker bool
dxil_container_add_features(struct dxil_container * c,const struct dxil_features * features)72*61046927SAndroid Build Coastguard Worker dxil_container_add_features(struct dxil_container *c,
73*61046927SAndroid Build Coastguard Worker const struct dxil_features *features)
74*61046927SAndroid Build Coastguard Worker {
75*61046927SAndroid Build Coastguard Worker /* DXIL feature info is a bitfield packed into a uint64_t. */
76*61046927SAndroid Build Coastguard Worker static_assert(sizeof(struct dxil_features) <= sizeof(uint64_t),
77*61046927SAndroid Build Coastguard Worker "Expected dxil_features to fit into a uint64_t");
78*61046927SAndroid Build Coastguard Worker uint64_t bits = 0;
79*61046927SAndroid Build Coastguard Worker memcpy(&bits, features, sizeof(struct dxil_features));
80*61046927SAndroid Build Coastguard Worker return add_part(c, DXIL_SFI0, &bits, sizeof(uint64_t));
81*61046927SAndroid Build Coastguard Worker }
82*61046927SAndroid Build Coastguard Worker
83*61046927SAndroid Build Coastguard Worker typedef struct {
84*61046927SAndroid Build Coastguard Worker struct {
85*61046927SAndroid Build Coastguard Worker const char *name;
86*61046927SAndroid Build Coastguard Worker uint32_t offset;
87*61046927SAndroid Build Coastguard Worker } entries[DXIL_SHADER_MAX_IO_ROWS];
88*61046927SAndroid Build Coastguard Worker uint32_t num_entries;
89*61046927SAndroid Build Coastguard Worker } name_offset_cache_t;
90*61046927SAndroid Build Coastguard Worker
91*61046927SAndroid Build Coastguard Worker static uint32_t
get_semantic_name_offset(name_offset_cache_t * cache,const char * name,struct _mesa_string_buffer * buf,uint32_t buf_offset,bool validator_7)92*61046927SAndroid Build Coastguard Worker get_semantic_name_offset(name_offset_cache_t *cache, const char *name,
93*61046927SAndroid Build Coastguard Worker struct _mesa_string_buffer *buf, uint32_t buf_offset,
94*61046927SAndroid Build Coastguard Worker bool validator_7)
95*61046927SAndroid Build Coastguard Worker {
96*61046927SAndroid Build Coastguard Worker uint32_t offset = buf->length + buf_offset;
97*61046927SAndroid Build Coastguard Worker
98*61046927SAndroid Build Coastguard Worker /* DXC doesn't de-duplicate arbitrary semantic names until validator 1.7, only SVs. */
99*61046927SAndroid Build Coastguard Worker if (validator_7 || strncmp(name, "SV_", 3) == 0) {
100*61046927SAndroid Build Coastguard Worker /* consider replacing this with a binary search using rb_tree */
101*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < cache->num_entries; ++i) {
102*61046927SAndroid Build Coastguard Worker if (!strcmp(name, cache->entries[i].name))
103*61046927SAndroid Build Coastguard Worker return cache->entries[i].offset;
104*61046927SAndroid Build Coastguard Worker }
105*61046927SAndroid Build Coastguard Worker
106*61046927SAndroid Build Coastguard Worker cache->entries[cache->num_entries].name = name;
107*61046927SAndroid Build Coastguard Worker cache->entries[cache->num_entries].offset = offset;
108*61046927SAndroid Build Coastguard Worker ++cache->num_entries;
109*61046927SAndroid Build Coastguard Worker }
110*61046927SAndroid Build Coastguard Worker _mesa_string_buffer_append_len(buf, name, strlen(name) + 1);
111*61046927SAndroid Build Coastguard Worker
112*61046927SAndroid Build Coastguard Worker return offset;
113*61046927SAndroid Build Coastguard Worker }
114*61046927SAndroid Build Coastguard Worker
115*61046927SAndroid Build Coastguard Worker static uint32_t
collect_semantic_names(unsigned num_records,struct dxil_signature_record * io_data,struct _mesa_string_buffer * buf,uint32_t buf_offset,bool validator_7)116*61046927SAndroid Build Coastguard Worker collect_semantic_names(unsigned num_records,
117*61046927SAndroid Build Coastguard Worker struct dxil_signature_record *io_data,
118*61046927SAndroid Build Coastguard Worker struct _mesa_string_buffer *buf,
119*61046927SAndroid Build Coastguard Worker uint32_t buf_offset,
120*61046927SAndroid Build Coastguard Worker bool validator_7)
121*61046927SAndroid Build Coastguard Worker {
122*61046927SAndroid Build Coastguard Worker name_offset_cache_t cache;
123*61046927SAndroid Build Coastguard Worker cache.num_entries = 0;
124*61046927SAndroid Build Coastguard Worker
125*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < num_records; ++i) {
126*61046927SAndroid Build Coastguard Worker struct dxil_signature_record *io = &io_data[i];
127*61046927SAndroid Build Coastguard Worker uint32_t offset = get_semantic_name_offset(&cache, io->name, buf, buf_offset, validator_7);
128*61046927SAndroid Build Coastguard Worker for (unsigned j = 0; j < io->num_elements; ++j)
129*61046927SAndroid Build Coastguard Worker io->elements[j].semantic_name_offset = offset;
130*61046927SAndroid Build Coastguard Worker }
131*61046927SAndroid Build Coastguard Worker if (validator_7 && buf->length % sizeof(uint32_t) != 0) {
132*61046927SAndroid Build Coastguard Worker unsigned padding_to_add = sizeof(uint32_t) - (buf->length % sizeof(uint32_t));
133*61046927SAndroid Build Coastguard Worker char padding[sizeof(uint32_t)] = { 0 };
134*61046927SAndroid Build Coastguard Worker _mesa_string_buffer_append_len(buf, padding, padding_to_add);
135*61046927SAndroid Build Coastguard Worker }
136*61046927SAndroid Build Coastguard Worker return buf_offset + buf->length;
137*61046927SAndroid Build Coastguard Worker }
138*61046927SAndroid Build Coastguard Worker
139*61046927SAndroid Build Coastguard Worker bool
dxil_container_add_io_signature(struct dxil_container * c,enum dxil_part_fourcc part,unsigned num_records,struct dxil_signature_record * io_data,bool validator_7)140*61046927SAndroid Build Coastguard Worker dxil_container_add_io_signature(struct dxil_container *c,
141*61046927SAndroid Build Coastguard Worker enum dxil_part_fourcc part,
142*61046927SAndroid Build Coastguard Worker unsigned num_records,
143*61046927SAndroid Build Coastguard Worker struct dxil_signature_record *io_data,
144*61046927SAndroid Build Coastguard Worker bool validator_7)
145*61046927SAndroid Build Coastguard Worker {
146*61046927SAndroid Build Coastguard Worker struct {
147*61046927SAndroid Build Coastguard Worker uint32_t param_count;
148*61046927SAndroid Build Coastguard Worker uint32_t param_offset;
149*61046927SAndroid Build Coastguard Worker } header;
150*61046927SAndroid Build Coastguard Worker header.param_count = 0;
151*61046927SAndroid Build Coastguard Worker uint32_t fixed_size = sizeof(header);
152*61046927SAndroid Build Coastguard Worker header.param_offset = fixed_size;
153*61046927SAndroid Build Coastguard Worker
154*61046927SAndroid Build Coastguard Worker bool retval = true;
155*61046927SAndroid Build Coastguard Worker
156*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < num_records; ++i) {
157*61046927SAndroid Build Coastguard Worker /* TODO:
158*61046927SAndroid Build Coastguard Worker * - Here we need to check whether the value is actually part of the
159*61046927SAndroid Build Coastguard Worker * signature */
160*61046927SAndroid Build Coastguard Worker fixed_size += sizeof(struct dxil_signature_element) * io_data[i].num_elements;
161*61046927SAndroid Build Coastguard Worker header.param_count += io_data[i].num_elements;
162*61046927SAndroid Build Coastguard Worker }
163*61046927SAndroid Build Coastguard Worker
164*61046927SAndroid Build Coastguard Worker struct _mesa_string_buffer *names =
165*61046927SAndroid Build Coastguard Worker _mesa_string_buffer_create(NULL, 1024);
166*61046927SAndroid Build Coastguard Worker
167*61046927SAndroid Build Coastguard Worker uint32_t last_offset = collect_semantic_names(num_records, io_data,
168*61046927SAndroid Build Coastguard Worker names, fixed_size,
169*61046927SAndroid Build Coastguard Worker validator_7);
170*61046927SAndroid Build Coastguard Worker
171*61046927SAndroid Build Coastguard Worker
172*61046927SAndroid Build Coastguard Worker if (!add_part_header(c, part, last_offset) ||
173*61046927SAndroid Build Coastguard Worker !blob_write_bytes(&c->parts, &header, sizeof(header))) {
174*61046927SAndroid Build Coastguard Worker retval = false;
175*61046927SAndroid Build Coastguard Worker goto cleanup;
176*61046927SAndroid Build Coastguard Worker }
177*61046927SAndroid Build Coastguard Worker
178*61046927SAndroid Build Coastguard Worker /* write all parts */
179*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < num_records; ++i)
180*61046927SAndroid Build Coastguard Worker for (unsigned j = 0; j < io_data[i].num_elements; ++j) {
181*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, &io_data[i].elements[j],
182*61046927SAndroid Build Coastguard Worker sizeof(io_data[i].elements[j]))) {
183*61046927SAndroid Build Coastguard Worker retval = false;
184*61046927SAndroid Build Coastguard Worker goto cleanup;
185*61046927SAndroid Build Coastguard Worker }
186*61046927SAndroid Build Coastguard Worker }
187*61046927SAndroid Build Coastguard Worker
188*61046927SAndroid Build Coastguard Worker /* write all names */
189*61046927SAndroid Build Coastguard Worker
190*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, names->buf, names->length))
191*61046927SAndroid Build Coastguard Worker retval = false;
192*61046927SAndroid Build Coastguard Worker
193*61046927SAndroid Build Coastguard Worker cleanup:
194*61046927SAndroid Build Coastguard Worker _mesa_string_buffer_destroy(names);
195*61046927SAndroid Build Coastguard Worker return retval;
196*61046927SAndroid Build Coastguard Worker }
197*61046927SAndroid Build Coastguard Worker
198*61046927SAndroid Build Coastguard Worker bool
dxil_container_add_state_validation(struct dxil_container * c,const struct dxil_module * m,struct dxil_validation_state * state)199*61046927SAndroid Build Coastguard Worker dxil_container_add_state_validation(struct dxil_container *c,
200*61046927SAndroid Build Coastguard Worker const struct dxil_module *m,
201*61046927SAndroid Build Coastguard Worker struct dxil_validation_state *state)
202*61046927SAndroid Build Coastguard Worker {
203*61046927SAndroid Build Coastguard Worker uint32_t psv_size = m->minor_validator >= 6 ?
204*61046927SAndroid Build Coastguard Worker sizeof(struct dxil_psv_runtime_info_2) :
205*61046927SAndroid Build Coastguard Worker sizeof(struct dxil_psv_runtime_info_1);
206*61046927SAndroid Build Coastguard Worker uint32_t resource_bind_info_size = m->minor_validator >= 6 ?
207*61046927SAndroid Build Coastguard Worker sizeof(struct dxil_resource_v1) : sizeof(struct dxil_resource_v0);
208*61046927SAndroid Build Coastguard Worker uint32_t dxil_pvs_sig_size = sizeof(struct dxil_psv_signature_element);
209*61046927SAndroid Build Coastguard Worker uint32_t resource_count = state->num_resources;
210*61046927SAndroid Build Coastguard Worker
211*61046927SAndroid Build Coastguard Worker uint32_t size = psv_size + 2 * sizeof(uint32_t);
212*61046927SAndroid Build Coastguard Worker if (resource_count > 0) {
213*61046927SAndroid Build Coastguard Worker size += sizeof (uint32_t) +
214*61046927SAndroid Build Coastguard Worker resource_bind_info_size * resource_count;
215*61046927SAndroid Build Coastguard Worker }
216*61046927SAndroid Build Coastguard Worker uint32_t string_table_size = (m->sem_string_table->length + 3) & ~3u;
217*61046927SAndroid Build Coastguard Worker size += sizeof(uint32_t) + string_table_size;
218*61046927SAndroid Build Coastguard Worker
219*61046927SAndroid Build Coastguard Worker size += sizeof(uint32_t) + m->sem_index_table.size * sizeof(uint32_t);
220*61046927SAndroid Build Coastguard Worker
221*61046927SAndroid Build Coastguard Worker if (m->num_sig_inputs || m->num_sig_outputs || m->num_sig_patch_consts) {
222*61046927SAndroid Build Coastguard Worker size += sizeof(uint32_t);
223*61046927SAndroid Build Coastguard Worker }
224*61046927SAndroid Build Coastguard Worker
225*61046927SAndroid Build Coastguard Worker size += dxil_pvs_sig_size * m->num_sig_inputs;
226*61046927SAndroid Build Coastguard Worker size += dxil_pvs_sig_size * m->num_sig_outputs;
227*61046927SAndroid Build Coastguard Worker size += dxil_pvs_sig_size * m->num_sig_patch_consts;
228*61046927SAndroid Build Coastguard Worker
229*61046927SAndroid Build Coastguard Worker state->state.psv1.sig_input_vectors = (uint8_t)m->num_psv_inputs;
230*61046927SAndroid Build Coastguard Worker
231*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; ++i)
232*61046927SAndroid Build Coastguard Worker state->state.psv1.sig_output_vectors[i] = (uint8_t)m->num_psv_outputs[i];
233*61046927SAndroid Build Coastguard Worker
234*61046927SAndroid Build Coastguard Worker if (state->state.psv1.uses_view_id) {
235*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; ++i)
236*61046927SAndroid Build Coastguard Worker size += m->dependency_table_dwords_per_input[i] * sizeof(uint32_t);
237*61046927SAndroid Build Coastguard Worker }
238*61046927SAndroid Build Coastguard Worker
239*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; ++i)
240*61046927SAndroid Build Coastguard Worker size += m->io_dependency_table_size[i] * sizeof(uint32_t);
241*61046927SAndroid Build Coastguard Worker
242*61046927SAndroid Build Coastguard Worker if (!add_part_header(c, DXIL_PSV0, size))
243*61046927SAndroid Build Coastguard Worker return false;
244*61046927SAndroid Build Coastguard Worker
245*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, &psv_size, sizeof(psv_size)))
246*61046927SAndroid Build Coastguard Worker return false;
247*61046927SAndroid Build Coastguard Worker
248*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, &state->state, psv_size))
249*61046927SAndroid Build Coastguard Worker return false;
250*61046927SAndroid Build Coastguard Worker
251*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, &resource_count, sizeof(resource_count)))
252*61046927SAndroid Build Coastguard Worker return false;
253*61046927SAndroid Build Coastguard Worker
254*61046927SAndroid Build Coastguard Worker if (resource_count > 0) {
255*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, &resource_bind_info_size, sizeof(resource_bind_info_size)) ||
256*61046927SAndroid Build Coastguard Worker !blob_write_bytes(&c->parts, state->resources.v0, resource_bind_info_size * state->num_resources))
257*61046927SAndroid Build Coastguard Worker return false;
258*61046927SAndroid Build Coastguard Worker }
259*61046927SAndroid Build Coastguard Worker
260*61046927SAndroid Build Coastguard Worker
261*61046927SAndroid Build Coastguard Worker uint32_t fill = 0;
262*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, &string_table_size, sizeof(string_table_size)) ||
263*61046927SAndroid Build Coastguard Worker !blob_write_bytes(&c->parts, m->sem_string_table->buf, m->sem_string_table->length) ||
264*61046927SAndroid Build Coastguard Worker !blob_write_bytes(&c->parts, &fill, string_table_size - m->sem_string_table->length))
265*61046927SAndroid Build Coastguard Worker return false;
266*61046927SAndroid Build Coastguard Worker
267*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, &m->sem_index_table.size, sizeof(uint32_t)))
268*61046927SAndroid Build Coastguard Worker return false;
269*61046927SAndroid Build Coastguard Worker
270*61046927SAndroid Build Coastguard Worker if (m->sem_index_table.size > 0) {
271*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, m->sem_index_table.data,
272*61046927SAndroid Build Coastguard Worker m->sem_index_table.size * sizeof(uint32_t)))
273*61046927SAndroid Build Coastguard Worker return false;
274*61046927SAndroid Build Coastguard Worker }
275*61046927SAndroid Build Coastguard Worker
276*61046927SAndroid Build Coastguard Worker if (m->num_sig_inputs || m->num_sig_outputs || m->num_sig_patch_consts) {
277*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, &dxil_pvs_sig_size, sizeof(dxil_pvs_sig_size)))
278*61046927SAndroid Build Coastguard Worker return false;
279*61046927SAndroid Build Coastguard Worker
280*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, &m->psv_inputs, dxil_pvs_sig_size * m->num_sig_inputs))
281*61046927SAndroid Build Coastguard Worker return false;
282*61046927SAndroid Build Coastguard Worker
283*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, &m->psv_outputs, dxil_pvs_sig_size * m->num_sig_outputs))
284*61046927SAndroid Build Coastguard Worker return false;
285*61046927SAndroid Build Coastguard Worker
286*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, &m->psv_patch_consts, dxil_pvs_sig_size * m->num_sig_patch_consts))
287*61046927SAndroid Build Coastguard Worker return false;
288*61046927SAndroid Build Coastguard Worker }
289*61046927SAndroid Build Coastguard Worker
290*61046927SAndroid Build Coastguard Worker /* This was a bug in the DXIL validation logic prior to 1.8. When replicating these I/O dependency
291*61046927SAndroid Build Coastguard Worker * tables from the metadata to the container, the pointer is advanced for each stream,
292*61046927SAndroid Build Coastguard Worker * and then copied for all streams... meaning that the first streams have zero data, since the
293*61046927SAndroid Build Coastguard Worker * pointer is advanced and then never written to. The last stream (that has data) then has the
294*61046927SAndroid Build Coastguard Worker * data from all streams written to it. However, if any stream before the last one has a larger
295*61046927SAndroid Build Coastguard Worker * size, this will cause corruption, since it's writing to the smaller space that was allocated
296*61046927SAndroid Build Coastguard Worker * for the last stream. We assume that never happens, and just zero all earlier streams. */
297*61046927SAndroid Build Coastguard Worker if (m->shader_kind == DXIL_GEOMETRY_SHADER && m->minor_validator < 8) {
298*61046927SAndroid Build Coastguard Worker bool zero_view_id_deps = false, zero_io_deps = false;
299*61046927SAndroid Build Coastguard Worker for (int i = 3; i >= 0; --i) {
300*61046927SAndroid Build Coastguard Worker if (state->state.psv1.uses_view_id && m->dependency_table_dwords_per_input[i]) {
301*61046927SAndroid Build Coastguard Worker if (zero_view_id_deps)
302*61046927SAndroid Build Coastguard Worker memset(m->viewid_dependency_table[i], 0, sizeof(uint32_t) * m->dependency_table_dwords_per_input[i]);
303*61046927SAndroid Build Coastguard Worker zero_view_id_deps = true;
304*61046927SAndroid Build Coastguard Worker }
305*61046927SAndroid Build Coastguard Worker if (m->io_dependency_table_size[i]) {
306*61046927SAndroid Build Coastguard Worker if (zero_io_deps)
307*61046927SAndroid Build Coastguard Worker memset(m->io_dependency_table[i], 0, sizeof(uint32_t) * m->io_dependency_table_size[i]);
308*61046927SAndroid Build Coastguard Worker zero_io_deps = true;
309*61046927SAndroid Build Coastguard Worker }
310*61046927SAndroid Build Coastguard Worker }
311*61046927SAndroid Build Coastguard Worker }
312*61046927SAndroid Build Coastguard Worker
313*61046927SAndroid Build Coastguard Worker if (state->state.psv1.uses_view_id) {
314*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; ++i)
315*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, m->viewid_dependency_table[i],
316*61046927SAndroid Build Coastguard Worker sizeof(uint32_t) * m->dependency_table_dwords_per_input[i]))
317*61046927SAndroid Build Coastguard Worker return false;
318*61046927SAndroid Build Coastguard Worker }
319*61046927SAndroid Build Coastguard Worker
320*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; ++i)
321*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(&c->parts, m->io_dependency_table[i],
322*61046927SAndroid Build Coastguard Worker sizeof(uint32_t) * m->io_dependency_table_size[i]))
323*61046927SAndroid Build Coastguard Worker return false;
324*61046927SAndroid Build Coastguard Worker
325*61046927SAndroid Build Coastguard Worker return true;
326*61046927SAndroid Build Coastguard Worker }
327*61046927SAndroid Build Coastguard Worker
328*61046927SAndroid Build Coastguard Worker bool
dxil_container_add_module(struct dxil_container * c,const struct dxil_module * m)329*61046927SAndroid Build Coastguard Worker dxil_container_add_module(struct dxil_container *c,
330*61046927SAndroid Build Coastguard Worker const struct dxil_module *m)
331*61046927SAndroid Build Coastguard Worker {
332*61046927SAndroid Build Coastguard Worker assert(m->buf.buf_bits == 0); // make sure the module is fully flushed
333*61046927SAndroid Build Coastguard Worker uint32_t version = (m->shader_kind << 16) |
334*61046927SAndroid Build Coastguard Worker (m->major_version << 4) |
335*61046927SAndroid Build Coastguard Worker m->minor_version;
336*61046927SAndroid Build Coastguard Worker uint32_t size = 6 * sizeof(uint32_t) + m->buf.blob.size;
337*61046927SAndroid Build Coastguard Worker assert(size % sizeof(uint32_t) == 0);
338*61046927SAndroid Build Coastguard Worker uint32_t uint32_size = size / sizeof(uint32_t);
339*61046927SAndroid Build Coastguard Worker uint32_t magic = 0x4C495844;
340*61046927SAndroid Build Coastguard Worker uint32_t dxil_version = 1 << 8; // I have no idea...
341*61046927SAndroid Build Coastguard Worker uint32_t bitcode_offset = 16;
342*61046927SAndroid Build Coastguard Worker uint32_t bitcode_size = m->buf.blob.size;
343*61046927SAndroid Build Coastguard Worker
344*61046927SAndroid Build Coastguard Worker return add_part_header(c, DXIL_DXIL, size) &&
345*61046927SAndroid Build Coastguard Worker blob_write_bytes(&c->parts, &version, sizeof(version)) &&
346*61046927SAndroid Build Coastguard Worker blob_write_bytes(&c->parts, &uint32_size, sizeof(uint32_size)) &&
347*61046927SAndroid Build Coastguard Worker blob_write_bytes(&c->parts, &magic, sizeof(magic)) &&
348*61046927SAndroid Build Coastguard Worker blob_write_bytes(&c->parts, &dxil_version, sizeof(dxil_version)) &&
349*61046927SAndroid Build Coastguard Worker blob_write_bytes(&c->parts, &bitcode_offset, sizeof(bitcode_offset)) &&
350*61046927SAndroid Build Coastguard Worker blob_write_bytes(&c->parts, &bitcode_size, sizeof(bitcode_size)) &&
351*61046927SAndroid Build Coastguard Worker blob_write_bytes(&c->parts, m->buf.blob.data, m->buf.blob.size);
352*61046927SAndroid Build Coastguard Worker }
353*61046927SAndroid Build Coastguard Worker
354*61046927SAndroid Build Coastguard Worker bool
dxil_container_write(struct dxil_container * c,struct blob * blob)355*61046927SAndroid Build Coastguard Worker dxil_container_write(struct dxil_container *c, struct blob *blob)
356*61046927SAndroid Build Coastguard Worker {
357*61046927SAndroid Build Coastguard Worker assert(blob->size == 0);
358*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(blob, &DXIL_DXBC, sizeof(DXIL_DXBC)))
359*61046927SAndroid Build Coastguard Worker return false;
360*61046927SAndroid Build Coastguard Worker
361*61046927SAndroid Build Coastguard Worker const uint8_t unsigned_digest[16] = { 0 }; // null-digest means unsigned
362*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(blob, unsigned_digest, sizeof(unsigned_digest)))
363*61046927SAndroid Build Coastguard Worker return false;
364*61046927SAndroid Build Coastguard Worker
365*61046927SAndroid Build Coastguard Worker uint16_t major_version = 1;
366*61046927SAndroid Build Coastguard Worker uint16_t minor_version = 0;
367*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(blob, &major_version, sizeof(major_version)) ||
368*61046927SAndroid Build Coastguard Worker !blob_write_bytes(blob, &minor_version, sizeof(minor_version)))
369*61046927SAndroid Build Coastguard Worker return false;
370*61046927SAndroid Build Coastguard Worker
371*61046927SAndroid Build Coastguard Worker size_t header_size = 32 + 4 * c->num_parts;
372*61046927SAndroid Build Coastguard Worker size_t size = header_size + c->parts.size;
373*61046927SAndroid Build Coastguard Worker assert(size <= UINT32_MAX);
374*61046927SAndroid Build Coastguard Worker uint32_t container_size = (uint32_t)size;
375*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(blob, &container_size, sizeof(container_size)))
376*61046927SAndroid Build Coastguard Worker return false;
377*61046927SAndroid Build Coastguard Worker
378*61046927SAndroid Build Coastguard Worker uint32_t part_offsets[DXIL_MAX_PARTS];
379*61046927SAndroid Build Coastguard Worker for (int i = 0; i < c->num_parts; ++i) {
380*61046927SAndroid Build Coastguard Worker size_t offset = header_size + c->part_offsets[i];
381*61046927SAndroid Build Coastguard Worker assert(offset <= UINT32_MAX);
382*61046927SAndroid Build Coastguard Worker part_offsets[i] = (uint32_t)offset;
383*61046927SAndroid Build Coastguard Worker }
384*61046927SAndroid Build Coastguard Worker
385*61046927SAndroid Build Coastguard Worker if (!blob_write_bytes(blob, &c->num_parts, sizeof(c->num_parts)) ||
386*61046927SAndroid Build Coastguard Worker !blob_write_bytes(blob, part_offsets, sizeof(uint32_t) * c->num_parts) ||
387*61046927SAndroid Build Coastguard Worker !blob_write_bytes(blob, c->parts.data, c->parts.size))
388*61046927SAndroid Build Coastguard Worker return false;
389*61046927SAndroid Build Coastguard Worker
390*61046927SAndroid Build Coastguard Worker return true;
391*61046927SAndroid Build Coastguard Worker }
392