summaryrefslogtreecommitdiff
path: root/lib/mesa/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mesa/src')
-rw-r--r--lib/mesa/src/compiler/blob.c384
-rw-r--r--lib/mesa/src/compiler/blob.h352
-rw-r--r--lib/mesa/src/compiler/glsl/ir_expression_flattening.cpp4
-rw-r--r--lib/mesa/src/compiler/glsl/loop_analysis.cpp226
-rw-r--r--lib/mesa/src/compiler/glsl/loop_unroll.cpp234
-rw-r--r--lib/mesa/src/compiler/glsl/lower_discard.cpp4
-rw-r--r--lib/mesa/src/compiler/glsl/lower_mat_op_to_vec.cpp8
-rw-r--r--lib/mesa/src/compiler/glsl/lower_shared_reference.cpp21
-rw-r--r--lib/mesa/src/compiler/glsl/lower_tess_level.cpp3
-rw-r--r--lib/mesa/src/compiler/glsl/lower_variable_index_to_cond_assign.cpp256
-rw-r--r--lib/mesa/src/compiler/glsl/lower_vec_index_to_swizzle.cpp7
-rw-r--r--lib/mesa/src/compiler/glsl/lower_vector.cpp4
-rw-r--r--lib/mesa/src/compiler/glsl/lower_vector_derefs.cpp3
-rw-r--r--lib/mesa/src/compiler/glsl/lower_vector_insert.cpp3
-rw-r--r--lib/mesa/src/compiler/glsl/opt_constant_folding.cpp7
-rw-r--r--lib/mesa/src/compiler/glsl/opt_constant_variable.cpp2
-rw-r--r--lib/mesa/src/compiler/glsl/opt_if_simplification.cpp3
-rw-r--r--lib/mesa/src/compiler/glsl/tests/array_refcount_test.cpp2
-rw-r--r--lib/mesa/src/compiler/glsl/tests/meson.build76
-rw-r--r--lib/mesa/src/compiler/nir/nir_linking_helpers.c152
-rw-r--r--lib/mesa/src/compiler/nir/nir_lower_alpha_test.c111
-rw-r--r--lib/mesa/src/compiler/nir/nir_lower_samplers_as_deref.c243
-rw-r--r--lib/mesa/src/compiler/nir/nir_lower_uniforms_to_ubo.c97
-rw-r--r--lib/mesa/src/compiler/nir/nir_lower_vec_to_movs.c7
-rw-r--r--lib/mesa/src/mapi/glapi/gen/ARB_clear_buffer_object.xml4
-rw-r--r--lib/mesa/src/mapi/glapi/gen/ARB_get_program_binary.xml2
-rw-r--r--lib/mesa/src/mapi/glapi/gen/ARB_robustness.xml2
-rw-r--r--lib/mesa/src/mapi/glapi/gen/ARB_tessellation_shader.xml2
-rw-r--r--lib/mesa/src/mapi/glapi/gen/ARB_texture_multisample.xml2
-rw-r--r--lib/mesa/src/mapi/glapi/gen/ARB_texture_storage.xml6
-rw-r--r--lib/mesa/src/mapi/glapi/gen/ARB_texture_view.xml2
-rw-r--r--lib/mesa/src/mapi/glapi/gen/EXT_external_objects.xml234
-rw-r--r--lib/mesa/src/mapi/glapi/gen/EXT_external_objects_fd.xml28
-rw-r--r--lib/mesa/src/mapi/glapi/gen/GL4x.xml14
-rw-r--r--lib/mesa/src/mapi/glapi/gen/MESA_tile_raster_order.xml12
-rw-r--r--lib/mesa/src/mapi/glapi/glapi.h3
-rw-r--r--lib/mesa/src/mapi/glapi/tests/check_table.cpp4
-rw-r--r--lib/mesa/src/mapi/shared-glapi/tests/check_table.cpp2
-rw-r--r--lib/mesa/src/mesa/drivers/dri/i915/intel_screen.h2
-rw-r--r--lib/mesa/src/mesa/drivers/dri/i965/brw_pipe_control.h89
-rw-r--r--lib/mesa/src/mesa/drivers/dri/i965/hsw_sol.c21
-rw-r--r--lib/mesa/src/mesa/drivers/dri/i965/intel_tex.h25
-rw-r--r--lib/mesa/src/mesa/drivers/dri/nouveau/nouveau_context.h4
-rw-r--r--lib/mesa/src/mesa/drivers/dri/nouveau/nv10_context.c6
-rw-r--r--lib/mesa/src/mesa/drivers/dri/nouveau/nv20_context.c6
-rw-r--r--lib/mesa/src/mesa/drivers/dri/r200/Makefile.am2
-rw-r--r--lib/mesa/src/mesa/drivers/dri/r200/radeon_screen.h2
-rw-r--r--lib/mesa/src/mesa/drivers/dri/r200/radeon_texture.c2
-rw-r--r--lib/mesa/src/mesa/drivers/dri/radeon/Makefile.am2
-rw-r--r--lib/mesa/src/mesa/drivers/dri/radeon/radeon_context.h1
-rw-r--r--lib/mesa/src/mesa/drivers/dri/radeon/radeon_screen.h2
-rw-r--r--lib/mesa/src/mesa/drivers/dri/radeon/radeon_state_init.c2
-rw-r--r--lib/mesa/src/mesa/drivers/dri/radeon/radeon_tcl.c4
-rw-r--r--lib/mesa/src/mesa/drivers/dri/radeon/radeon_texture.c2
-rw-r--r--lib/mesa/src/mesa/drivers/dri/swrast/Makefile.am2
-rw-r--r--lib/mesa/src/mesa/swrast/s_texfetch.c1
56 files changed, 2381 insertions, 320 deletions
diff --git a/lib/mesa/src/compiler/blob.c b/lib/mesa/src/compiler/blob.c
new file mode 100644
index 000000000..8dd254fef
--- /dev/null
+++ b/lib/mesa/src/compiler/blob.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * 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 <string.h>
+
+#include "main/macros.h"
+#include "blob.h"
+
+#ifdef HAVE_VALGRIND
+#include <valgrind.h>
+#include <memcheck.h>
+#define VG(x) x
+#else
+#define VG(x)
+#endif
+
+#define BLOB_INITIAL_SIZE 4096
+
+/* Ensure that \blob will be able to fit an additional object of size
+ * \additional. The growing (if any) will occur by doubling the existing
+ * allocation.
+ */
+static bool
+grow_to_fit(struct blob *blob, size_t additional)
+{
+ size_t to_allocate;
+ uint8_t *new_data;
+
+ if (blob->out_of_memory)
+ return false;
+
+ if (blob->size + additional <= blob->allocated)
+ return true;
+
+ if (blob->fixed_allocation) {
+ blob->out_of_memory = true;
+ return false;
+ }
+
+ if (blob->allocated == 0)
+ to_allocate = BLOB_INITIAL_SIZE;
+ else
+ to_allocate = blob->allocated * 2;
+
+ to_allocate = MAX2(to_allocate, blob->allocated + additional);
+
+ new_data = realloc(blob->data, to_allocate);
+ if (new_data == NULL) {
+ blob->out_of_memory = true;
+ return false;
+ }
+
+ blob->data = new_data;
+ blob->allocated = to_allocate;
+
+ return true;
+}
+
+/* Align the blob->size so that reading or writing a value at (blob->data +
+ * blob->size) will result in an access aligned to a granularity of \alignment
+ * bytes.
+ *
+ * \return True unless allocation fails
+ */
+static bool
+align_blob(struct blob *blob, size_t alignment)
+{
+ const size_t new_size = ALIGN(blob->size, alignment);
+
+ if (blob->size < new_size) {
+ if (!grow_to_fit(blob, new_size - blob->size))
+ return false;
+
+ if (blob->data)
+ memset(blob->data + blob->size, 0, new_size - blob->size);
+ blob->size = new_size;
+ }
+
+ return true;
+}
+
+static void
+align_blob_reader(struct blob_reader *blob, size_t alignment)
+{
+ blob->current = blob->data + ALIGN(blob->current - blob->data, alignment);
+}
+
+void
+blob_init(struct blob *blob)
+{
+ blob->data = NULL;
+ blob->allocated = 0;
+ blob->size = 0;
+ blob->fixed_allocation = false;
+ blob->out_of_memory = false;
+}
+
+void
+blob_init_fixed(struct blob *blob, void *data, size_t size)
+{
+ blob->data = data;
+ blob->allocated = size;
+ blob->size = 0;
+ blob->fixed_allocation = true;
+ blob->out_of_memory = false;
+}
+
+bool
+blob_overwrite_bytes(struct blob *blob,
+ size_t offset,
+ const void *bytes,
+ size_t to_write)
+{
+ /* Detect an attempt to overwrite data out of bounds. */
+ if (offset + to_write < offset || blob->size < offset + to_write)
+ return false;
+
+ VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes, to_write));
+
+ if (blob->data)
+ memcpy(blob->data + offset, bytes, to_write);
+
+ return true;
+}
+
+bool
+blob_write_bytes(struct blob *blob, const void *bytes, size_t to_write)
+{
+ if (! grow_to_fit(blob, to_write))
+ return false;
+
+ VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes, to_write));
+
+ if (blob->data)
+ memcpy(blob->data + blob->size, bytes, to_write);
+ blob->size += to_write;
+
+ return true;
+}
+
+intptr_t
+blob_reserve_bytes(struct blob *blob, size_t to_write)
+{
+ intptr_t ret;
+
+ if (! grow_to_fit (blob, to_write))
+ return -1;
+
+ ret = blob->size;
+ blob->size += to_write;
+
+ return ret;
+}
+
+intptr_t
+blob_reserve_uint32(struct blob *blob)
+{
+ align_blob(blob, sizeof(uint32_t));
+ return blob_reserve_bytes(blob, sizeof(uint32_t));
+}
+
+intptr_t
+blob_reserve_intptr(struct blob *blob)
+{
+ align_blob(blob, sizeof(intptr_t));
+ return blob_reserve_bytes(blob, sizeof(intptr_t));
+}
+
+bool
+blob_write_uint32(struct blob *blob, uint32_t value)
+{
+ align_blob(blob, sizeof(value));
+
+ return blob_write_bytes(blob, &value, sizeof(value));
+}
+
+#define ASSERT_ALIGNED(_offset, _align) \
+ assert(ALIGN((_offset), (_align)) == (_offset))
+
+bool
+blob_overwrite_uint32 (struct blob *blob,
+ size_t offset,
+ uint32_t value)
+{
+ ASSERT_ALIGNED(offset, sizeof(value));
+ return blob_overwrite_bytes(blob, offset, &value, sizeof(value));
+}
+
+bool
+blob_write_uint64(struct blob *blob, uint64_t value)
+{
+ align_blob(blob, sizeof(value));
+
+ return blob_write_bytes(blob, &value, sizeof(value));
+}
+
+bool
+blob_write_intptr(struct blob *blob, intptr_t value)
+{
+ align_blob(blob, sizeof(value));
+
+ return blob_write_bytes(blob, &value, sizeof(value));
+}
+
+bool
+blob_overwrite_intptr (struct blob *blob,
+ size_t offset,
+ intptr_t value)
+{
+ ASSERT_ALIGNED(offset, sizeof(value));
+ return blob_overwrite_bytes(blob, offset, &value, sizeof(value));
+}
+
+bool
+blob_write_string(struct blob *blob, const char *str)
+{
+ return blob_write_bytes(blob, str, strlen(str) + 1);
+}
+
+void
+blob_reader_init(struct blob_reader *blob, const void *data, size_t size)
+{
+ blob->data = data;
+ blob->end = blob->data + size;
+ blob->current = data;
+ blob->overrun = false;
+}
+
+/* Check that an object of size \size can be read from this blob.
+ *
+ * If not, set blob->overrun to indicate that we attempted to read too far.
+ */
+static bool
+ensure_can_read(struct blob_reader *blob, size_t size)
+{
+ if (blob->overrun)
+ return false;
+
+ if (blob->current < blob->end && blob->end - blob->current >= size)
+ return true;
+
+ blob->overrun = true;
+
+ return false;
+}
+
+const void *
+blob_read_bytes(struct blob_reader *blob, size_t size)
+{
+ const void *ret;
+
+ if (! ensure_can_read (blob, size))
+ return NULL;
+
+ ret = blob->current;
+
+ blob->current += size;
+
+ return ret;
+}
+
+void
+blob_copy_bytes(struct blob_reader *blob, void *dest, size_t size)
+{
+ const void *bytes;
+
+ bytes = blob_read_bytes(blob, size);
+ if (bytes == NULL)
+ return;
+
+ memcpy(dest, bytes, size);
+}
+
+/* These next three read functions have identical form. If we add any beyond
+ * these first three we should probably switch to generating these with a
+ * preprocessor macro.
+*/
+uint32_t
+blob_read_uint32(struct blob_reader *blob)
+{
+ uint32_t ret;
+ int size = sizeof(ret);
+
+ align_blob_reader(blob, size);
+
+ if (! ensure_can_read(blob, size))
+ return 0;
+
+ ret = *((uint32_t*) blob->current);
+
+ blob->current += size;
+
+ return ret;
+}
+
+uint64_t
+blob_read_uint64(struct blob_reader *blob)
+{
+ uint64_t ret;
+ int size = sizeof(ret);
+
+ align_blob_reader(blob, size);
+
+ if (! ensure_can_read(blob, size))
+ return 0;
+
+ ret = *((uint64_t*) blob->current);
+
+ blob->current += size;
+
+ return ret;
+}
+
+intptr_t
+blob_read_intptr(struct blob_reader *blob)
+{
+ intptr_t ret;
+ int size = sizeof(ret);
+
+ align_blob_reader(blob, size);
+
+ if (! ensure_can_read(blob, size))
+ return 0;
+
+ ret = *((intptr_t *) blob->current);
+
+ blob->current += size;
+
+ return ret;
+}
+
+char *
+blob_read_string(struct blob_reader *blob)
+{
+ int size;
+ char *ret;
+ uint8_t *nul;
+
+ /* If we're already at the end, then this is an overrun. */
+ if (blob->current >= blob->end) {
+ blob->overrun = true;
+ return NULL;
+ }
+
+ /* Similarly, if there is no zero byte in the data remaining in this blob,
+ * we also consider that an overrun.
+ */
+ nul = memchr(blob->current, 0, blob->end - blob->current);
+
+ if (nul == NULL) {
+ blob->overrun = true;
+ return NULL;
+ }
+
+ size = nul - blob->current + 1;
+
+ assert(ensure_can_read(blob, size));
+
+ ret = (char *) blob->current;
+
+ blob->current += size;
+
+ return ret;
+}
diff --git a/lib/mesa/src/compiler/blob.h b/lib/mesa/src/compiler/blob.h
new file mode 100644
index 000000000..2b975d45d
--- /dev/null
+++ b/lib/mesa/src/compiler/blob.h
@@ -0,0 +1,352 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * 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.
+ */
+
+#ifndef BLOB_H
+#define BLOB_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The blob functions implement a simple, low-level API for serializing and
+ * deserializing.
+ *
+ * All objects written to a blob will be serialized directly, (without any
+ * additional meta-data to describe the data written). Therefore, it is the
+ * caller's responsibility to ensure that any data can be read later, (either
+ * by knowing exactly what data is expected, or by writing to the blob
+ * sufficient meta-data to describe what has been written).
+ *
+ * A blob is efficient in that it dynamically grows by doubling in size, so
+ * allocation costs are logarithmic.
+ */
+
+struct blob {
+ /* The data actually written to the blob. */
+ uint8_t *data;
+
+ /** Number of bytes that have been allocated for \c data. */
+ size_t allocated;
+
+ /** The number of bytes that have actual data written to them. */
+ size_t size;
+
+ /** True if \c data a fixed allocation that we cannot resize
+ *
+ * \see blob_init_fixed
+ */
+ bool fixed_allocation;
+
+ /**
+ * True if we've ever failed to realloc or if we go pas the end of a fixed
+ * allocation blob.
+ */
+ bool out_of_memory;
+};
+
+/* When done reading, the caller can ensure that everything was consumed by
+ * checking the following:
+ *
+ * 1. blob->current should be equal to blob->end, (if not, too little was
+ * read).
+ *
+ * 2. blob->overrun should be false, (otherwise, too much was read).
+ */
+struct blob_reader {
+ const uint8_t *data;
+ const uint8_t *end;
+ const uint8_t *current;
+ bool overrun;
+};
+
+/**
+ * Init a new, empty blob.
+ */
+void
+blob_init(struct blob *blob);
+
+/**
+ * Init a new, fixed-size blob.
+ *
+ * A fixed-size blob has a fixed block of data that will not be freed on
+ * blob_finish and will never be grown. If we hit the end, we simply start
+ * returning false from the write functions.
+ *
+ * If a fixed-size blob has a NULL data pointer then the data is written but
+ * it otherwise operates normally. This can be used to determine the size
+ * that will be required to write a given data structure.
+ */
+void
+blob_init_fixed(struct blob *blob, void *data, size_t size);
+
+/**
+ * Finish a blob and free its memory.
+ *
+ * If \blob was initialized with blob_init_fixed, the data pointer is
+ * considered to be owned by the user and will not be freed.
+ */
+static inline void
+blob_finish(struct blob *blob)
+{
+ if (!blob->fixed_allocation)
+ free(blob->data);
+}
+
+/**
+ * Add some unstructured, fixed-size data to a blob.
+ *
+ * \return True unless allocation failed.
+ */
+bool
+blob_write_bytes(struct blob *blob, const void *bytes, size_t to_write);
+
+/**
+ * Reserve space in \blob for a number of bytes.
+ *
+ * Space will be allocated within the blob for these byes, but the bytes will
+ * be left uninitialized. The caller is expected to use \sa
+ * blob_overwrite_bytes to write to these bytes.
+ *
+ * \return An offset to space allocated within \blob to which \to_write bytes
+ * can be written, (or -1 in case of any allocation error).
+ */
+intptr_t
+blob_reserve_bytes(struct blob *blob, size_t to_write);
+
+/**
+ * Similar to \sa blob_reserve_bytes, but only reserves an uint32_t worth of
+ * space. Note that this must be used if later reading with \sa
+ * blob_read_uint32, since it aligns the offset correctly.
+ */
+intptr_t
+blob_reserve_uint32(struct blob *blob);
+
+/**
+ * Similar to \sa blob_reserve_bytes, but only reserves an intptr_t worth of
+ * space. Note that this must be used if later reading with \sa
+ * blob_read_intptr, since it aligns the offset correctly.
+ */
+intptr_t
+blob_reserve_intptr(struct blob *blob);
+
+/**
+ * Overwrite some data previously written to the blob.
+ *
+ * Writes data to an existing portion of the blob at an offset of \offset.
+ * This data range must have previously been written to the blob by one of the
+ * blob_write_* calls.
+ *
+ * For example usage, see blob_overwrite_uint32
+ *
+ * \return True unless the requested offset or offset+to_write lie outside
+ * the current blob's size.
+ */
+bool
+blob_overwrite_bytes(struct blob *blob,
+ size_t offset,
+ const void *bytes,
+ size_t to_write);
+
+/**
+ * Add a uint32_t to a blob.
+ *
+ * \note This function will only write to a uint32_t-aligned offset from the
+ * beginning of the blob's data, so some padding bytes may be added to the
+ * blob if this write follows some unaligned write (such as
+ * blob_write_string).
+ *
+ * \return True unless allocation failed.
+ */
+bool
+blob_write_uint32(struct blob *blob, uint32_t value);
+
+/**
+ * Overwrite a uint32_t previously written to the blob.
+ *
+ * Writes a uint32_t value to an existing portion of the blob at an offset of
+ * \offset. This data range must have previously been written to the blob by
+ * one of the blob_write_* calls.
+ *
+ *
+ * The expected usage is something like the following pattern:
+ *
+ * size_t offset;
+ *
+ * offset = blob_reserve_uint32(blob);
+ * ... various blob write calls, writing N items ...
+ * blob_overwrite_uint32 (blob, offset, N);
+ *
+ * \return True unless the requested position or position+to_write lie outside
+ * the current blob's size.
+ */
+bool
+blob_overwrite_uint32(struct blob *blob,
+ size_t offset,
+ uint32_t value);
+
+/**
+ * Add a uint64_t to a blob.
+ *
+ * \note This function will only write to a uint64_t-aligned offset from the
+ * beginning of the blob's data, so some padding bytes may be added to the
+ * blob if this write follows some unaligned write (such as
+ * blob_write_string).
+ *
+ * \return True unless allocation failed.
+ */
+bool
+blob_write_uint64(struct blob *blob, uint64_t value);
+
+/**
+ * Add an intptr_t to a blob.
+ *
+ * \note This function will only write to an intptr_t-aligned offset from the
+ * beginning of the blob's data, so some padding bytes may be added to the
+ * blob if this write follows some unaligned write (such as
+ * blob_write_string).
+ *
+ * \return True unless allocation failed.
+ */
+bool
+blob_write_intptr(struct blob *blob, intptr_t value);
+
+/**
+ * Overwrite an intptr_t previously written to the blob.
+ *
+ * Writes a intptr_t value to an existing portion of the blob at an offset of
+ * \offset. This data range must have previously been written to the blob by
+ * one of the blob_write_* calls.
+ *
+ * For example usage, see blob_overwrite_uint32
+ *
+ * \return True unless the requested position or position+to_write lie outside
+ * the current blob's size.
+ */
+bool
+blob_overwrite_intptr(struct blob *blob,
+ size_t offset,
+ intptr_t value);
+
+/**
+ * Add a NULL-terminated string to a blob, (including the NULL terminator).
+ *
+ * \return True unless allocation failed.
+ */
+bool
+blob_write_string(struct blob *blob, const char *str);
+
+/**
+ * Start reading a blob, (initializing the contents of \blob for reading).
+ *
+ * After this call, the caller can use the various blob_read_* functions to
+ * read elements from the data array.
+ *
+ * For all of the blob_read_* functions, if there is insufficient data
+ * remaining, the functions will do nothing, (perhaps returning default values
+ * such as 0). The caller can detect this by noting that the blob_reader's
+ * current value is unchanged before and after the call.
+ */
+void
+blob_reader_init(struct blob_reader *blob, const void *data, size_t size);
+
+/**
+ * Read some unstructured, fixed-size data from the current location, (and
+ * update the current location to just past this data).
+ *
+ * \note The memory returned belongs to the data underlying the blob reader. The
+ * caller must copy the data in order to use it after the lifetime of the data
+ * underlying the blob reader.
+ *
+ * \return The bytes read (see note above about memory lifetime).
+ */
+const void *
+blob_read_bytes(struct blob_reader *blob, size_t size);
+
+/**
+ * Read some unstructured, fixed-size data from the current location, copying
+ * it to \dest (and update the current location to just past this data)
+ */
+void
+blob_copy_bytes(struct blob_reader *blob, void *dest, size_t size);
+
+/**
+ * Read a uint32_t from the current location, (and update the current location
+ * to just past this uint32_t).
+ *
+ * \note This function will only read from a uint32_t-aligned offset from the
+ * beginning of the blob's data, so some padding bytes may be skipped.
+ *
+ * \return The uint32_t read
+ */
+uint32_t
+blob_read_uint32(struct blob_reader *blob);
+
+/**
+ * Read a uint64_t from the current location, (and update the current location
+ * to just past this uint64_t).
+ *
+ * \note This function will only read from a uint64_t-aligned offset from the
+ * beginning of the blob's data, so some padding bytes may be skipped.
+ *
+ * \return The uint64_t read
+ */
+uint64_t
+blob_read_uint64(struct blob_reader *blob);
+
+/**
+ * Read an intptr_t value from the current location, (and update the
+ * current location to just past this intptr_t).
+ *
+ * \note This function will only read from an intptr_t-aligned offset from the
+ * beginning of the blob's data, so some padding bytes may be skipped.
+ *
+ * \return The intptr_t read
+ */
+intptr_t
+blob_read_intptr(struct blob_reader *blob);
+
+/**
+ * Read a NULL-terminated string from the current location, (and update the
+ * current location to just past this string).
+ *
+ * \note The memory returned belongs to the data underlying the blob reader. The
+ * caller must copy the string in order to use the string after the lifetime
+ * of the data underlying the blob reader.
+ *
+ * \return The string read (see note above about memory lifetime). However, if
+ * there is no NULL byte remaining within the blob, this function returns
+ * NULL.
+ */
+char *
+blob_read_string(struct blob_reader *blob);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BLOB_H */
diff --git a/lib/mesa/src/compiler/glsl/ir_expression_flattening.cpp b/lib/mesa/src/compiler/glsl/ir_expression_flattening.cpp
index c13ae811d..e4ca850d2 100644
--- a/lib/mesa/src/compiler/glsl/ir_expression_flattening.cpp
+++ b/lib/mesa/src/compiler/glsl/ir_expression_flattening.cpp
@@ -77,9 +77,7 @@ ir_expression_flattening_visitor::handle_rvalue(ir_rvalue **rvalue)
var = new(ctx) ir_variable(ir->type, "flattening_tmp", ir_var_temporary);
base_ir->insert_before(var);
- assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
- ir,
- NULL);
+ assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var), ir);
base_ir->insert_before(assign);
*rvalue = new(ctx) ir_dereference_variable(var);
diff --git a/lib/mesa/src/compiler/glsl/loop_analysis.cpp b/lib/mesa/src/compiler/glsl/loop_analysis.cpp
index b9bae4353..2979e0943 100644
--- a/lib/mesa/src/compiler/glsl/loop_analysis.cpp
+++ b/lib/mesa/src/compiler/glsl/loop_analysis.cpp
@@ -25,13 +25,188 @@
#include "loop_analysis.h"
#include "ir_hierarchical_visitor.h"
-static bool is_loop_terminator(ir_if *ir);
+static void try_add_loop_terminator(loop_variable_state *ls, ir_if *ir);
static bool all_expression_operands_are_loop_constant(ir_rvalue *,
hash_table *);
static ir_rvalue *get_basic_induction_increment(ir_assignment *, hash_table *);
+/**
+ * Find an initializer of a variable outside a loop
+ *
+ * Works backwards from the loop to find the pre-loop value of the variable.
+ * This is used, for example, to find the initial value of loop induction
+ * variables.
+ *
+ * \param loop Loop where \c var is an induction variable
+ * \param var Variable whose initializer is to be found
+ *
+ * \return
+ * The \c ir_rvalue assigned to the variable outside the loop. May return
+ * \c NULL if no initializer can be found.
+ */
+static ir_rvalue *
+find_initial_value(ir_loop *loop, ir_variable *var)
+{
+ for (exec_node *node = loop->prev; !node->is_head_sentinel();
+ node = node->prev) {
+ ir_instruction *ir = (ir_instruction *) node;
+
+ switch (ir->ir_type) {
+ case ir_type_call:
+ case ir_type_loop:
+ case ir_type_loop_jump:
+ case ir_type_return:
+ case ir_type_if:
+ return NULL;
+
+ case ir_type_function:
+ case ir_type_function_signature:
+ assert(!"Should not get here.");
+ return NULL;
+
+ case ir_type_assignment: {
+ ir_assignment *assign = ir->as_assignment();
+ ir_variable *assignee = assign->lhs->whole_variable_referenced();
+
+ if (assignee == var)
+ return (assign->condition != NULL) ? NULL : assign->rhs;
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+
+static int
+calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
+ enum ir_expression_operation op, bool continue_from_then)
+{
+ if (from == NULL || to == NULL || increment == NULL)
+ return -1;
+
+ void *mem_ctx = ralloc_context(NULL);
+
+ ir_expression *const sub =
+ new(mem_ctx) ir_expression(ir_binop_sub, from->type, to, from);
+
+ ir_expression *const div =
+ new(mem_ctx) ir_expression(ir_binop_div, sub->type, sub, increment);
+
+ ir_constant *iter = div->constant_expression_value(mem_ctx);
+ if (iter == NULL) {
+ ralloc_free(mem_ctx);
+ return -1;
+ }
+
+ if (!iter->type->is_integer()) {
+ const ir_expression_operation op = iter->type->is_double()
+ ? ir_unop_d2i : ir_unop_f2i;
+ ir_rvalue *cast =
+ new(mem_ctx) ir_expression(op, glsl_type::int_type, iter, NULL);
+
+ iter = cast->constant_expression_value(mem_ctx);
+ }
+
+ int iter_value = iter->get_int_component(0);
+
+ /* Make sure that the calculated number of iterations satisfies the exit
+ * condition. This is needed to catch off-by-one errors and some types of
+ * ill-formed loops. For example, we need to detect that the following
+ * loop does not have a maximum iteration count.
+ *
+ * for (float x = 0.0; x != 0.9; x += 0.2)
+ * ;
+ */
+ const int bias[] = { -1, 0, 1 };
+ bool valid_loop = false;
+
+ for (unsigned i = 0; i < ARRAY_SIZE(bias); i++) {
+ /* Increment may be of type int, uint or float. */
+ switch (increment->type->base_type) {
+ case GLSL_TYPE_INT:
+ iter = new(mem_ctx) ir_constant(iter_value + bias[i]);
+ break;
+ case GLSL_TYPE_UINT:
+ iter = new(mem_ctx) ir_constant(unsigned(iter_value + bias[i]));
+ break;
+ case GLSL_TYPE_FLOAT:
+ iter = new(mem_ctx) ir_constant(float(iter_value + bias[i]));
+ break;
+ case GLSL_TYPE_DOUBLE:
+ iter = new(mem_ctx) ir_constant(double(iter_value + bias[i]));
+ break;
+ default:
+ unreachable("Unsupported type for loop iterator.");
+ }
+
+ ir_expression *const mul =
+ new(mem_ctx) ir_expression(ir_binop_mul, increment->type, iter,
+ increment);
+
+ ir_expression *const add =
+ new(mem_ctx) ir_expression(ir_binop_add, mul->type, mul, from);
+
+ ir_expression *cmp =
+ new(mem_ctx) ir_expression(op, glsl_type::bool_type, add, to);
+ if (continue_from_then)
+ cmp = new(mem_ctx) ir_expression(ir_unop_logic_not, cmp);
+
+ ir_constant *const cmp_result = cmp->constant_expression_value(mem_ctx);
+
+ assert(cmp_result != NULL);
+ if (cmp_result->get_bool_component(0)) {
+ iter_value += bias[i];
+ valid_loop = true;
+ break;
+ }
+ }
+
+ ralloc_free(mem_ctx);
+ return (valid_loop) ? iter_value : -1;
+}
+
+static bool
+incremented_before_terminator(ir_loop *loop, ir_variable *var,
+ ir_if *terminator)
+{
+ for (exec_node *node = loop->body_instructions.get_head();
+ !node->is_tail_sentinel();
+ node = node->get_next()) {
+ ir_instruction *ir = (ir_instruction *) node;
+
+ switch (ir->ir_type) {
+ case ir_type_if:
+ if (ir->as_if() == terminator)
+ return false;
+ break;
+
+ case ir_type_assignment: {
+ ir_assignment *assign = ir->as_assignment();
+ ir_variable *assignee = assign->lhs->whole_variable_referenced();
+
+ if (assignee == var) {
+ assert(assign->condition == NULL);
+ return true;
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ unreachable("Unable to find induction variable");
+}
/**
* Record the fact that the given loop variable was referenced inside the loop.
@@ -133,12 +308,14 @@ loop_variable_state::insert(ir_variable *var)
loop_terminator *
-loop_variable_state::insert(ir_if *if_stmt)
+loop_variable_state::insert(ir_if *if_stmt, bool continue_from_then)
{
void *mem_ctx = ralloc_parent(this);
loop_terminator *t = new(mem_ctx) loop_terminator();
t->ir = if_stmt;
+ t->continue_from_then = continue_from_then;
+
this->terminators.push_tail(t);
return t;
@@ -295,10 +472,8 @@ loop_analysis::visit_leave(ir_loop *ir)
ir_if *if_stmt = ((ir_instruction *) node)->as_if();
- if ((if_stmt != NULL) && is_loop_terminator(if_stmt))
- ls->insert(if_stmt);
- else
- break;
+ if (if_stmt != NULL)
+ try_add_loop_terminator(ls, if_stmt);
}
@@ -441,7 +616,11 @@ loop_analysis::visit_leave(ir_loop *ir)
loop_variable *lv = ls->get(var);
if (lv != NULL && lv->is_induction_var()) {
t->iterations = calculate_iterations(init, limit, lv->increment,
- cmp);
+ cmp, t->continue_from_then);
+
+ if (incremented_before_terminator(ir, var, t->ir)) {
+ t->iterations--;
+ }
if (t->iterations >= 0 &&
(ls->limiting_terminator == NULL ||
@@ -604,31 +783,26 @@ get_basic_induction_increment(ir_assignment *ir, hash_table *var_hash)
/**
- * Detect whether an if-statement is a loop terminating condition
+ * Detect whether an if-statement is a loop terminating condition, if so
+ * add it to the list of loop terminators.
*
* Detects if-statements of the form
*
- * (if (expression bool ...) (break))
+ * (if (expression bool ...) (...then_instrs...break))
+ *
+ * or
+ *
+ * (if (expression bool ...) ... (...else_instrs...break))
*/
-bool
-is_loop_terminator(ir_if *ir)
+void
+try_add_loop_terminator(loop_variable_state *ls, ir_if *ir)
{
- if (!ir->else_instructions.is_empty())
- return false;
-
- ir_instruction *const inst =
- (ir_instruction *) ir->then_instructions.get_head();
- if (inst == NULL)
- return false;
-
- if (inst->ir_type != ir_type_loop_jump)
- return false;
-
- ir_loop_jump *const jump = (ir_loop_jump *) inst;
- if (jump->mode != ir_loop_jump::jump_break)
- return false;
+ ir_instruction *inst = (ir_instruction *) ir->then_instructions.get_tail();
+ ir_instruction *else_inst =
+ (ir_instruction *) ir->else_instructions.get_tail();
- return true;
+ if (is_break(inst) || is_break(else_inst))
+ ls->insert(ir, is_break(else_inst));
}
diff --git a/lib/mesa/src/compiler/glsl/loop_unroll.cpp b/lib/mesa/src/compiler/glsl/loop_unroll.cpp
index bc377dff3..874f41856 100644
--- a/lib/mesa/src/compiler/glsl/loop_unroll.cpp
+++ b/lib/mesa/src/compiler/glsl/loop_unroll.cpp
@@ -42,7 +42,9 @@ public:
virtual ir_visitor_status visit_leave(ir_loop *ir);
void simple_unroll(ir_loop *ir, int iterations);
void complex_unroll(ir_loop *ir, int iterations,
- bool continue_from_then_branch);
+ bool continue_from_then_branch,
+ bool limiting_term_first,
+ bool lt_continue_from_then_branch);
void splice_post_if_instructions(ir_if *ir_if, exec_list *splice_dest);
loop_state *state;
@@ -53,13 +55,6 @@ public:
} /* anonymous namespace */
-static bool
-is_break(ir_instruction *ir)
-{
- return ir != NULL && ir->ir_type == ir_type_loop_jump
- && ((ir_loop_jump *) ir)->is_break();
-}
-
class loop_unroll_count : public ir_hierarchical_visitor {
public:
int nodes;
@@ -106,7 +101,7 @@ public:
if (options->EmitNoIndirectSampler) {
if ((ir->array->type->is_array() &&
ir->array->type->contains_sampler()) &&
- !ir->array_index->constant_expression_value()) {
+ !ir->array_index->constant_expression_value(ralloc_parent(ir))) {
unsupported_variable_indexing = true;
return visit_continue;
}
@@ -183,6 +178,51 @@ void
loop_unroll_visitor::simple_unroll(ir_loop *ir, int iterations)
{
void *const mem_ctx = ralloc_parent(ir);
+ loop_variable_state *const ls = this->state->get(ir);
+
+ ir_instruction *first_ir =
+ (ir_instruction *) ir->body_instructions.get_head();
+
+ if (!first_ir) {
+ /* The loop is empty remove it and return */
+ ir->remove();
+ return;
+ }
+
+ ir_if *limit_if = NULL;
+ bool exit_branch_has_instructions = false;
+ if (ls->limiting_terminator) {
+ limit_if = ls->limiting_terminator->ir;
+ ir_instruction *ir_if_last = (ir_instruction *)
+ limit_if->then_instructions.get_tail();
+
+ if (is_break(ir_if_last)) {
+ if (ir_if_last != limit_if->then_instructions.get_head())
+ exit_branch_has_instructions = true;
+
+ splice_post_if_instructions(limit_if, &limit_if->else_instructions);
+ ir_if_last->remove();
+ } else {
+ ir_if_last = (ir_instruction *)
+ limit_if->else_instructions.get_tail();
+ assert(is_break(ir_if_last));
+
+ if (ir_if_last != limit_if->else_instructions.get_head())
+ exit_branch_has_instructions = true;
+
+ splice_post_if_instructions(limit_if, &limit_if->then_instructions);
+ ir_if_last->remove();
+ }
+ }
+
+ /* Because 'iterations' is the number of times we pass over the *entire*
+ * loop body before hitting the first break, we need to bump the number of
+ * iterations if the limiting terminator is not the first instruction in
+ * the loop, or it the exit branch contains instructions. This ensures we
+ * execute any instructions before the terminator or in its exit branch.
+ */
+ if (limit_if != first_ir->as_if() || exit_branch_has_instructions)
+ iterations++;
for (int i = 0; i < iterations; i++) {
exec_list copy_list;
@@ -234,11 +274,22 @@ loop_unroll_visitor::simple_unroll(ir_loop *ir, int iterations)
*/
void
loop_unroll_visitor::complex_unroll(ir_loop *ir, int iterations,
- bool continue_from_then_branch)
+ bool second_term_then_continue,
+ bool extra_iteration_required,
+ bool first_term_then_continue)
{
void *const mem_ctx = ralloc_parent(ir);
ir_instruction *ir_to_replace = ir;
+ /* Because 'iterations' is the number of times we pass over the *entire*
+ * loop body before hitting the first break, we need to bump the number of
+ * iterations if the limiting terminator is not the first instruction in
+ * the loop, or it the exit branch contains instructions. This ensures we
+ * execute any instructions before the terminator or in its exit branch.
+ */
+ if (extra_iteration_required)
+ iterations++;
+
for (int i = 0; i < iterations; i++) {
exec_list copy_list;
@@ -248,6 +299,10 @@ loop_unroll_visitor::complex_unroll(ir_loop *ir, int iterations,
ir_if *ir_if = ((ir_instruction *) copy_list.get_tail())->as_if();
assert(ir_if != NULL);
+ exec_list *const first_list = first_term_then_continue
+ ? &ir_if->then_instructions : &ir_if->else_instructions;
+ ir_if = ((ir_instruction *) first_list->get_tail())->as_if();
+
ir_to_replace->insert_before(&copy_list);
ir_to_replace->remove();
@@ -255,10 +310,10 @@ loop_unroll_visitor::complex_unroll(ir_loop *ir, int iterations,
ir_to_replace =
new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue);
- exec_list *const list = (continue_from_then_branch)
+ exec_list *const second_term_continue_list = second_term_then_continue
? &ir_if->then_instructions : &ir_if->else_instructions;
- list->push_tail(ir_to_replace);
+ second_term_continue_list->push_tail(ir_to_replace);
}
ir_to_replace->remove();
@@ -300,12 +355,26 @@ loop_unroll_visitor::splice_post_if_instructions(ir_if *ir_if,
}
}
+static bool
+exit_branch_has_instructions(ir_if *term_if, bool lt_then_continue)
+{
+ if (lt_then_continue) {
+ if (term_if->else_instructions.get_head() ==
+ term_if->else_instructions.get_tail())
+ return false;
+ } else {
+ if (term_if->then_instructions.get_head() ==
+ term_if->then_instructions.get_tail())
+ return false;
+ }
+
+ return true;
+}
ir_visitor_status
loop_unroll_visitor::visit_leave(ir_loop *ir)
{
loop_variable_state *const ls = this->state->get(ir);
- int iterations;
/* If we've entered a loop that hasn't been analyzed, something really,
* really bad has happened.
@@ -315,6 +384,58 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
return visit_continue;
}
+ if (ls->limiting_terminator != NULL) {
+ /* If the limiting terminator has an iteration count of zero, then we've
+ * proven that the loop cannot run, so delete it.
+ */
+ int iterations = ls->limiting_terminator->iterations;
+ if (iterations == 0) {
+ ir->remove();
+ this->progress = true;
+ return visit_continue;
+ }
+ }
+
+ /* Remove the conditional break statements associated with all terminators
+ * that are associated with a fixed iteration count, except for the one
+ * associated with the limiting terminator--that one needs to stay, since
+ * it terminates the loop. Exception: if the loop still has a normative
+ * bound, then that terminates the loop, so we don't even need the limiting
+ * terminator.
+ */
+ foreach_in_list_safe(loop_terminator, t, &ls->terminators) {
+ if (t->iterations < 0)
+ continue;
+
+ exec_list *branch_instructions;
+ if (t != ls->limiting_terminator) {
+ ir_instruction *ir_if_last = (ir_instruction *)
+ t->ir->then_instructions.get_tail();
+ if (is_break(ir_if_last)) {
+ branch_instructions = &t->ir->else_instructions;
+ } else {
+ branch_instructions = &t->ir->then_instructions;
+ assert(is_break((ir_instruction *)
+ t->ir->else_instructions.get_tail()));
+ }
+
+ exec_list copy_list;
+ copy_list.make_empty();
+ clone_ir_list(ir, &copy_list, branch_instructions);
+
+ t->ir->insert_before(&copy_list);
+ t->ir->remove();
+
+ assert(ls->num_loop_jumps > 0);
+ ls->num_loop_jumps--;
+
+ /* Also remove it from the terminator list */
+ t->remove();
+
+ this->progress = true;
+ }
+ }
+
if (ls->limiting_terminator == NULL) {
ir_instruction *last_ir =
(ir_instruction *) ir->body_instructions.get_tail();
@@ -343,7 +464,7 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
return visit_continue;
}
- iterations = ls->limiting_terminator->iterations;
+ int iterations = ls->limiting_terminator->iterations;
const int max_iterations = options->MaxUnrollIterations;
@@ -373,7 +494,6 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
return visit_continue;
if (predicted_num_loop_jumps == 0) {
- ls->limiting_terminator->ir->remove();
simple_unroll(ir, iterations);
return visit_continue;
}
@@ -388,51 +508,69 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
*/
last_ir->remove();
- ls->limiting_terminator->ir->remove();
simple_unroll(ir, 1);
return visit_continue;
}
- /* recognize loops in the form produced by ir_lower_jumps */
- foreach_in_list(ir_instruction, cur_ir, &ir->body_instructions) {
- /* Skip the limiting terminator, since it will go away when we
- * unroll.
- */
- if (cur_ir == ls->limiting_terminator->ir)
- continue;
+ /* Complex unrolling can only handle two terminators. One with an unknown
+ * iteration count and one with a known iteration count. We have already
+ * made sure we have a known iteration count above and removed any
+ * unreachable terminators with a known count. Here we make sure there
+ * isn't any additional unknown terminators, or any other jumps nested
+ * inside futher ifs.
+ */
+ if (ls->num_loop_jumps != 2 || ls->terminators.length() != 2)
+ return visit_continue;
+
+ ir_instruction *first_ir =
+ (ir_instruction *) ir->body_instructions.get_head();
- ir_if *ir_if = cur_ir->as_if();
- if (ir_if != NULL) {
- /* Determine which if-statement branch, if any, ends with a
- * break. The branch that did *not* have the break will get a
- * temporary continue inserted in each iteration of the loop
- * unroll.
- *
- * Note that since ls->num_loop_jumps is <= 1, it is impossible
- * for both branches to end with a break.
- */
- ir_instruction *ir_if_last =
- (ir_instruction *) ir_if->then_instructions.get_tail();
+ unsigned term_count = 0;
+ bool first_term_then_continue = false;
+ foreach_in_list(loop_terminator, t, &ls->terminators) {
+ ir_if *ir_if = t->ir->as_if();
+ assert(ir_if != NULL);
+ ir_instruction *ir_if_last =
+ (ir_instruction *) ir_if->then_instructions.get_tail();
+
+ if (is_break(ir_if_last)) {
+ splice_post_if_instructions(ir_if, &ir_if->else_instructions);
+ ir_if_last->remove();
+ if (term_count == 1) {
+ bool ebi =
+ exit_branch_has_instructions(ls->limiting_terminator->ir,
+ first_term_then_continue);
+ complex_unroll(ir, iterations, false,
+ first_ir->as_if() != ls->limiting_terminator->ir ||
+ ebi,
+ first_term_then_continue);
+ return visit_continue;
+ }
+ } else {
+ ir_if_last =
+ (ir_instruction *) ir_if->else_instructions.get_tail();
+
+ assert(is_break(ir_if_last));
if (is_break(ir_if_last)) {
- ls->limiting_terminator->ir->remove();
- splice_post_if_instructions(ir_if, &ir_if->else_instructions);
+ splice_post_if_instructions(ir_if, &ir_if->then_instructions);
ir_if_last->remove();
- complex_unroll(ir, iterations, false);
- return visit_continue;
- } else {
- ir_if_last =
- (ir_instruction *) ir_if->else_instructions.get_tail();
-
- if (is_break(ir_if_last)) {
- ls->limiting_terminator->ir->remove();
- splice_post_if_instructions(ir_if, &ir_if->then_instructions);
- ir_if_last->remove();
- complex_unroll(ir, iterations, true);
+ if (term_count == 1) {
+ bool ebi =
+ exit_branch_has_instructions(ls->limiting_terminator->ir,
+ first_term_then_continue);
+ complex_unroll(ir, iterations, true,
+ first_ir->as_if() != ls->limiting_terminator->ir ||
+ ebi,
+ first_term_then_continue);
return visit_continue;
+ } else {
+ first_term_then_continue = true;
}
}
}
+
+ term_count++;
}
/* Did not find the break statement. It must be in a complex if-nesting,
diff --git a/lib/mesa/src/compiler/glsl/lower_discard.cpp b/lib/mesa/src/compiler/glsl/lower_discard.cpp
index b62eb20dc..203d9e3b9 100644
--- a/lib/mesa/src/compiler/glsl/lower_discard.cpp
+++ b/lib/mesa/src/compiler/glsl/lower_discard.cpp
@@ -158,7 +158,7 @@ replace_discard(void *mem_ctx, ir_variable *var, ir_discard *ir)
ir_assignment *assignment =
new(mem_ctx) ir_assignment(new(mem_ctx) ir_dereference_variable(var),
- condition, NULL);
+ condition);
ir->replace_with(assignment);
}
@@ -180,7 +180,7 @@ lower_discard_visitor::visit_leave(ir_if *ir)
ir_var_temporary);
ir_assignment *temp_initializer =
new(mem_ctx) ir_assignment(new(mem_ctx) ir_dereference_variable(temp),
- new(mem_ctx) ir_constant(false), NULL);
+ new(mem_ctx) ir_constant(false));
ir->insert_before(temp);
ir->insert_before(temp_initializer);
diff --git a/lib/mesa/src/compiler/glsl/lower_mat_op_to_vec.cpp b/lib/mesa/src/compiler/glsl/lower_mat_op_to_vec.cpp
index 9a27029de..88c5d6679 100644
--- a/lib/mesa/src/compiler/glsl/lower_mat_op_to_vec.cpp
+++ b/lib/mesa/src/compiler/glsl/lower_mat_op_to_vec.cpp
@@ -76,7 +76,7 @@ mat_op_to_vec_predicate(ir_instruction *ir)
if (!expr)
return false;
- for (i = 0; i < expr->get_num_operands(); i++) {
+ for (i = 0; i < expr->num_operands; i++) {
if (expr->operands[i]->type->is_matrix())
return true;
}
@@ -294,7 +294,7 @@ ir_mat_op_to_vec_visitor::do_equal_mat_mat(ir_dereference *result,
static bool
has_matrix_operand(const ir_expression *expr, unsigned &columns)
{
- for (unsigned i = 0; i < expr->get_num_operands(); i++) {
+ for (unsigned i = 0; i < expr->num_operands; i++) {
if (expr->operands[i]->type->is_matrix()) {
columns = expr->operands[i]->type->matrix_columns;
return true;
@@ -318,7 +318,7 @@ ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *orig_assign)
if (!has_matrix_operand(orig_expr, matrix_columns))
return visit_continue;
- assert(orig_expr->get_num_operands() <= 2);
+ assert(orig_expr->num_operands <= 2);
mem_ctx = ralloc_parent(orig_assign);
@@ -329,7 +329,7 @@ ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *orig_assign)
/* Store the expression operands in temps so we can use them
* multiple times.
*/
- for (i = 0; i < orig_expr->get_num_operands(); i++) {
+ for (i = 0; i < orig_expr->num_operands; i++) {
ir_assignment *assign;
ir_dereference *deref = orig_expr->operands[i]->as_dereference();
diff --git a/lib/mesa/src/compiler/glsl/lower_shared_reference.cpp b/lib/mesa/src/compiler/glsl/lower_shared_reference.cpp
index b9098913a..a1b3f7df4 100644
--- a/lib/mesa/src/compiler/glsl/lower_shared_reference.cpp
+++ b/lib/mesa/src/compiler/glsl/lower_shared_reference.cpp
@@ -33,6 +33,7 @@
#include "lower_buffer_access.h"
#include "ir_builder.h"
+#include "linker.h"
#include "main/macros.h"
#include "util/list.h"
#include "glsl_parser_extras.h"
@@ -478,7 +479,9 @@ lower_shared_reference_visitor::visit_enter(ir_call *ir)
} /* unnamed namespace */
void
-lower_shared_reference(struct gl_linked_shader *shader, unsigned *shared_size)
+lower_shared_reference(struct gl_context *ctx,
+ struct gl_shader_program *prog,
+ struct gl_linked_shader *shader)
{
if (shader->Stage != MESA_SHADER_COMPUTE)
return;
@@ -495,5 +498,19 @@ lower_shared_reference(struct gl_linked_shader *shader, unsigned *shared_size)
visit_list_elements(&v, shader->ir);
} while (v.progress);
- *shared_size = v.shared_size;
+ prog->Comp.SharedSize = v.shared_size;
+
+ /* Section 19.1 (Compute Shader Variables) of the OpenGL 4.5 (Core Profile)
+ * specification says:
+ *
+ * "There is a limit to the total size of all variables declared as
+ * shared in a single program object. This limit, expressed in units of
+ * basic machine units, may be queried as the value of
+ * MAX_COMPUTE_SHARED_MEMORY_SIZE."
+ */
+ if (prog->Comp.SharedSize > ctx->Const.MaxComputeSharedMemorySize) {
+ linker_error(prog, "Too much shared memory used (%u/%u)\n",
+ prog->Comp.SharedSize,
+ ctx->Const.MaxComputeSharedMemorySize);
+ }
}
diff --git a/lib/mesa/src/compiler/glsl/lower_tess_level.cpp b/lib/mesa/src/compiler/glsl/lower_tess_level.cpp
index 0a244f143..b0965eb56 100644
--- a/lib/mesa/src/compiler/glsl/lower_tess_level.cpp
+++ b/lib/mesa/src/compiler/glsl/lower_tess_level.cpp
@@ -264,7 +264,8 @@ lower_tess_level_visitor::fix_lhs(ir_assignment *ir)
ir_dereference *const new_lhs = (ir_dereference *) expr->operands[0];
- ir_constant *old_index_constant = expr->operands[1]->constant_expression_value();
+ ir_constant *old_index_constant =
+ expr->operands[1]->constant_expression_value(mem_ctx);
if (!old_index_constant) {
ir->rhs = new(mem_ctx) ir_expression(ir_triop_vector_insert,
expr->operands[0]->type,
diff --git a/lib/mesa/src/compiler/glsl/lower_variable_index_to_cond_assign.cpp b/lib/mesa/src/compiler/glsl/lower_variable_index_to_cond_assign.cpp
index fcb12d1b7..6fe4fe62b 100644
--- a/lib/mesa/src/compiler/glsl/lower_variable_index_to_cond_assign.cpp
+++ b/lib/mesa/src/compiler/glsl/lower_variable_index_to_cond_assign.cpp
@@ -51,6 +51,10 @@
#include "ir_optimization.h"
#include "compiler/glsl_types.h"
#include "main/macros.h"
+#include "program/prog_instruction.h" /* For SWIZZLE_XXXX */
+#include "ir_builder.h"
+
+using namespace ir_builder;
/**
* Generate a comparison value for a block of indices
@@ -66,23 +70,21 @@
* \param mem_ctx ralloc memory context to be used for all allocations.
*
* \returns
- * An \c ir_rvalue that \b must be cloned for each use in conditional
- * assignments, etc.
+ * An \c ir_variable containing the per-component comparison results. This
+ * must be dereferenced per use.
*/
-ir_rvalue *
-compare_index_block(exec_list *instructions, ir_variable *index,
- unsigned base, unsigned components, void *mem_ctx)
+ir_variable *
+compare_index_block(ir_factory &body, ir_variable *index,
+ unsigned base, unsigned components)
{
- ir_rvalue *broadcast_index = new(mem_ctx) ir_dereference_variable(index);
-
assert(index->type->is_scalar());
- assert(index->type->base_type == GLSL_TYPE_INT || index->type->base_type == GLSL_TYPE_UINT);
+ assert(index->type->base_type == GLSL_TYPE_INT ||
+ index->type->base_type == GLSL_TYPE_UINT);
assert(components >= 1 && components <= 4);
- if (components > 1) {
- const ir_swizzle_mask m = { 0, 0, 0, 0, components, false };
- broadcast_index = new(mem_ctx) ir_swizzle(broadcast_index, m);
- }
+ ir_rvalue *const broadcast_index = components > 1
+ ? swizzle(index, SWIZZLE_XXXX, components)
+ : operand(index).val;
/* Compare the desired index value with the next block of four indices.
*/
@@ -94,26 +96,16 @@ compare_index_block(exec_list *instructions, ir_variable *index,
test_indices_data.i[3] = base + 3;
ir_constant *const test_indices =
- new(mem_ctx) ir_constant(broadcast_index->type,
- &test_indices_data);
-
- ir_rvalue *const condition_val =
- new(mem_ctx) ir_expression(ir_binop_equal,
- glsl_type::bvec(components),
- broadcast_index,
- test_indices);
-
- ir_variable *const condition =
- new(mem_ctx) ir_variable(condition_val->type,
- "dereference_condition",
- ir_var_temporary);
- instructions->push_tail(condition);
-
- ir_rvalue *const cond_deref =
- new(mem_ctx) ir_dereference_variable(condition);
- instructions->push_tail(new(mem_ctx) ir_assignment(cond_deref, condition_val, 0));
-
- return cond_deref;
+ new(body.mem_ctx) ir_constant(broadcast_index->type, &test_indices_data);
+
+ ir_rvalue *const condition_val = equal(broadcast_index, test_indices);
+
+ ir_variable *const condition = body.make_temp(condition_val->type,
+ "dereference_condition");
+
+ body.emit(assign(condition, condition_val));
+
+ return condition;
}
static inline bool
@@ -133,7 +125,7 @@ class deref_replacer : public ir_rvalue_visitor {
public:
deref_replacer(const ir_variable *variable_to_replace, ir_rvalue *value)
: variable_to_replace(variable_to_replace), value(value),
- progress(false)
+ progress(false)
{
assert(this->variable_to_replace != NULL);
assert(this->value != NULL);
@@ -143,9 +135,9 @@ public:
{
ir_dereference_variable *const dv = (*rvalue)->as_dereference_variable();
- if ((dv != NULL) && (dv->var == this->variable_to_replace)) {
- this->progress = true;
- *rvalue = this->value->clone(ralloc_parent(*rvalue), NULL);
+ if (dv != NULL && dv->var == this->variable_to_replace) {
+ this->progress = true;
+ *rvalue = this->value->clone(ralloc_parent(*rvalue), NULL);
}
}
@@ -167,10 +159,10 @@ public:
virtual ir_visitor_status visit_enter(ir_dereference_array *ir)
{
- if (is_array_or_matrix(ir->array)
- && (ir->array_index->as_constant() == NULL)) {
- this->deref = ir;
- return visit_stop;
+ if (is_array_or_matrix(ir->array) &&
+ ir->array_index->as_constant() == NULL) {
+ this->deref = ir;
+ return visit_stop;
}
return visit_continue;
@@ -201,18 +193,13 @@ struct assignment_generator
{
}
- void generate(unsigned i, ir_rvalue* condition, exec_list *list) const
+ void generate(unsigned i, ir_rvalue* condition, ir_factory &body) const
{
- /* Just clone the rest of the deref chain when trying to get at the
- * underlying variable.
- */
- void *mem_ctx = ralloc_parent(base_ir);
-
/* Clone the old r-value in its entirety. Then replace any occurances of
* the old variable index with the new constant index.
*/
- ir_dereference *element = this->rvalue->clone(mem_ctx, NULL);
- ir_constant *const index = new(mem_ctx) ir_constant(i);
+ ir_dereference *element = this->rvalue->clone(body.mem_ctx, NULL);
+ ir_constant *const index = body.constant(i);
deref_replacer r(this->old_index, index);
element->accept(&r);
assert(r.progress);
@@ -220,12 +207,11 @@ struct assignment_generator
/* Generate a conditional assignment to (or from) the constant indexed
* array dereference.
*/
- ir_rvalue *variable = new(mem_ctx) ir_dereference_variable(this->var);
ir_assignment *const assignment = (is_write)
- ? new(mem_ctx) ir_assignment(element, variable, condition, write_mask)
- : new(mem_ctx) ir_assignment(variable, element, condition);
+ ? assign(element, this->var, condition, write_mask)
+ : assign(this->var, element, condition);
- list->push_tail(assignment);
+ body.emit(assignment);
}
};
@@ -242,16 +228,16 @@ struct switch_generator
void *mem_ctx;
switch_generator(const TFunction& generator, ir_variable *index,
- unsigned linear_sequence_max_length,
- unsigned condition_components)
+ unsigned linear_sequence_max_length,
+ unsigned condition_components)
: generator(generator), index(index),
- linear_sequence_max_length(linear_sequence_max_length),
- condition_components(condition_components)
+ linear_sequence_max_length(linear_sequence_max_length),
+ condition_components(condition_components)
{
this->mem_ctx = ralloc_parent(index);
}
- void linear_sequence(unsigned begin, unsigned end, exec_list *list)
+ void linear_sequence(unsigned begin, unsigned end, ir_factory &body)
{
if (begin == end)
return;
@@ -266,66 +252,57 @@ struct switch_generator
*/
unsigned first;
if (!this->generator.is_write) {
- this->generator.generate(begin, 0, list);
- first = begin + 1;
+ this->generator.generate(begin, 0, body);
+ first = begin + 1;
} else {
- first = begin;
+ first = begin;
}
for (unsigned i = first; i < end; i += 4) {
const unsigned comps = MIN2(condition_components, end - i);
-
- ir_rvalue *const cond_deref =
- compare_index_block(list, index, i, comps, this->mem_ctx);
+ ir_variable *const cond = compare_index_block(body, index, i, comps);
if (comps == 1) {
- this->generator.generate(i, cond_deref->clone(this->mem_ctx, NULL),
- list);
+ this->generator.generate(i,
+ operand(cond).val,
+ body);
} else {
for (unsigned j = 0; j < comps; j++) {
- ir_rvalue *const cond_swiz =
- new(this->mem_ctx) ir_swizzle(cond_deref->clone(this->mem_ctx, NULL),
- j, 0, 0, 0, 1);
-
- this->generator.generate(i + j, cond_swiz, list);
+ this->generator.generate(i + j,
+ swizzle(cond, j, 1),
+ body);
}
}
}
}
- void bisect(unsigned begin, unsigned end, exec_list *list)
+ void bisect(unsigned begin, unsigned end, ir_factory &body)
{
unsigned middle = (begin + end) >> 1;
assert(index->type->is_integer());
ir_constant *const middle_c = (index->type->base_type == GLSL_TYPE_UINT)
- ? new(this->mem_ctx) ir_constant((unsigned)middle)
- : new(this->mem_ctx) ir_constant((int)middle);
-
-
- ir_dereference_variable *deref =
- new(this->mem_ctx) ir_dereference_variable(this->index);
+ ? new(body.mem_ctx) ir_constant((unsigned)middle)
+ : new(body.mem_ctx) ir_constant((int)middle);
- ir_expression *less =
- new(this->mem_ctx) ir_expression(ir_binop_less, glsl_type::bool_type,
- deref, middle_c);
+ ir_if *if_less = new(body.mem_ctx) ir_if(less(this->index, middle_c));
- ir_if *if_less = new(this->mem_ctx) ir_if(less);
+ ir_factory then_body(&if_less->then_instructions, body.mem_ctx);
+ ir_factory else_body(&if_less->else_instructions, body.mem_ctx);
+ generate(begin, middle, then_body);
+ generate(middle, end, else_body);
- generate(begin, middle, &if_less->then_instructions);
- generate(middle, end, &if_less->else_instructions);
-
- list->push_tail(if_less);
+ body.emit(if_less);
}
- void generate(unsigned begin, unsigned end, exec_list *list)
+ void generate(unsigned begin, unsigned end, ir_factory &body)
{
unsigned length = end - begin;
if (length <= this->linear_sequence_max_length)
- return linear_sequence(begin, end, list);
+ return linear_sequence(begin, end, body);
else
- return bisect(begin, end, list);
+ return bisect(begin, end, body);
}
};
@@ -340,13 +317,11 @@ public:
bool lower_output,
bool lower_temp,
bool lower_uniform)
+ : progress(false), stage(stage), lower_inputs(lower_input),
+ lower_outputs(lower_output), lower_temps(lower_temp),
+ lower_uniforms(lower_uniform)
{
- this->progress = false;
- this->stage = stage;
- this->lower_inputs = lower_input;
- this->lower_outputs = lower_output;
- this->lower_temps = lower_temp;
- this->lower_uniforms = lower_uniform;
+ /* empty */
}
bool progress;
@@ -367,19 +342,19 @@ public:
*/
const ir_variable *const var = deref->array->variable_referenced();
if (var == NULL)
- return this->lower_temps;
+ return this->lower_temps;
switch (var->data.mode) {
case ir_var_auto:
case ir_var_temporary:
- return this->lower_temps;
+ return this->lower_temps;
case ir_var_uniform:
case ir_var_shader_storage:
- return this->lower_uniforms;
+ return this->lower_uniforms;
case ir_var_shader_shared:
- return false;
+ return false;
case ir_var_function_in:
case ir_var_const_in:
@@ -435,7 +410,7 @@ public:
return this->lower_outputs;
case ir_var_function_inout:
- return this->lower_temps;
+ return this->lower_temps;
}
assert(!"Should not get here.");
@@ -444,25 +419,27 @@ public:
bool needs_lowering(ir_dereference_array *deref) const
{
- if (deref == NULL || deref->array_index->as_constant()
- || !is_array_or_matrix(deref->array))
- return false;
+ if (deref == NULL || deref->array_index->as_constant() ||
+ !is_array_or_matrix(deref->array))
+ return false;
return this->storage_type_needs_lowering(deref);
}
ir_variable *convert_dereference_array(ir_dereference_array *orig_deref,
- ir_assignment* orig_assign,
- ir_dereference *orig_base)
+ ir_assignment* orig_assign,
+ ir_dereference *orig_base)
{
+ void *const mem_ctx = ralloc_parent(base_ir);
+ exec_list list;
+ ir_factory body(&list, mem_ctx);
+
assert(is_array_or_matrix(orig_deref->array));
const unsigned length = (orig_deref->array->type->is_array())
? orig_deref->array->type->length
: orig_deref->array->type->matrix_columns;
- void *const mem_ctx = ralloc_parent(base_ir);
-
/* Temporary storage for either the result of the dereference of
* the array, or the RHS that's being assigned into the
* dereference of the array.
@@ -470,36 +447,22 @@ public:
ir_variable *var;
if (orig_assign) {
- var = new(mem_ctx) ir_variable(orig_assign->rhs->type,
- "dereference_array_value",
- ir_var_temporary);
- base_ir->insert_before(var);
+ var = body.make_temp(orig_assign->rhs->type,
+ "dereference_array_value");
- ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(var);
- ir_assignment *assign = new(mem_ctx) ir_assignment(lhs,
- orig_assign->rhs,
- NULL);
-
- base_ir->insert_before(assign);
+ body.emit(assign(var, orig_assign->rhs));
} else {
- var = new(mem_ctx) ir_variable(orig_deref->type,
- "dereference_array_value",
- ir_var_temporary);
- base_ir->insert_before(var);
+ var = body.make_temp(orig_deref->type,
+ "dereference_array_value");
}
/* Store the index to a temporary to avoid reusing its tree. */
- ir_variable *index =
- new(mem_ctx) ir_variable(orig_deref->array_index->type,
- "dereference_array_index", ir_var_temporary);
- base_ir->insert_before(index);
+ ir_variable *index = body.make_temp(orig_deref->array_index->type,
+ "dereference_array_index");
- ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(index);
- ir_assignment *assign =
- new(mem_ctx) ir_assignment(lhs, orig_deref->array_index, NULL);
- base_ir->insert_before(assign);
+ body.emit(assign(index, orig_deref->array_index));
- orig_deref->array_index = lhs->clone(mem_ctx, NULL);
+ orig_deref->array_index = deref(index).val;
assignment_generator ag;
ag.rvalue = orig_base;
@@ -507,10 +470,10 @@ public:
ag.old_index = index;
ag.var = var;
if (orig_assign) {
- ag.is_write = true;
- ag.write_mask = orig_assign->write_mask;
+ ag.is_write = true;
+ ag.write_mask = orig_assign->write_mask;
} else {
- ag.is_write = false;
+ ag.is_write = false;
}
switch_generator sg(ag, index, 4, 4);
@@ -519,28 +482,27 @@ public:
* condition! This is acomplished by wrapping the new conditional
* assignments in an if-statement that uses the original condition.
*/
- if ((orig_assign != NULL) && (orig_assign->condition != NULL)) {
- /* No need to clone the condition because the IR that it hangs on is
- * going to be removed from the instruction sequence.
- */
- ir_if *if_stmt = new(mem_ctx) ir_if(orig_assign->condition);
-
- sg.generate(0, length, &if_stmt->then_instructions);
- base_ir->insert_before(if_stmt);
- } else {
- exec_list list;
+ if (orig_assign != NULL && orig_assign->condition != NULL) {
+ /* No need to clone the condition because the IR that it hangs on is
+ * going to be removed from the instruction sequence.
+ */
+ ir_if *if_stmt = new(mem_ctx) ir_if(orig_assign->condition);
+ ir_factory then_body(&if_stmt->then_instructions, body.mem_ctx);
- sg.generate(0, length, &list);
- base_ir->insert_before(&list);
+ sg.generate(0, length, then_body);
+ body.emit(if_stmt);
+ } else {
+ sg.generate(0, length, body);
}
+ base_ir->insert_before(&list);
return var;
}
virtual void handle_rvalue(ir_rvalue **pir)
{
if (this->in_assignee)
- return;
+ return;
if (!*pir)
return;
@@ -548,7 +510,7 @@ public:
ir_dereference_array* orig_deref = (*pir)->as_dereference_array();
if (needs_lowering(orig_deref)) {
ir_variable *var =
- convert_dereference_array(orig_deref, NULL, orig_deref);
+ convert_dereference_array(orig_deref, NULL, orig_deref);
assert(var);
*pir = new(ralloc_parent(base_ir)) ir_dereference_variable(var);
this->progress = true;
@@ -563,7 +525,7 @@ public:
find_variable_index f;
ir->lhs->accept(&f);
- if ((f.deref != NULL) && storage_type_needs_lowering(f.deref)) {
+ if (f.deref != NULL && storage_type_needs_lowering(f.deref)) {
convert_dereference_array(f.deref, ir, ir->lhs);
ir->remove();
this->progress = true;
diff --git a/lib/mesa/src/compiler/glsl/lower_vec_index_to_swizzle.cpp b/lib/mesa/src/compiler/glsl/lower_vec_index_to_swizzle.cpp
index b49255e05..fdbad16a3 100644
--- a/lib/mesa/src/compiler/glsl/lower_vec_index_to_swizzle.cpp
+++ b/lib/mesa/src/compiler/glsl/lower_vec_index_to_swizzle.cpp
@@ -63,11 +63,12 @@ ir_vec_index_to_swizzle_visitor::handle_rvalue(ir_rvalue **rv)
if (expr == NULL || expr->operation != ir_binop_vector_extract)
return;
- ir_constant *const idx = expr->operands[1]->constant_expression_value();
+ void *mem_ctx = ralloc_parent(expr);
+ ir_constant *const idx =
+ expr->operands[1]->constant_expression_value(mem_ctx);
if (idx == NULL)
return;
- void *ctx = ralloc_parent(expr);
this->progress = true;
/* Page 40 of the GLSL 1.20 spec says:
@@ -87,7 +88,7 @@ ir_vec_index_to_swizzle_visitor::handle_rvalue(ir_rvalue **rv)
const int i = CLAMP(idx->value.i[0], 0,
(int) expr->operands[0]->type->vector_elements - 1);
- *rv = new(ctx) ir_swizzle(expr->operands[0], i, 0, 0, 0, 1);
+ *rv = new(mem_ctx) ir_swizzle(expr->operands[0], i, 0, 0, 0, 1);
}
bool
diff --git a/lib/mesa/src/compiler/glsl/lower_vector.cpp b/lib/mesa/src/compiler/glsl/lower_vector.cpp
index a658410ae..4024644b0 100644
--- a/lib/mesa/src/compiler/glsl/lower_vector.cpp
+++ b/lib/mesa/src/compiler/glsl/lower_vector.cpp
@@ -58,7 +58,7 @@ public:
* Extended swizzles consist of access of a single vector source (with possible
* per component negation) and the constants -1, 0, or 1.
*/
-bool
+static bool
is_extended_swizzle(ir_expression *ir)
{
/* Track any variables that are accessed by this expression.
@@ -133,7 +133,7 @@ lower_vector_visitor::handle_rvalue(ir_rvalue **rvalue)
*/
void *const mem_ctx = expr;
- assert(expr->type->vector_elements == expr->get_num_operands());
+ assert(expr->type->vector_elements == expr->num_operands);
/* Generate a temporary with the same type as the ir_quadop_operation.
*/
diff --git a/lib/mesa/src/compiler/glsl/lower_vector_derefs.cpp b/lib/mesa/src/compiler/glsl/lower_vector_derefs.cpp
index f7bf68db3..a83658d20 100644
--- a/lib/mesa/src/compiler/glsl/lower_vector_derefs.cpp
+++ b/lib/mesa/src/compiler/glsl/lower_vector_derefs.cpp
@@ -61,8 +61,9 @@ vector_deref_visitor::visit_enter(ir_assignment *ir)
ir_dereference *const new_lhs = (ir_dereference *) deref->array;
ir->set_lhs(new_lhs);
- ir_constant *old_index_constant = deref->array_index->constant_expression_value();
void *mem_ctx = ralloc_parent(ir);
+ ir_constant *old_index_constant =
+ deref->array_index->constant_expression_value(mem_ctx);
if (!old_index_constant) {
ir->rhs = new(mem_ctx) ir_expression(ir_triop_vector_insert,
new_lhs->type,
diff --git a/lib/mesa/src/compiler/glsl/lower_vector_insert.cpp b/lib/mesa/src/compiler/glsl/lower_vector_insert.cpp
index 26d31b03c..ceaa5887c 100644
--- a/lib/mesa/src/compiler/glsl/lower_vector_insert.cpp
+++ b/lib/mesa/src/compiler/glsl/lower_vector_insert.cpp
@@ -65,7 +65,8 @@ vector_insert_visitor::handle_rvalue(ir_rvalue **rv)
factory.mem_ctx = ralloc_parent(expr);
- ir_constant *const idx = expr->operands[2]->constant_expression_value();
+ ir_constant *const idx =
+ expr->operands[2]->constant_expression_value(factory.mem_ctx);
if (idx != NULL) {
/* Replace (vector_insert (vec) (scalar) (index)) with a dereference of
* a new temporary. The new temporary gets assigned as
diff --git a/lib/mesa/src/compiler/glsl/opt_constant_folding.cpp b/lib/mesa/src/compiler/glsl/opt_constant_folding.cpp
index 97dcc7e1a..3b9394d13 100644
--- a/lib/mesa/src/compiler/glsl/opt_constant_folding.cpp
+++ b/lib/mesa/src/compiler/glsl/opt_constant_folding.cpp
@@ -74,7 +74,7 @@ ir_constant_fold(ir_rvalue **rvalue)
*/
ir_expression *expr = (*rvalue)->as_expression();
if (expr) {
- for (unsigned int i = 0; i < expr->get_num_operands(); i++) {
+ for (unsigned int i = 0; i < expr->num_operands; i++) {
if (!expr->operands[i]->as_constant())
return false;
}
@@ -100,7 +100,8 @@ ir_constant_fold(ir_rvalue **rvalue)
if (var_ref)
return false;
- ir_constant *constant = (*rvalue)->constant_expression_value();
+ ir_constant *constant =
+ (*rvalue)->constant_expression_value(ralloc_parent(*rvalue));
if (constant) {
*rvalue = constant;
return true;
@@ -189,7 +190,7 @@ ir_constant_folding_visitor::visit_enter(ir_call *ir)
}
/* Next, see if the call can be replaced with an assignment of a constant */
- ir_constant *const_val = ir->constant_expression_value();
+ ir_constant *const_val = ir->constant_expression_value(ralloc_parent(ir));
if (const_val != NULL) {
ir_assignment *assignment =
diff --git a/lib/mesa/src/compiler/glsl/opt_constant_variable.cpp b/lib/mesa/src/compiler/glsl/opt_constant_variable.cpp
index 1c06ffe67..914b46004 100644
--- a/lib/mesa/src/compiler/glsl/opt_constant_variable.cpp
+++ b/lib/mesa/src/compiler/glsl/opt_constant_variable.cpp
@@ -131,7 +131,7 @@ ir_constant_variable_visitor::visit_enter(ir_assignment *ir)
var->data.mode == ir_var_shader_shared)
return visit_continue;
- constval = ir->rhs->constant_expression_value();
+ constval = ir->rhs->constant_expression_value(ralloc_parent(ir));
if (!constval)
return visit_continue;
diff --git a/lib/mesa/src/compiler/glsl/opt_if_simplification.cpp b/lib/mesa/src/compiler/glsl/opt_if_simplification.cpp
index e05f03190..136ef8772 100644
--- a/lib/mesa/src/compiler/glsl/opt_if_simplification.cpp
+++ b/lib/mesa/src/compiler/glsl/opt_if_simplification.cpp
@@ -84,7 +84,8 @@ ir_if_simplification_visitor::visit_leave(ir_if *ir)
* FINISHME: This can probably be done with some flags, but it would take
* FINISHME: some work to get right.
*/
- ir_constant *condition_constant = ir->condition->constant_expression_value();
+ ir_constant *condition_constant =
+ ir->condition->constant_expression_value(ralloc_parent(ir));
if (condition_constant) {
/* Move the contents of the one branch of the conditional
* that matters out.
diff --git a/lib/mesa/src/compiler/glsl/tests/array_refcount_test.cpp b/lib/mesa/src/compiler/glsl/tests/array_refcount_test.cpp
index ecd7f4690..0d8f4521c 100644
--- a/lib/mesa/src/compiler/glsl/tests/array_refcount_test.cpp
+++ b/lib/mesa/src/compiler/glsl/tests/array_refcount_test.cpp
@@ -628,7 +628,7 @@ TEST_F(array_refcount_test, visit_array_indexing_an_array)
ir_array_refcount_entry *const entry_c = v.get_variable_entry(var_c);
- for (unsigned i = 0; i < var_c->type->array_size(); i++) {
+ for (int i = 0; i < var_c->type->array_size(); i++) {
EXPECT_EQ(true, entry_c->is_linearized_index_referenced(i)) <<
"array c, i = " << i;
}
diff --git a/lib/mesa/src/compiler/glsl/tests/meson.build b/lib/mesa/src/compiler/glsl/tests/meson.build
new file mode 100644
index 000000000..27f34075b
--- /dev/null
+++ b/lib/mesa/src/compiler/glsl/tests/meson.build
@@ -0,0 +1,76 @@
+# Copyright © 2017 Intel Corporation
+
+# 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 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.
+
+glsl_blob_test = executable(
+ 'blob_test',
+ 'blob_test.c',
+ c_args : [c_vis_args, c_msvc_compat_args, no_override_init_args],
+ include_directories : [inc_common, inc_compiler],
+ link_with : [libglsl],
+)
+
+glsl_cache_test = executable(
+ 'cache_test',
+ 'cache_test.c',
+ c_args : [c_vis_args, c_msvc_compat_args, no_override_init_args],
+ include_directories : [inc_common, inc_glsl],
+ link_with : [libglsl],
+ dependencies : [dep_clock, dep_thread],
+)
+
+glsl_general_ir_test = executable(
+ 'general_ir_test',
+ ['array_refcount_test.cpp', 'builtin_variable_test.cpp',
+ 'invalidate_locations_test.cpp', 'general_ir_test.cpp',
+ 'lower_int64_test.cpp', 'opt_add_neg_to_sub_test.cpp', 'varyings_test.cpp',
+ ir_expression_operation_h],
+ cpp_args : [cpp_vis_args, cpp_msvc_compat_args],
+ include_directories : [inc_common, inc_glsl],
+ link_with : [libglsl, libglsl_standalone, libglsl_util],
+ dependencies : [dep_clock, dep_thread, idep_gtest],
+)
+
+glsl_uniform_initializer_test = executable(
+ 'uniform_initializer_test',
+ ['copy_constant_to_storage_tests.cpp', 'set_uniform_initializer_tests.cpp',
+ 'uniform_initializer_utils.cpp', 'uniform_initializer_utils.h',
+ ir_expression_operation_h],
+ cpp_args : [cpp_vis_args, cpp_msvc_compat_args],
+ include_directories : [inc_common, inc_glsl],
+ link_with : [libglsl, libglsl_util],
+ dependencies : [dep_thread, idep_gtest],
+)
+
+glsl_sampler_types_test = executable(
+ 'sampler_types_test',
+ ['sampler_types_test.cpp', ir_expression_operation_h],
+ cpp_args : [cpp_vis_args, cpp_msvc_compat_args],
+ include_directories : [inc_common, inc_glsl],
+ link_with : [libglsl, libglsl_util],
+ dependencies : [dep_thread, idep_gtest],
+)
+
+test('blob_test', glsl_blob_test)
+test('cache_test', glsl_cache_test)
+test('general_ir_test', glsl_general_ir_test)
+test('uniform_initializer_test', glsl_uniform_initializer_test)
+test('sampler_types_test', glsl_sampler_types_test)
+
+# TODO: figure out how to get the shell based tests to work?
diff --git a/lib/mesa/src/compiler/nir/nir_linking_helpers.c b/lib/mesa/src/compiler/nir/nir_linking_helpers.c
new file mode 100644
index 000000000..54ba1c85e
--- /dev/null
+++ b/lib/mesa/src/compiler/nir/nir_linking_helpers.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * 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.h"
+#include "util/set.h"
+#include "util/hash_table.h"
+
+/* This file contains various little helpers for doing simple linking in
+ * NIR. Eventually, we'll probably want a full-blown varying packing
+ * implementation in here. Right now, it just deletes unused things.
+ */
+
+/**
+ * Returns the bits in the inputs_read, outputs_written, or
+ * system_values_read bitfield corresponding to this variable.
+ */
+static uint64_t
+get_variable_io_mask(nir_variable *var, gl_shader_stage stage)
+{
+ /* TODO: add support for tess patches */
+ if (var->data.patch || var->data.location < 0)
+ return 0;
+
+ assert(var->data.mode == nir_var_shader_in ||
+ var->data.mode == nir_var_shader_out ||
+ var->data.mode == nir_var_system_value);
+ assert(var->data.location >= 0);
+
+ const struct glsl_type *type = var->type;
+ if (nir_is_per_vertex_io(var, stage)) {
+ assert(glsl_type_is_array(type));
+ type = glsl_get_array_element(type);
+ }
+
+ unsigned slots = glsl_count_attribute_slots(type, false);
+ return ((1ull << slots) - 1) << var->data.location;
+}
+
+static void
+tcs_add_output_reads(nir_shader *shader, uint64_t *read)
+{
+ nir_foreach_function(function, shader) {
+ if (function->impl) {
+ nir_foreach_block(block, function->impl) {
+ nir_foreach_instr(instr, block) {
+ if (instr->type != nir_instr_type_intrinsic)
+ continue;
+
+ nir_intrinsic_instr *intrin_instr =
+ nir_instr_as_intrinsic(instr);
+ if (intrin_instr->intrinsic == nir_intrinsic_load_var &&
+ intrin_instr->variables[0]->var->data.mode ==
+ nir_var_shader_out) {
+
+ nir_variable *var = intrin_instr->variables[0]->var;
+ read[var->data.location_frac] |=
+ get_variable_io_mask(intrin_instr->variables[0]->var,
+ shader->info.stage);
+ }
+ }
+ }
+ }
+ }
+}
+
+static bool
+remove_unused_io_vars(nir_shader *shader, struct exec_list *var_list,
+ uint64_t *used_by_other_stage)
+{
+ bool progress = false;
+
+ nir_foreach_variable_safe(var, var_list) {
+ /* TODO: add patch support */
+ if (var->data.patch)
+ continue;
+
+ if (var->data.location < VARYING_SLOT_VAR0 && var->data.location >= 0)
+ continue;
+
+ if (var->data.always_active_io)
+ continue;
+
+ uint64_t other_stage = used_by_other_stage[var->data.location_frac];
+
+ if (!(other_stage & get_variable_io_mask(var, shader->info.stage))) {
+ /* This one is invalid, make it a global variable instead */
+ var->data.location = 0;
+ var->data.mode = nir_var_global;
+
+ exec_node_remove(&var->node);
+ exec_list_push_tail(&shader->globals, &var->node);
+
+ progress = true;
+ }
+ }
+
+ return progress;
+}
+
+bool
+nir_remove_unused_varyings(nir_shader *producer, nir_shader *consumer)
+{
+ assert(producer->info.stage != MESA_SHADER_FRAGMENT);
+ assert(consumer->info.stage != MESA_SHADER_VERTEX);
+
+ uint64_t read[4] = { 0 }, written[4] = { 0 };
+
+ nir_foreach_variable(var, &producer->outputs) {
+ written[var->data.location_frac] |=
+ get_variable_io_mask(var, producer->info.stage);
+ }
+
+ nir_foreach_variable(var, &consumer->inputs) {
+ read[var->data.location_frac] |=
+ get_variable_io_mask(var, consumer->info.stage);
+ }
+
+ /* Each TCS invocation can read data written by other TCS invocations,
+ * so even if the outputs are not used by the TES we must also make
+ * sure they are not read by the TCS before demoting them to globals.
+ */
+ if (producer->info.stage == MESA_SHADER_TESS_CTRL)
+ tcs_add_output_reads(producer, read);
+
+ bool progress = false;
+ progress = remove_unused_io_vars(producer, &producer->outputs, read);
+
+ progress =
+ remove_unused_io_vars(consumer, &consumer->inputs, written) || progress;
+
+ return progress;
+}
diff --git a/lib/mesa/src/compiler/nir/nir_lower_alpha_test.c b/lib/mesa/src/compiler/nir/nir_lower_alpha_test.c
new file mode 100644
index 000000000..6bf9ff142
--- /dev/null
+++ b/lib/mesa/src/compiler/nir/nir_lower_alpha_test.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2017 Broadcom
+ *
+ * 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.
+ */
+
+/**
+ * @file
+ *
+ * Implements GL alpha testing by comparing the output color's alpha to the
+ * alpha_ref intrinsic and emitting a discard based on it.
+ *
+ * The alpha_to_one value overrides the source alpha to 1.0 to implement
+ * GL_SAMPLE_ALPHA_TO_ONE, which applies before the alpha test (and would be
+ * rather silly to use with alpha test, but the spec permits).
+ */
+
+#include "nir/nir.h"
+#include "nir/nir_builder.h"
+
+void
+nir_lower_alpha_test(nir_shader *shader, enum compare_func func,
+ bool alpha_to_one)
+{
+ assert(shader->info.stage == MESA_SHADER_FRAGMENT);
+
+ nir_foreach_function(function, shader) {
+ nir_function_impl *impl = function->impl;
+ nir_builder b;
+ nir_builder_init(&b, impl);
+ b.cursor = nir_before_cf_list(&impl->body);
+
+ nir_foreach_block(block, impl) {
+ nir_foreach_instr_safe(instr, block) {
+ if (instr->type == nir_instr_type_intrinsic) {
+ nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+
+ nir_variable *out = NULL;
+
+ switch (intr->intrinsic) {
+ case nir_intrinsic_store_var:
+ out = intr->variables[0]->var;
+ break;
+ case nir_intrinsic_store_output:
+ /* already had i/o lowered.. lookup the matching output var: */
+ nir_foreach_variable(var, &shader->outputs) {
+ int drvloc = var->data.driver_location;
+ if (nir_intrinsic_base(intr) == drvloc) {
+ out = var;
+ break;
+ }
+ }
+ assume(out);
+ break;
+ default:
+ continue;
+ }
+
+ if (out->data.mode != nir_var_shader_out)
+ continue;
+
+ if (out->data.location != FRAG_RESULT_COLOR &&
+ out->data.location != FRAG_RESULT_DATA0)
+ continue;
+
+ b.cursor = nir_before_instr(&intr->instr);
+
+ nir_ssa_def *alpha;
+ if (alpha_to_one) {
+ alpha = nir_imm_float(&b, 1.0);
+ } else {
+ alpha = nir_channel(&b, nir_ssa_for_src(&b, intr->src[0], 4),
+ 3);
+ }
+
+ nir_ssa_def *condition =
+ nir_compare_func(&b, func,
+ alpha, nir_load_alpha_ref_float(&b));
+
+ nir_intrinsic_instr *discard =
+ nir_intrinsic_instr_create(b.shader,
+ nir_intrinsic_discard_if);
+ discard->num_components = 1;
+ discard->src[0] = nir_src_for_ssa(nir_inot(&b, condition));
+ nir_builder_instr_insert(&b, &discard->instr);
+ shader->info.fs.uses_discard = true;
+ }
+ }
+ }
+
+ nir_metadata_preserve(impl, nir_metadata_block_index |
+ nir_metadata_dominance);
+ }
+}
diff --git a/lib/mesa/src/compiler/nir/nir_lower_samplers_as_deref.c b/lib/mesa/src/compiler/nir/nir_lower_samplers_as_deref.c
new file mode 100644
index 000000000..bdbd8672f
--- /dev/null
+++ b/lib/mesa/src/compiler/nir/nir_lower_samplers_as_deref.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ * Copyright © 2014 Intel Corporation
+ * Copyright © 2017 Advanced Micro Devices, Inc.
+ *
+ * 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.
+ */
+
+/**
+ * \file
+ *
+ * Lower sampler and image references of (non-bindless) uniforms by removing
+ * struct dereferences, and synthesizing new uniform variables without structs
+ * if required.
+ *
+ * This will allow backends to have a simple, uniform treatment of bindless and
+ * non-bindless samplers and images.
+ *
+ * Example:
+ *
+ * struct S {
+ * sampler2D tex[2];
+ * sampler2D other;
+ * };
+ * uniform S s[2];
+ *
+ * tmp = texture(s[n].tex[m], coord);
+ *
+ * Becomes:
+ *
+ * decl_var uniform INTERP_MODE_NONE sampler2D[2][2] lower@s.tex (...)
+ *
+ * vec1 32 ssa_idx = $(2 * n + m)
+ * vec4 32 ssa_out = tex ssa_coord (coord), lower@s.tex[n][m] (texture), lower@s.tex[n][m] (sampler)
+ *
+ * and lower@s.tex has var->data.binding set to the base index as defined by
+ * the opaque uniform mapping.
+ */
+
+#include "nir.h"
+#include "nir_builder.h"
+#include "compiler/glsl/ir_uniform.h"
+
+#include "main/compiler.h"
+#include "main/mtypes.h"
+#include "program/prog_parameter.h"
+#include "program/program.h"
+
+struct lower_samplers_as_deref_state {
+ nir_shader *shader;
+ const struct gl_shader_program *shader_program;
+ struct hash_table *remap_table;
+};
+
+static void
+remove_struct_derefs(nir_deref *tail,
+ struct lower_samplers_as_deref_state *state,
+ nir_builder *b, char **path, unsigned *location)
+{
+ if (!tail->child)
+ return;
+
+ switch (tail->child->deref_type) {
+ case nir_deref_type_array: {
+ unsigned length = glsl_get_length(tail->type);
+
+ remove_struct_derefs(tail->child, state, b, path, location);
+
+ tail->type = glsl_get_array_instance(tail->child->type, length);
+ break;
+ }
+
+ case nir_deref_type_struct: {
+ nir_deref_struct *deref_struct = nir_deref_as_struct(tail->child);
+
+ *location += glsl_get_record_location_offset(tail->type, deref_struct->index);
+ ralloc_asprintf_append(path, ".%s",
+ glsl_get_struct_elem_name(tail->type, deref_struct->index));
+
+ remove_struct_derefs(tail->child, state, b, path, location);
+
+ /* Drop the struct deref and re-parent. */
+ ralloc_steal(tail, tail->child->child);
+ tail->type = tail->child->type;
+ tail->child = tail->child->child;
+ break;
+ }
+
+ default:
+ unreachable("Invalid deref type");
+ break;
+ }
+}
+
+static void
+lower_deref(nir_deref_var *deref,
+ struct lower_samplers_as_deref_state *state,
+ nir_builder *b)
+{
+ nir_variable *var = deref->var;
+ gl_shader_stage stage = state->shader->info.stage;
+ unsigned location = var->data.location;
+ unsigned binding;
+ const struct glsl_type *orig_type = deref->deref.type;
+ char *path;
+
+ assert(var->data.mode == nir_var_uniform);
+
+ path = ralloc_asprintf(state->remap_table, "lower@%s", var->name);
+ remove_struct_derefs(&deref->deref, state, b, &path, &location);
+
+ assert(location < state->shader_program->data->NumUniformStorage &&
+ state->shader_program->data->UniformStorage[location].opaque[stage].active);
+
+ binding = state->shader_program->data->UniformStorage[location].opaque[stage].index;
+
+ if (orig_type == deref->deref.type) {
+ /* Fast path: We did not encounter any struct derefs. */
+ var->data.binding = binding;
+ return;
+ }
+
+ uint32_t hash = _mesa_key_hash_string(path);
+ struct hash_entry *h =
+ _mesa_hash_table_search_pre_hashed(state->remap_table, hash, path);
+
+ if (h) {
+ var = (nir_variable *)h->data;
+ } else {
+ var = nir_variable_create(state->shader, nir_var_uniform, deref->deref.type, path);
+ var->data.binding = binding;
+ _mesa_hash_table_insert_pre_hashed(state->remap_table, hash, path, var);
+ }
+
+ deref->var = var;
+}
+
+static bool
+lower_sampler(nir_tex_instr *instr, struct lower_samplers_as_deref_state *state,
+ nir_builder *b)
+{
+ /* In GLSL, we only fill out the texture field. The sampler is inferred */
+ assert(instr->texture != NULL);
+ assert(instr->sampler == NULL);
+
+ b->cursor = nir_before_instr(&instr->instr);
+ lower_deref(instr->texture, state, b);
+
+ if (instr->op != nir_texop_txf_ms &&
+ instr->op != nir_texop_txf_ms_mcs &&
+ instr->op != nir_texop_samples_identical) {
+ nir_instr_rewrite_deref(&instr->instr, &instr->sampler,
+ nir_deref_var_clone(instr->texture, instr));
+ } else {
+ assert(!instr->sampler);
+ }
+
+ return true;
+}
+
+static bool
+lower_intrinsic(nir_intrinsic_instr *instr,
+ struct lower_samplers_as_deref_state *state,
+ nir_builder *b)
+{
+ if (instr->intrinsic == nir_intrinsic_image_load ||
+ instr->intrinsic == nir_intrinsic_image_store ||
+ instr->intrinsic == nir_intrinsic_image_atomic_add ||
+ instr->intrinsic == nir_intrinsic_image_atomic_min ||
+ instr->intrinsic == nir_intrinsic_image_atomic_max ||
+ instr->intrinsic == nir_intrinsic_image_atomic_and ||
+ instr->intrinsic == nir_intrinsic_image_atomic_or ||
+ instr->intrinsic == nir_intrinsic_image_atomic_xor ||
+ instr->intrinsic == nir_intrinsic_image_atomic_exchange ||
+ instr->intrinsic == nir_intrinsic_image_atomic_comp_swap ||
+ instr->intrinsic == nir_intrinsic_image_size) {
+ b->cursor = nir_before_instr(&instr->instr);
+ lower_deref(instr->variables[0], state, b);
+ return true;
+ }
+
+ return false;
+}
+
+static bool
+lower_impl(nir_function_impl *impl, struct lower_samplers_as_deref_state *state)
+{
+ nir_builder b;
+ nir_builder_init(&b, impl);
+ bool progress = false;
+
+ nir_foreach_block(block, impl) {
+ nir_foreach_instr(instr, block) {
+ if (instr->type == nir_instr_type_tex)
+ progress |= lower_sampler(nir_instr_as_tex(instr), state, &b);
+ else if (instr->type == nir_instr_type_intrinsic)
+ progress |= lower_intrinsic(nir_instr_as_intrinsic(instr), state, &b);
+ }
+ }
+
+ return progress;
+}
+
+bool
+nir_lower_samplers_as_deref(nir_shader *shader,
+ const struct gl_shader_program *shader_program)
+{
+ bool progress = false;
+ struct lower_samplers_as_deref_state state;
+
+ state.shader = shader;
+ state.shader_program = shader_program;
+ state.remap_table = _mesa_hash_table_create(NULL, _mesa_key_hash_string,
+ _mesa_key_string_equal);
+
+ nir_foreach_function(function, shader) {
+ if (function->impl)
+ progress |= lower_impl(function->impl, &state);
+ }
+
+ /* keys are freed automatically by ralloc */
+ _mesa_hash_table_destroy(state.remap_table, NULL);
+
+ return progress;
+}
diff --git a/lib/mesa/src/compiler/nir/nir_lower_uniforms_to_ubo.c b/lib/mesa/src/compiler/nir/nir_lower_uniforms_to_ubo.c
new file mode 100644
index 000000000..15bf0d985
--- /dev/null
+++ b/lib/mesa/src/compiler/nir/nir_lower_uniforms_to_ubo.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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.
+ */
+
+/*
+ * Remap load_uniform intrinsics to UBO accesses of UBO binding point 0. Both
+ * the base and the offset are interpreted as 16-byte units.
+ *
+ * Simultaneously, remap existing UBO accesses by increasing their binding
+ * point by 1.
+ */
+
+#include "nir.h"
+#include "nir_builder.h"
+
+static bool
+lower_instr(nir_intrinsic_instr *instr, nir_builder *b)
+{
+ b->cursor = nir_before_instr(&instr->instr);
+
+ if (instr->intrinsic == nir_intrinsic_load_ubo) {
+ nir_ssa_def *old_idx = nir_ssa_for_src(b, instr->src[0], 1);
+ nir_ssa_def *new_idx = nir_iadd(b, old_idx, nir_imm_int(b, 1));
+ nir_instr_rewrite_src(&instr->instr, &instr->src[0],
+ nir_src_for_ssa(new_idx));
+ return true;
+ }
+
+ if (instr->intrinsic == nir_intrinsic_load_uniform) {
+ nir_ssa_def *ubo_idx = nir_imm_int(b, 0);
+ nir_ssa_def *ubo_offset =
+ nir_imul(b, nir_imm_int(b, 16),
+ nir_iadd(b, nir_imm_int(b, nir_intrinsic_base(instr)),
+ nir_ssa_for_src(b, instr->src[0], 1)));
+
+ nir_intrinsic_instr *load =
+ nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_ubo);
+ load->num_components = instr->num_components;
+ load->src[0] = nir_src_for_ssa(ubo_idx);
+ load->src[1] = nir_src_for_ssa(ubo_offset);
+ nir_ssa_dest_init(&load->instr, &load->dest,
+ load->num_components, instr->dest.ssa.bit_size,
+ instr->dest.ssa.name);
+ nir_builder_instr_insert(b, &load->instr);
+ nir_ssa_def_rewrite_uses(&instr->dest.ssa, nir_src_for_ssa(&load->dest.ssa));
+
+ nir_instr_remove(&instr->instr);
+ return true;
+ }
+
+ return false;
+}
+
+bool
+nir_lower_uniforms_to_ubo(nir_shader *shader)
+{
+ bool progress = false;
+
+ nir_foreach_function(function, shader) {
+ if (function->impl) {
+ nir_builder builder;
+ nir_builder_init(&builder, function->impl);
+ nir_foreach_block(block, function->impl) {
+ nir_foreach_instr_safe(instr, block) {
+ if (instr->type == nir_instr_type_intrinsic)
+ progress |= lower_instr(nir_instr_as_intrinsic(instr),
+ &builder);
+ }
+ }
+
+ nir_metadata_preserve(function->impl, nir_metadata_block_index |
+ nir_metadata_dominance);
+ }
+ }
+
+ return progress;
+}
+
diff --git a/lib/mesa/src/compiler/nir/nir_lower_vec_to_movs.c b/lib/mesa/src/compiler/nir/nir_lower_vec_to_movs.c
index 711ddd38b..8b24376b0 100644
--- a/lib/mesa/src/compiler/nir/nir_lower_vec_to_movs.c
+++ b/lib/mesa/src/compiler/nir/nir_lower_vec_to_movs.c
@@ -230,6 +230,7 @@ lower_vec_to_movs_block(nir_block *block, nir_function_impl *impl)
continue; /* The loop */
}
+ bool vec_had_ssa_dest = vec->dest.dest.is_ssa;
if (vec->dest.dest.is_ssa) {
/* Since we insert multiple MOVs, we have a register destination. */
nir_register *reg = nir_local_reg_create(impl);
@@ -263,7 +264,11 @@ lower_vec_to_movs_block(nir_block *block, nir_function_impl *impl)
if (!(vec->dest.write_mask & (1 << i)))
continue;
- if (!(finished_write_mask & (1 << i)))
+ /* Coalescing moves the register writes from the vec up to the ALU
+ * instruction in the source. We can only do this if the original
+ * vecN had an SSA destination.
+ */
+ if (vec_had_ssa_dest && !(finished_write_mask & (1 << i)))
finished_write_mask |= try_coalesce(vec, i);
if (!(finished_write_mask & (1 << i)))
diff --git a/lib/mesa/src/mapi/glapi/gen/ARB_clear_buffer_object.xml b/lib/mesa/src/mapi/glapi/gen/ARB_clear_buffer_object.xml
index 2284eacd6..25a42b3a4 100644
--- a/lib/mesa/src/mapi/glapi/gen/ARB_clear_buffer_object.xml
+++ b/lib/mesa/src/mapi/glapi/gen/ARB_clear_buffer_object.xml
@@ -8,7 +8,7 @@
<category name="GL_ARB_clear_buffer_object" number="121">
- <function name ="ClearBufferData">
+ <function name ="ClearBufferData" no_error="true">
<param name="target" type="GLenum"/>
<param name="internalformat" type="GLenum"/>
<param name="format" type="GLenum"/>
@@ -16,7 +16,7 @@
<param name="data" type="const GLvoid *"/>
</function>
- <function name ="ClearBufferSubData">
+ <function name ="ClearBufferSubData" no_error="true">
<param name="target" type="GLenum"/>
<param name="internalformat" type="GLenum"/>
<param name="offset" type="GLintptr"/>
diff --git a/lib/mesa/src/mapi/glapi/gen/ARB_get_program_binary.xml b/lib/mesa/src/mapi/glapi/gen/ARB_get_program_binary.xml
index 25e0a37c8..c521c04de 100644
--- a/lib/mesa/src/mapi/glapi/gen/ARB_get_program_binary.xml
+++ b/lib/mesa/src/mapi/glapi/gen/ARB_get_program_binary.xml
@@ -26,7 +26,7 @@
<param name="length" type="GLsizei"/>
</function>
- <function name="ProgramParameteri" es2="3.0">
+ <function name="ProgramParameteri" es2="3.0" no_error="true">
<param name="program" type="GLuint"/>
<param name="pname" type="GLenum"/>
<param name="value" type="GLint"/>
diff --git a/lib/mesa/src/mapi/glapi/gen/ARB_robustness.xml b/lib/mesa/src/mapi/glapi/gen/ARB_robustness.xml
index 9b2f2f0a7..1f6ac4696 100644
--- a/lib/mesa/src/mapi/glapi/gen/ARB_robustness.xml
+++ b/lib/mesa/src/mapi/glapi/gen/ARB_robustness.xml
@@ -82,7 +82,7 @@
<param name="img" type="GLvoid *" output="true"/>
</function>
- <function name="ReadnPixelsARB">
+ <function name="ReadnPixelsARB" no_error="true">
<param name="x" type="GLint"/>
<param name="y" type="GLint"/>
<param name="width" type="GLsizei"/>
diff --git a/lib/mesa/src/mapi/glapi/gen/ARB_tessellation_shader.xml b/lib/mesa/src/mapi/glapi/gen/ARB_tessellation_shader.xml
index e26f227b6..d0b03750e 100644
--- a/lib/mesa/src/mapi/glapi/gen/ARB_tessellation_shader.xml
+++ b/lib/mesa/src/mapi/glapi/gen/ARB_tessellation_shader.xml
@@ -50,7 +50,7 @@
<enum value="0x8E8A" name="MAX_TESS_EVALUATION_UNIFORM_BLOCKS"/>
<enum value="0x8221" name="PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED"/>
- <function name="PatchParameteri" es2="3.2">
+ <function name="PatchParameteri" es2="3.2" no_error="true">
<param name="pname" type="GLenum"/>
<param name="value" type="GLint"/>
</function>
diff --git a/lib/mesa/src/mapi/glapi/gen/ARB_texture_multisample.xml b/lib/mesa/src/mapi/glapi/gen/ARB_texture_multisample.xml
index 595e1c7ea..0040c5398 100644
--- a/lib/mesa/src/mapi/glapi/gen/ARB_texture_multisample.xml
+++ b/lib/mesa/src/mapi/glapi/gen/ARB_texture_multisample.xml
@@ -59,7 +59,7 @@
<param name="val" type="GLfloat *"/>
</function>
- <function name="SampleMaski" es2="3.1">
+ <function name="SampleMaski" es2="3.1" no_error="true">
<param name="index" type="GLuint"/>
<param name="mask" type="GLbitfield"/>
</function>
diff --git a/lib/mesa/src/mapi/glapi/gen/ARB_texture_storage.xml b/lib/mesa/src/mapi/glapi/gen/ARB_texture_storage.xml
index 7df394241..4dbab3947 100644
--- a/lib/mesa/src/mapi/glapi/gen/ARB_texture_storage.xml
+++ b/lib/mesa/src/mapi/glapi/gen/ARB_texture_storage.xml
@@ -10,14 +10,14 @@
<enum name="TEXTURE_IMMUTABLE_FORMAT" value="0x912F"/>
- <function name="TexStorage1D">
+ <function name="TexStorage1D" no_error="true">
<param name="target" type="GLenum"/>
<param name="levels" type="GLsizei"/>
<param name="internalFormat" type="GLenum"/>
<param name="width" type="GLsizei"/>
</function>
- <function name="TexStorage2D" es2="3.0">
+ <function name="TexStorage2D" es2="3.0" no_error="true">
<param name="target" type="GLenum"/>
<param name="levels" type="GLsizei"/>
<param name="internalFormat" type="GLenum"/>
@@ -25,7 +25,7 @@
<param name="height" type="GLsizei"/>
</function>
- <function name="TexStorage3D" es2="3.0">
+ <function name="TexStorage3D" es2="3.0" no_error="true">
<param name="target" type="GLenum"/>
<param name="levels" type="GLsizei"/>
<param name="internalFormat" type="GLenum"/>
diff --git a/lib/mesa/src/mapi/glapi/gen/ARB_texture_view.xml b/lib/mesa/src/mapi/glapi/gen/ARB_texture_view.xml
index 4215fc5bd..0c20ef97d 100644
--- a/lib/mesa/src/mapi/glapi/gen/ARB_texture_view.xml
+++ b/lib/mesa/src/mapi/glapi/gen/ARB_texture_view.xml
@@ -7,7 +7,7 @@
<category name="GL_ARB_texture_view" number="124">
- <function name="TextureView">
+ <function name="TextureView" no_error="true">
<param name="texture" type="GLuint"/>
<param name="target" type="GLenum"/>
<param name="origtexture" type="GLuint"/>
diff --git a/lib/mesa/src/mapi/glapi/gen/EXT_external_objects.xml b/lib/mesa/src/mapi/glapi/gen/EXT_external_objects.xml
new file mode 100644
index 000000000..25e6879ec
--- /dev/null
+++ b/lib/mesa/src/mapi/glapi/gen/EXT_external_objects.xml
@@ -0,0 +1,234 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<!-- Note: no GLX protocol info yet. -->
+
+
+<OpenGLAPI>
+
+<category name="EXT_external_objects" number="503">
+
+ <enum name="TEXTURE_TILING_EXT" value="0x9580"/>
+ <enum name="DEDICATED_MEMORY_OBJECT_EXT" value="0x9581"/>
+ <enum name="PROTECTED_MEMORY_OBJECT_EXT" value="0x959B"/>
+ <enum name="NUM_TILING_TYPES_EXT" value="0x9582"/>
+ <enum name="TILING_TYPES_EXT" value="0x9583"/>
+ <enum name="OPTIMAL_TILING_EXT" value="0x9584"/>
+ <enum name="LINEAR_TILING_EXT" value="0x9585"/>
+ <enum name="NUM_DEVICE_UUIDS_EXT" value="0x9596"/>
+ <enum name="DEVICE_UUID_EXT" value="0x9597"/>
+ <enum name="DRIVER_UUID_EXT" value="0x9598"/>
+ <enum name="LAYOUT_GENERAL_EXT" value="0x958D"/>
+ <enum name="LAYOUT_COLOR_ATTACHMENT_EXT" value="0x958E"/>
+ <enum name="LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT" value="0x958F"/>
+ <enum name="LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT" value="0x9590"/>
+ <enum name="LAYOUT_SHADER_READ_ONLY_EXT" value="0x9591"/>
+ <enum name="LAYOUT_TRANSFER_SRC_EXT" value="0x9592"/>
+ <enum name="LAYOUT_TRANSFER_DST_EXT" value="0x9593"/>
+
+ <function name="GetUnsignedBytevEXT" es2="3.2">
+ <param name="pname" type="GLenum"/>
+ <param name="data" type="GLubyte *"/>
+ </function>
+
+ <function name="GetUnsignedBytei_vEXT" es2="3.2">
+ <param name="target" type="GLenum"/>
+ <param name="index" type="GLuint"/>
+ <param name="data" type="GLubyte *"/>
+ </function>
+
+ <function name="DeleteMemoryObjectsEXT" es2="3.2">
+ <param name="n" type="GLsizei"/>
+ <param name="memoryObjects" type="const GLuint *"/>
+ </function>
+
+ <function name="IsMemoryObjectEXT" es2="3.2">
+ <param name="memoryObject" type="GLuint"/>
+ <return type="GLboolean"/>
+ </function>
+
+ <function name="CreateMemoryObjectsEXT" es2="3.2">
+ <param name="n" type="GLsizei"/>
+ <param name="memoryObjects" type="GLuint *"/>
+ </function>
+
+ <function name="MemoryObjectParameterivEXT" es2="3.2">
+ <param name="memoryObject" type="GLuint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLint *"/>
+ </function>
+
+ <function name="GetMemoryObjectParameterivEXT" es2="3.2">
+ <param name="memoryObject" type="GLuint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *"/>
+ </function>
+
+ <function name="TexStorageMem2DEXT" es2="3.2">
+ <param name="target" type="GLenum"/>
+ <param name="levels" type="GLsizei"/>
+ <param name="internalFormat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="memory" type="GLuint"/>
+ <param name="offset" type="GLuint64"/>
+ </function>
+
+ <function name="TexStorageMem2DMultisampleEXT" es2="3.2">
+ <param name="target" type="GLenum"/>
+ <param name="samples" type="GLsizei"/>
+ <param name="internalFormat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="fixedSampleLocations" type="GLboolean"/>
+ <param name="memory" type="GLuint"/>
+ <param name="offset" type="GLuint64"/>
+ </function>
+
+ <function name="TexStorageMem3DEXT" es2="3.2">
+ <param name="target" type="GLenum"/>
+ <param name="levels" type="GLsizei"/>
+ <param name="internalFormat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="memory" type="GLuint"/>
+ <param name="offset" type="GLuint64"/>
+ </function>
+
+ <function name="TexStorageMem3DMultisampleEXT" es2="3.2">
+ <param name="target" type="GLenum"/>
+ <param name="samples" type="GLsizei"/>
+ <param name="internalFormat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="fixedSampleLocations" type="GLboolean"/>
+ <param name="memory" type="GLuint"/>
+ <param name="offset" type="GLuint64"/>
+ </function>
+
+ <function name="BufferStorageMemEXT" es2="3.2" no_error="true">
+ <param name="target" type="GLenum"/>
+ <param name="size" type="GLsizeiptr"/>
+ <param name="memory" type="GLuint"/>
+ <param name="offset" type="GLuint64"/>
+ </function>
+
+ <function name="TextureStorageMem2DEXT" es2="3.2">
+ <param name="texture" type="GLenum"/>
+ <param name="levels" type="GLsizei"/>
+ <param name="internalFormat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="memory" type="GLuint"/>
+ <param name="offset" type="GLuint64"/>
+ </function>
+
+ <function name="TextureStorageMem2DMultisampleEXT" es2="3.2">
+ <param name="texture" type="GLuint"/>
+ <param name="samples" type="GLsizei"/>
+ <param name="internalFormat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="fixedSampleLocations" type="GLboolean"/>
+ <param name="memory" type="GLuint"/>
+ <param name="offset" type="GLuint64"/>
+ </function>
+
+ <function name="TextureStorageMem3DEXT" es2="3.2">
+ <param name="texture" type="GLuint"/>
+ <param name="levels" type="GLsizei"/>
+ <param name="internalFormat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="memory" type="GLuint"/>
+ <param name="offset" type="GLuint64"/>
+ </function>
+
+ <function name="TextureStorageMem3DMultisampleEXT" es2="3.2">
+ <param name="texture" type="GLuint"/>
+ <param name="samples" type="GLsizei"/>
+ <param name="internalFormat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="height" type="GLsizei"/>
+ <param name="depth" type="GLsizei"/>
+ <param name="fixedSampleLocations" type="GLboolean"/>
+ <param name="memory" type="GLuint"/>
+ <param name="offset" type="GLuint64"/>
+ </function>
+
+ <function name="NamedBufferStorageMemEXT" es2="3.2" no_error="true">
+ <param name="buffer" type="GLuint"/>
+ <param name="size" type="GLsizeiptr"/>
+ <param name="memory" type="GLuint"/>
+ <param name="offset" type="GLuint64"/>
+ </function>
+
+ <function name="TexStorageMem1DEXT">
+ <param name="target" type="GLenum"/>
+ <param name="levels" type="GLsizei"/>
+ <param name="internalFormat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="memory" type="GLuint"/>
+ <param name="offset" type="GLuint64"/>
+ </function>
+
+ <function name="TextureStorageMem1DEXT">
+ <param name="texture" type="GLuint"/>
+ <param name="levels" type="GLsizei"/>
+ <param name="internalFormat" type="GLenum"/>
+ <param name="width" type="GLsizei"/>
+ <param name="memory" type="GLuint"/>
+ <param name="offset" type="GLuint64"/>
+ </function>
+
+ <function name="GenSemaphoresEXT" es2="3.2">
+ <param name="n" type="GLsizei"/>
+ <param name="semaphores" type="GLuint *"/>
+ </function>
+
+ <function name="DeleteSemaphoresEXT" es2="3.2">
+ <param name="n" type="GLsizei"/>
+ <param name="semaphores" type="const GLuint *"/>
+ </function>
+
+ <function name="IsSemaphoreEXT" es2="3.2">
+ <param name="semaphore" type="GLuint"/>
+ <return type="GLboolean"/>
+ </function>
+
+ <function name="SemaphoreParameterui64vEXT" es2="3.2">
+ <param name="semaphore" type="GLuint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="const GLuint64 *"/>
+ </function>
+
+ <function name="GetSemaphoreParameterui64vEXT" es2="3.2">
+ <param name="semaphore" type="GLuint"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLuint64 *"/>
+ </function>
+
+ <function name="WaitSemaphoreEXT" es2="3.2">
+ <param name="semaphore" type="GLuint"/>
+ <param name="numBufferBarriers" type="GLuint"/>
+ <param name="buffers" type="const GLuint *"/>
+ <param name="numTextureBarriers" type="GLuint"/>
+ <param name="textures" type="const GLuint *"/>
+ <param name="srcLayouts" type="const GLenum *"/>
+ </function>
+
+ <function name="SignalSemaphoreEXT" es2="3.2">
+ <param name="semaphore" type="GLuint"/>
+ <param name="numBufferBarriers" type="GLuint"/>
+ <param name="buffers" type="const GLuint *"/>
+ <param name="numTextureBarriers" type="GLuint"/>
+ <param name="textures" type="const GLuint *"/>
+ <param name="dstLayouts" type="const GLenum *"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/lib/mesa/src/mapi/glapi/gen/EXT_external_objects_fd.xml b/lib/mesa/src/mapi/glapi/gen/EXT_external_objects_fd.xml
new file mode 100644
index 000000000..6eaa3f5b0
--- /dev/null
+++ b/lib/mesa/src/mapi/glapi/gen/EXT_external_objects_fd.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<!-- Note: no GLX protocol info yet. -->
+
+
+<OpenGLAPI>
+
+<category name="EXT_external_objects_fd" number="504">
+
+ <enum name="HANDLE_TYPE_OPAQUE_FD_EXT" value="0x9586"/>
+
+ <function name="ImportMemoryFdEXT" es2="3.2">
+ <param name="memory" type="GLuint"/>
+ <param name="size" type="GLuint64"/>
+ <param name="handleType" type="GLenum"/>
+ <param name="fd" type="GLint"/>
+ </function>
+
+ <function name="ImportSemaphoreFdEXT" es2="3.2">
+ <param name="semaphore" type="GLuint"/>
+ <param name="handleType" type="GLenum"/>
+ <param name="fd" type="GLint"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/lib/mesa/src/mapi/glapi/gen/GL4x.xml b/lib/mesa/src/mapi/glapi/gen/GL4x.xml
index 53b77896c..512addc2b 100644
--- a/lib/mesa/src/mapi/glapi/gen/GL4x.xml
+++ b/lib/mesa/src/mapi/glapi/gen/GL4x.xml
@@ -9,7 +9,7 @@
<enum name="SAMPLE_SHADING" value="0x8C36"/>
<enum name="MIN_SAMPLE_SHADING_VALUE" value="0x8C37"/>
- <function name="MinSampleShading" es2="3.2">
+ <function name="MinSampleShading" es2="3.2" no_error="true">
<param name="value" type="GLfloat"/>
</function>
@@ -42,6 +42,7 @@
<category name="4.3">
<enum name="SHADER_STORAGE_BARRIER_BIT" value="0x2000" />
+ <enum name="NUM_SHADING_LANGUAGE_VERSIONS" value="0x82E9" />
<enum name="MAX_COMBINED_SHADER_OUTPUT_RESOURCES" value="0x8F39" />
<enum name="SHADER_STORAGE_BUFFER" value="0x90D2"/>
<enum name="SHADER_STORAGE_BUFFER_BINDING" value="0x90D3"/>
@@ -61,9 +62,18 @@
</category>
<category name="4.5">
- <function name="MemoryBarrierByRegion" es2="3.1">
+ <function name="MemoryBarrierByRegion" es2="3.1" no_error="true">
<param name="barriers" type="GLbitfield"/>
</function>
</category>
+<category name="4.6">
+ <function name="PolygonOffsetClamp" alias="PolygonOffsetClampEXT">
+ <param name="factor" type="GLfloat"/>
+ <param name="units" type="GLfloat"/>
+ <param name="clamp" type="GLfloat"/>
+ </function>
+ <enum name="POLYGON_OFFSET_CLAMP" value="0x8E1B"/>
+</category>
+
</OpenGLAPI>
diff --git a/lib/mesa/src/mapi/glapi/gen/MESA_tile_raster_order.xml b/lib/mesa/src/mapi/glapi/gen/MESA_tile_raster_order.xml
new file mode 100644
index 000000000..7cc73ca4b
--- /dev/null
+++ b/lib/mesa/src/mapi/glapi/gen/MESA_tile_raster_order.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_MESA_tile_rasterizer_order" number="515">
+ <enum name="TILE_RASTER_ORDER_FIXED_MESA" value="0x8BB8"/>
+ <enum name="TILE_RASTER_ORDER_INCREASING_X_MESA" value="0x8BB9"/>
+ <enum name="TILE_RASTER_ORDER_INCREASING_Y_MESA" value="0x8BBA"/>
+</category>
+
+</OpenGLAPI>
diff --git a/lib/mesa/src/mapi/glapi/glapi.h b/lib/mesa/src/mapi/glapi/glapi.h
index f1ad4c1b5..d5d4e0a03 100644
--- a/lib/mesa/src/mapi/glapi/glapi.h
+++ b/lib/mesa/src/mapi/glapi/glapi.h
@@ -161,6 +161,9 @@ _glapi_get_proc_name(unsigned int offset);
#if defined(GLX_USE_APPLEGL) || defined(GLX_USE_WINDOWSGL)
_GLAPI_EXPORT struct _glapi_table *
_glapi_create_table_from_handle(void *handle, const char *symbol_prefix);
+
+_GLAPI_EXPORT void
+_glapi_table_patch(struct _glapi_table *, const char *name, void *wrapper);
#endif
diff --git a/lib/mesa/src/mapi/glapi/tests/check_table.cpp b/lib/mesa/src/mapi/glapi/tests/check_table.cpp
index 09bf4f358..f23f00be5 100644
--- a/lib/mesa/src/mapi/glapi/tests/check_table.cpp
+++ b/lib/mesa/src/mapi/glapi/tests/check_table.cpp
@@ -24,10 +24,8 @@
#include <gtest/gtest.h>
#include "../mesa/main/glheader.h"
-extern "C" {
#include "glapi/glapi.h"
#include "glapi/glapitable.h"
-}
struct name_offset {
const char *name;
@@ -1404,9 +1402,7 @@ const struct name_offset known_dispatch[] = {
{ "glPointParameteri", _O(PointParameteri) },
{ "glPointParameteriv", _O(PointParameteriv) },
{ "glActiveStencilFaceEXT", _O(ActiveStencilFaceEXT) },
- { "glBindVertexArrayAPPLE", _O(BindVertexArrayAPPLE) },
{ "glDeleteVertexArrays", _O(DeleteVertexArrays) },
- { "glGenVertexArraysAPPLE", _O(GenVertexArraysAPPLE) },
{ "glIsVertexArray", _O(IsVertexArray) },
{ "glGetProgramNamedParameterdvNV", _O(GetProgramNamedParameterdvNV) },
{ "glGetProgramNamedParameterfvNV", _O(GetProgramNamedParameterfvNV) },
diff --git a/lib/mesa/src/mapi/shared-glapi/tests/check_table.cpp b/lib/mesa/src/mapi/shared-glapi/tests/check_table.cpp
index 02d313c22..314e6769b 100644
--- a/lib/mesa/src/mapi/shared-glapi/tests/check_table.cpp
+++ b/lib/mesa/src/mapi/shared-glapi/tests/check_table.cpp
@@ -25,7 +25,7 @@
#include "../../../mesa/main/glheader.h"
#include "glapi/glapi.h"
-#include "glapi/glapitable.h"
+#include "glapitable.h"
struct name_offset {
const char *name;
diff --git a/lib/mesa/src/mesa/drivers/dri/i915/intel_screen.h b/lib/mesa/src/mesa/drivers/dri/i915/intel_screen.h
index 11e1a3fa3..a22888b39 100644
--- a/lib/mesa/src/mesa/drivers/dri/i915/intel_screen.h
+++ b/lib/mesa/src/mesa/drivers/dri/i915/intel_screen.h
@@ -33,7 +33,7 @@
#include "dri_util.h"
#include "intel_bufmgr.h"
#include "i915_drm.h"
-#include "xmlconfig.h"
+#include "util/xmlconfig.h"
struct intel_screen
{
diff --git a/lib/mesa/src/mesa/drivers/dri/i965/brw_pipe_control.h b/lib/mesa/src/mesa/drivers/dri/i965/brw_pipe_control.h
new file mode 100644
index 000000000..6e9a40487
--- /dev/null
+++ b/lib/mesa/src/mesa/drivers/dri/i965/brw_pipe_control.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2017 Intel Corporation
+ *
+ * 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.
+ */
+
+#ifndef BRW_PIPE_CONTROL_DOT_H
+#define BRW_PIPE_CONTROL_DOT_H
+
+struct brw_context;
+struct gen_device_info;
+struct brw_bo;
+
+/** @{
+ *
+ * PIPE_CONTROL operation, a combination MI_FLUSH and register write with
+ * additional flushing control.
+ */
+#define _3DSTATE_PIPE_CONTROL (CMD_3D | (3 << 27) | (2 << 24))
+#define PIPE_CONTROL_CS_STALL (1 << 20)
+#define PIPE_CONTROL_GLOBAL_SNAPSHOT_COUNT_RESET (1 << 19)
+#define PIPE_CONTROL_TLB_INVALIDATE (1 << 18)
+#define PIPE_CONTROL_SYNC_GFDT (1 << 17)
+#define PIPE_CONTROL_MEDIA_STATE_CLEAR (1 << 16)
+#define PIPE_CONTROL_NO_WRITE (0 << 14)
+#define PIPE_CONTROL_WRITE_IMMEDIATE (1 << 14)
+#define PIPE_CONTROL_WRITE_DEPTH_COUNT (2 << 14)
+#define PIPE_CONTROL_WRITE_TIMESTAMP (3 << 14)
+#define PIPE_CONTROL_DEPTH_STALL (1 << 13)
+#define PIPE_CONTROL_RENDER_TARGET_FLUSH (1 << 12)
+#define PIPE_CONTROL_INSTRUCTION_INVALIDATE (1 << 11)
+#define PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE (1 << 10) /* GM45+ only */
+#define PIPE_CONTROL_ISP_DIS (1 << 9)
+#define PIPE_CONTROL_INTERRUPT_ENABLE (1 << 8)
+#define PIPE_CONTROL_FLUSH_ENABLE (1 << 7) /* Gen7+ only */
+/* GT */
+#define PIPE_CONTROL_DATA_CACHE_FLUSH (1 << 5)
+#define PIPE_CONTROL_VF_CACHE_INVALIDATE (1 << 4)
+#define PIPE_CONTROL_CONST_CACHE_INVALIDATE (1 << 3)
+#define PIPE_CONTROL_STATE_CACHE_INVALIDATE (1 << 2)
+#define PIPE_CONTROL_STALL_AT_SCOREBOARD (1 << 1)
+#define PIPE_CONTROL_DEPTH_CACHE_FLUSH (1 << 0)
+#define PIPE_CONTROL_PPGTT_WRITE (0 << 2)
+#define PIPE_CONTROL_GLOBAL_GTT_WRITE (1 << 2)
+
+#define PIPE_CONTROL_CACHE_FLUSH_BITS \
+ (PIPE_CONTROL_DEPTH_CACHE_FLUSH | PIPE_CONTROL_DATA_CACHE_FLUSH | \
+ PIPE_CONTROL_RENDER_TARGET_FLUSH)
+
+#define PIPE_CONTROL_CACHE_INVALIDATE_BITS \
+ (PIPE_CONTROL_STATE_CACHE_INVALIDATE | PIPE_CONTROL_CONST_CACHE_INVALIDATE | \
+ PIPE_CONTROL_VF_CACHE_INVALIDATE | PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | \
+ PIPE_CONTROL_INSTRUCTION_INVALIDATE)
+
+/** @} */
+
+int brw_init_pipe_control(struct brw_context *brw,
+ const struct gen_device_info *info);
+void brw_fini_pipe_control(struct brw_context *brw);
+
+void brw_emit_pipe_control_flush(struct brw_context *brw, uint32_t flags);
+void brw_emit_pipe_control_write(struct brw_context *brw, uint32_t flags,
+ struct brw_bo *bo, uint32_t offset,
+ uint64_t imm);
+void brw_emit_end_of_pipe_sync(struct brw_context *brw, uint32_t flags);
+void brw_emit_mi_flush(struct brw_context *brw);
+void brw_emit_post_sync_nonzero_flush(struct brw_context *brw);
+void brw_emit_depth_stall_flushes(struct brw_context *brw);
+void gen7_emit_vs_workaround_flush(struct brw_context *brw);
+void gen7_emit_cs_stall_flush(struct brw_context *brw);
+
+#endif
diff --git a/lib/mesa/src/mesa/drivers/dri/i965/hsw_sol.c b/lib/mesa/src/mesa/drivers/dri/i965/hsw_sol.c
index b0dd150b7..f84063ded 100644
--- a/lib/mesa/src/mesa/drivers/dri/i965/hsw_sol.c
+++ b/lib/mesa/src/mesa/drivers/dri/i965/hsw_sol.c
@@ -92,14 +92,10 @@ tally_prims_written(struct brw_context *brw,
/* GPR0 = Tally */
brw_load_register_imm32(brw, HSW_CS_GPR(0) + 4, 0);
brw_load_register_mem(brw, HSW_CS_GPR(0), obj->prim_count_bo,
- I915_GEM_DOMAIN_INSTRUCTION,
- I915_GEM_DOMAIN_INSTRUCTION,
TALLY_OFFSET + i * sizeof(uint32_t));
if (!obj->base.Paused) {
/* GPR1 = Start Snapshot */
brw_load_register_mem64(brw, HSW_CS_GPR(1), obj->prim_count_bo,
- I915_GEM_DOMAIN_INSTRUCTION,
- I915_GEM_DOMAIN_INSTRUCTION,
START_OFFSET + i * sizeof(uint64_t));
/* GPR2 = Ending Snapshot */
brw_load_register_reg64(brw, GEN7_SO_NUM_PRIMS_WRITTEN(i), HSW_CS_GPR(2));
@@ -165,11 +161,12 @@ hsw_begin_transform_feedback(struct gl_context *ctx, GLenum mode,
struct brw_context *brw = brw_context(ctx);
struct brw_transform_feedback_object *brw_obj =
(struct brw_transform_feedback_object *) obj;
+ const struct gen_device_info *devinfo = &brw->screen->devinfo;
brw_obj->primitive_mode = mode;
/* Reset the SO buffer offsets to 0. */
- if (brw->gen >= 8) {
+ if (devinfo->gen >= 8) {
brw_obj->zero_offsets = true;
} else {
BEGIN_BATCH(1 + 2 * BRW_MAX_XFB_STREAMS);
@@ -199,8 +196,9 @@ hsw_pause_transform_feedback(struct gl_context *ctx,
struct brw_context *brw = brw_context(ctx);
struct brw_transform_feedback_object *brw_obj =
(struct brw_transform_feedback_object *) obj;
+ const struct gen_device_info *devinfo = &brw->screen->devinfo;
- if (brw->is_haswell) {
+ if (devinfo->is_haswell) {
/* Flush any drawing so that the counters have the right values. */
brw_emit_mi_flush(brw);
@@ -209,9 +207,7 @@ hsw_pause_transform_feedback(struct gl_context *ctx,
BEGIN_BATCH(3);
OUT_BATCH(MI_STORE_REGISTER_MEM | (3 - 2));
OUT_BATCH(GEN7_SO_WRITE_OFFSET(i));
- OUT_RELOC(brw_obj->offset_bo,
- I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
- i * sizeof(uint32_t));
+ OUT_RELOC(brw_obj->offset_bo, RELOC_WRITE, i * sizeof(uint32_t));
ADVANCE_BATCH();
}
}
@@ -230,16 +226,15 @@ hsw_resume_transform_feedback(struct gl_context *ctx,
struct brw_context *brw = brw_context(ctx);
struct brw_transform_feedback_object *brw_obj =
(struct brw_transform_feedback_object *) obj;
+ const struct gen_device_info *devinfo = &brw->screen->devinfo;
- if (brw->is_haswell) {
+ if (devinfo->is_haswell) {
/* Reload the SOL buffer offset registers. */
for (int i = 0; i < BRW_MAX_XFB_STREAMS; i++) {
BEGIN_BATCH(3);
OUT_BATCH(GEN7_MI_LOAD_REGISTER_MEM | (3 - 2));
OUT_BATCH(GEN7_SO_WRITE_OFFSET(i));
- OUT_RELOC(brw_obj->offset_bo,
- I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
- i * sizeof(uint32_t));
+ OUT_RELOC(brw_obj->offset_bo, RELOC_WRITE, i * sizeof(uint32_t));
ADVANCE_BATCH();
}
}
diff --git a/lib/mesa/src/mesa/drivers/dri/i965/intel_tex.h b/lib/mesa/src/mesa/drivers/dri/i965/intel_tex.h
index 376f075c9..42565baeb 100644
--- a/lib/mesa/src/mesa/drivers/dri/i965/intel_tex.h
+++ b/lib/mesa/src/mesa/drivers/dri/i965/intel_tex.h
@@ -29,13 +29,12 @@
#include "main/mtypes.h"
#include "main/formats.h"
#include "brw_context.h"
+#include "intel_mipmap_tree.h"
void intelInitTextureFuncs(struct dd_function_table *functions);
void intelInitTextureImageFuncs(struct dd_function_table *functions);
-void intelInitTextureSubImageFuncs(struct dd_function_table *functions);
-
void intelInitTextureCopyImageFuncs(struct dd_function_table *functions);
void intelInitCopyImageFuncs(struct dd_function_table *functions);
@@ -49,28 +48,8 @@ struct intel_mipmap_tree *
intel_miptree_create_for_teximage(struct brw_context *brw,
struct intel_texture_object *intelObj,
struct intel_texture_image *intelImage,
- uint32_t layout_flags);
+ enum intel_miptree_create_flags flags);
void intel_finalize_mipmap_tree(struct brw_context *brw, GLuint unit);
-bool
-intel_texsubimage_tiled_memcpy(struct gl_context *ctx,
- GLuint dims,
- struct gl_texture_image *texImage,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type,
- const GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing,
- bool for_glTexImage);
-
-bool
-intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
- struct gl_texture_image *texImage,
- GLint xoffset, GLint yofset,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- GLvoid *pixels,
- const struct gl_pixelstore_attrib *packing);
-
#endif
diff --git a/lib/mesa/src/mesa/drivers/dri/nouveau/nouveau_context.h b/lib/mesa/src/mesa/drivers/dri/nouveau/nouveau_context.h
index b6cbde44a..6ab865c7b 100644
--- a/lib/mesa/src/mesa/drivers/dri/nouveau/nouveau_context.h
+++ b/lib/mesa/src/mesa/drivers/dri/nouveau/nouveau_context.h
@@ -111,8 +111,8 @@ GLboolean
nouveau_context_create(gl_api api,
const struct gl_config *visual, __DRIcontext *dri_ctx,
unsigned major_version, unsigned minor_version,
- uint32_t flags, bool notify_reset, unsigned *error,
- void *share_ctx);
+ uint32_t flags, bool notify_reset, unsigned priority,
+ unsigned *error, void *share_ctx);
GLboolean
nouveau_context_init(struct gl_context *ctx, gl_api api,
diff --git a/lib/mesa/src/mesa/drivers/dri/nouveau/nv10_context.c b/lib/mesa/src/mesa/drivers/dri/nouveau/nv10_context.c
index 7a86ba235..be2178fb7 100644
--- a/lib/mesa/src/mesa/drivers/dri/nouveau/nv10_context.c
+++ b/lib/mesa/src/mesa/drivers/dri/nouveau/nv10_context.c
@@ -451,10 +451,8 @@ nv10_context_create(struct nouveau_screen *screen, gl_api api,
ctx->Extensions.EXT_texture_env_dot3 = true;
ctx->Extensions.NV_fog_distance = true;
ctx->Extensions.NV_texture_rectangle = true;
- if (ctx->Mesa_DXTn) {
- ctx->Extensions.EXT_texture_compression_s3tc = true;
- ctx->Extensions.ANGLE_texture_compression_dxt = true;
- }
+ ctx->Extensions.EXT_texture_compression_s3tc = true;
+ ctx->Extensions.ANGLE_texture_compression_dxt = true;
/* GL constants. */
ctx->Const.MaxTextureLevels = 12;
diff --git a/lib/mesa/src/mesa/drivers/dri/nouveau/nv20_context.c b/lib/mesa/src/mesa/drivers/dri/nouveau/nv20_context.c
index ec638c036..0ab2db0b0 100644
--- a/lib/mesa/src/mesa/drivers/dri/nouveau/nv20_context.c
+++ b/lib/mesa/src/mesa/drivers/dri/nouveau/nv20_context.c
@@ -462,10 +462,8 @@ nv20_context_create(struct nouveau_screen *screen, gl_api api,
ctx->Extensions.EXT_texture_env_dot3 = true;
ctx->Extensions.NV_fog_distance = true;
ctx->Extensions.NV_texture_rectangle = true;
- if (ctx->Mesa_DXTn) {
- ctx->Extensions.EXT_texture_compression_s3tc = true;
- ctx->Extensions.ANGLE_texture_compression_dxt = true;
- }
+ ctx->Extensions.EXT_texture_compression_s3tc = true;
+ ctx->Extensions.ANGLE_texture_compression_dxt = true;
/* GL constants. */
ctx->Const.MaxTextureCoordUnits = NV20_TEXTURE_UNITS;
diff --git a/lib/mesa/src/mesa/drivers/dri/r200/Makefile.am b/lib/mesa/src/mesa/drivers/dri/r200/Makefile.am
index 1094343d6..110c02ed2 100644
--- a/lib/mesa/src/mesa/drivers/dri/r200/Makefile.am
+++ b/lib/mesa/src/mesa/drivers/dri/r200/Makefile.am
@@ -34,7 +34,7 @@ AM_CFLAGS = \
-I$(top_srcdir)/src/mesa/ \
-I$(top_srcdir)/src/gallium/include \
-I$(top_srcdir)/src/gallium/auxiliary \
- -I$(top_builddir)/src/mesa/drivers/dri/common \
+ -I$(top_builddir)/src/util \
-I$(top_srcdir)/src/mesa/drivers/dri/common \
-I$(top_srcdir)/src/mesa/drivers/dri/r200/server \
$(DEFINES) \
diff --git a/lib/mesa/src/mesa/drivers/dri/r200/radeon_screen.h b/lib/mesa/src/mesa/drivers/dri/r200/radeon_screen.h
index b3e926798..e70e334ab 100644
--- a/lib/mesa/src/mesa/drivers/dri/r200/radeon_screen.h
+++ b/lib/mesa/src/mesa/drivers/dri/r200/radeon_screen.h
@@ -45,7 +45,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "dri_util.h"
#include "radeon_chipset.h"
#include "radeon_reg.h"
-#include "xmlconfig.h"
+#include "util/xmlconfig.h"
typedef struct {
diff --git a/lib/mesa/src/mesa/drivers/dri/r200/radeon_texture.c b/lib/mesa/src/mesa/drivers/dri/r200/radeon_texture.c
index 4794ddae0..f2d435a37 100644
--- a/lib/mesa/src/mesa/drivers/dri/r200/radeon_texture.c
+++ b/lib/mesa/src/mesa/drivers/dri/r200/radeon_texture.c
@@ -41,7 +41,7 @@
#include "main/texobj.h"
#include "drivers/common/meta.h"
-#include "xmlpool.h" /* for symbolic values of enum-type options */
+#include "util/xmlpool.h" /* for symbolic values of enum-type options */
#include "radeon_common.h"
diff --git a/lib/mesa/src/mesa/drivers/dri/radeon/Makefile.am b/lib/mesa/src/mesa/drivers/dri/radeon/Makefile.am
index 176ec797e..aa898645c 100644
--- a/lib/mesa/src/mesa/drivers/dri/radeon/Makefile.am
+++ b/lib/mesa/src/mesa/drivers/dri/radeon/Makefile.am
@@ -35,7 +35,7 @@ AM_CFLAGS = \
-I$(top_srcdir)/src/mesa/ \
-I$(top_srcdir)/src/gallium/include \
-I$(top_srcdir)/src/gallium/auxiliary \
- -I$(top_builddir)/src/mesa/drivers/dri/common \
+ -I$(top_builddir)/src/util \
-I$(top_srcdir)/src/mesa/drivers/dri/common \
-I$(top_srcdir)/src/mesa/drivers/dri/radeon/server \
$(DEFINES) \
diff --git a/lib/mesa/src/mesa/drivers/dri/radeon/radeon_context.h b/lib/mesa/src/mesa/drivers/dri/radeon/radeon_context.h
index 88a295386..4124f50db 100644
--- a/lib/mesa/src/mesa/drivers/dri/radeon/radeon_context.h
+++ b/lib/mesa/src/mesa/drivers/dri/radeon/radeon_context.h
@@ -456,6 +456,7 @@ extern GLboolean r100CreateContext( gl_api api,
unsigned minor_version,
uint32_t flags,
bool notify_reset,
+ unsigned priority,
unsigned *error,
void *sharedContextPrivate);
diff --git a/lib/mesa/src/mesa/drivers/dri/radeon/radeon_screen.h b/lib/mesa/src/mesa/drivers/dri/radeon/radeon_screen.h
index b3e926798..e70e334ab 100644
--- a/lib/mesa/src/mesa/drivers/dri/radeon/radeon_screen.h
+++ b/lib/mesa/src/mesa/drivers/dri/radeon/radeon_screen.h
@@ -45,7 +45,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "dri_util.h"
#include "radeon_chipset.h"
#include "radeon_reg.h"
-#include "xmlconfig.h"
+#include "util/xmlconfig.h"
typedef struct {
diff --git a/lib/mesa/src/mesa/drivers/dri/radeon/radeon_state_init.c b/lib/mesa/src/mesa/drivers/dri/radeon/radeon_state_init.c
index 5e2f41fdb..99c535a49 100644
--- a/lib/mesa/src/mesa/drivers/dri/radeon/radeon_state_init.c
+++ b/lib/mesa/src/mesa/drivers/dri/radeon/radeon_state_init.c
@@ -44,7 +44,7 @@
#include "../r200/r200_reg.h"
-#include "xmlpool.h"
+#include "util/xmlpool.h"
/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in
* 1.3 cmdbuffers allow all previous state to be updated as well as
diff --git a/lib/mesa/src/mesa/drivers/dri/radeon/radeon_tcl.c b/lib/mesa/src/mesa/drivers/dri/radeon/radeon_tcl.c
index 3e2f42616..61ff2311e 100644
--- a/lib/mesa/src/mesa/drivers/dri/radeon/radeon_tcl.c
+++ b/lib/mesa/src/mesa/drivers/dri/radeon/radeon_tcl.c
@@ -39,6 +39,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "main/enums.h"
#include "main/state.h"
+#include "util/macros.h"
+
#include "vbo/vbo.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
@@ -297,7 +299,7 @@ static GLuint radeonEnsureEmitSize( struct gl_context * ctx , GLuint inputs )
VERT_BIT_FOG
};
/* predict number of aos to emit */
- for (i=0; i < sizeof(flags_to_check)/sizeof(flags_to_check[0]); ++i)
+ for (i=0; i < ARRAY_SIZE(flags_to_check); ++i)
{
if (inputs & flags_to_check[i])
++nr_aos;
diff --git a/lib/mesa/src/mesa/drivers/dri/radeon/radeon_texture.c b/lib/mesa/src/mesa/drivers/dri/radeon/radeon_texture.c
index 4794ddae0..f2d435a37 100644
--- a/lib/mesa/src/mesa/drivers/dri/radeon/radeon_texture.c
+++ b/lib/mesa/src/mesa/drivers/dri/radeon/radeon_texture.c
@@ -41,7 +41,7 @@
#include "main/texobj.h"
#include "drivers/common/meta.h"
-#include "xmlpool.h" /* for symbolic values of enum-type options */
+#include "util/xmlpool.h" /* for symbolic values of enum-type options */
#include "radeon_common.h"
diff --git a/lib/mesa/src/mesa/drivers/dri/swrast/Makefile.am b/lib/mesa/src/mesa/drivers/dri/swrast/Makefile.am
index a82e580f1..7e1ea59e9 100644
--- a/lib/mesa/src/mesa/drivers/dri/swrast/Makefile.am
+++ b/lib/mesa/src/mesa/drivers/dri/swrast/Makefile.am
@@ -30,7 +30,7 @@ AM_CFLAGS = \
-I$(top_srcdir)/src/mesa/ \
-I$(top_srcdir)/src/gallium/include \
-I$(top_srcdir)/src/gallium/auxiliary \
- -I$(top_builddir)/src/mesa/drivers/dri/common \
+ -I$(top_builddir)/src/util \
-I$(top_srcdir)/src/mesa/drivers/dri/common \
$(LIBDRM_CFLAGS) \
$(DEFINES) \
diff --git a/lib/mesa/src/mesa/swrast/s_texfetch.c b/lib/mesa/src/mesa/swrast/s_texfetch.c
index 4353ea0e4..e2c3c085b 100644
--- a/lib/mesa/src/mesa/swrast/s_texfetch.c
+++ b/lib/mesa/src/mesa/swrast/s_texfetch.c
@@ -159,6 +159,7 @@ texfetch_funcs[] =
FETCH_NULL(B4G4R4X4_UNORM),
FETCH_FUNCS(A4R4G4B4_UNORM),
FETCH_FUNCS(A1B5G5R5_UNORM),
+ FETCH_NULL(X1B5G5R5_UNORM),
FETCH_FUNCS(B5G5R5A1_UNORM),
FETCH_NULL(B5G5R5X1_UNORM),
FETCH_FUNCS(A1R5G5B5_UNORM),