Jason started the task by creating anv_cmd_buffer.c and anv_cmd_emit.c.
This patch finishes the task by renaming all other files except
gen*_pack.h and glsl_scraper.py.
# Generated source files
-/*-spirv.h
-/entrypoints.c
-/entrypoints.h
+/*_spirv.h
+/anv_entrypoints.c
+/anv_entrypoints.h
libvulkan_la_CXXFLAGS = \
-Wall -Wextra -Wno-unused-parameter -fvisibility=hidden -O0 -g
-libvulkan_la_SOURCES = \
- private.h \
- gem.c \
- device.c \
- anv_cmd_buffer.c \
- anv_cmd_emit.c \
- aub.c \
- allocator.c \
- util.c \
- pipeline.c \
- image.c \
- meta.c \
- intel.c \
- entrypoints.c \
- entrypoints.h \
- x11.c \
- formats.c \
- compiler.cpp \
- query.c
-
-BUILT_SOURCES = \
- entrypoints.h \
- entrypoints.c \
- meta-spirv.h
-
-entrypoints.h : vk_gen.py $(vulkan_include_HEADERS)
+libvulkan_la_SOURCES = \
+ anv_allocator.c \
+ anv_aub.c \
+ anv_cmd_buffer.c \
+ anv_cmd_emit.c \
+ anv_compiler.cpp \
+ anv_device.c \
+ anv_entrypoints.c \
+ anv_entrypoints.h \
+ anv_formats.c \
+ anv_gem.c \
+ anv_image.c \
+ anv_intel.c \
+ anv_meta.c \
+ anv_pipeline.c \
+ anv_private.h \
+ anv_query.c \
+ anv_util.c \
+ anv_x11.c
+
+BUILT_SOURCES = \
+ anv_entrypoints.h \
+ anv_entrypoints.c \
+ anv_meta_spirv.h
+
+anv_entrypoints.h : anv_entrypoints_gen.py $(vulkan_include_HEADERS)
$(AM_V_GEN)cat $(vulkan_include_HEADERS) | $(PYTHON2) $< header > $@
-entrypoints.c : vk_gen.py $(vulkan_include_HEADERS)
+anv_entrypoints.c : anv_entrypoints_gen.py $(vulkan_include_HEADERS)
$(AM_V_GEN)cat $(vulkan_include_HEADERS) | $(PYTHON2) $< code > $@
-%-spirv.h: %.c glsl_scraper.py
+%_spirv.h: %.c glsl_scraper.py
$(AM_V_GEN) $(PYTHON2) $(srcdir)/glsl_scraper.py --glsl-only -o $@ $<
CLEANFILES = $(BUILT_SOURCES)
+++ /dev/null
-/*
- * 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.
- */
-
-#define _DEFAULT_SOURCE
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <values.h>
-#include <assert.h>
-#include <linux/futex.h>
-#include <linux/memfd.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <sys/syscall.h>
-
-#include "private.h"
-
-#ifdef HAVE_VALGRIND
-#define VG_NOACCESS_READ(__ptr) ({ \
- VALGRIND_MAKE_MEM_DEFINED((__ptr), sizeof(*(__ptr))); \
- __typeof(*(__ptr)) __val = *(__ptr); \
- VALGRIND_MAKE_MEM_NOACCESS((__ptr), sizeof(*(__ptr)));\
- __val; \
-})
-#define VG_NOACCESS_WRITE(__ptr, __val) ({ \
- VALGRIND_MAKE_MEM_UNDEFINED((__ptr), sizeof(*(__ptr))); \
- *(__ptr) = (__val); \
- VALGRIND_MAKE_MEM_NOACCESS((__ptr), sizeof(*(__ptr))); \
-})
-#else
-#define VG_NOACCESS_READ(__ptr) (*(__ptr))
-#define VG_NOACCESS_WRITE(__ptr, __val) (*(__ptr) = (__val))
-#endif
-
-/* Design goals:
- *
- * - Lock free (except when resizing underlying bos)
- *
- * - Constant time allocation with typically only one atomic
- *
- * - Multiple allocation sizes without fragmentation
- *
- * - Can grow while keeping addresses and offset of contents stable
- *
- * - All allocations within one bo so we can point one of the
- * STATE_BASE_ADDRESS pointers at it.
- *
- * The overall design is a two-level allocator: top level is a fixed size, big
- * block (8k) allocator, which operates out of a bo. Allocation is done by
- * either pulling a block from the free list or growing the used range of the
- * bo. Growing the range may run out of space in the bo which we then need to
- * grow. Growing the bo is tricky in a multi-threaded, lockless environment:
- * we need to keep all pointers and contents in the old map valid. GEM bos in
- * general can't grow, but we use a trick: we create a memfd and use ftruncate
- * to grow it as necessary. We mmap the new size and then create a gem bo for
- * it using the new gem userptr ioctl. Without heavy-handed locking around
- * our allocation fast-path, there isn't really a way to munmap the old mmap,
- * so we just keep it around until garbage collection time. While the block
- * allocator is lockless for normal operations, we block other threads trying
- * to allocate while we're growing the map. It sholdn't happen often, and
- * growing is fast anyway.
- *
- * At the next level we can use various sub-allocators. The state pool is a
- * pool of smaller, fixed size objects, which operates much like the block
- * pool. It uses a free list for freeing objects, but when it runs out of
- * space it just allocates a new block from the block pool. This allocator is
- * intended for longer lived state objects such as SURFACE_STATE and most
- * other persistent state objects in the API. We may need to track more info
- * with these object and a pointer back to the CPU object (eg VkImage). In
- * those cases we just allocate a slightly bigger object and put the extra
- * state after the GPU state object.
- *
- * The state stream allocator works similar to how the i965 DRI driver streams
- * all its state. Even with Vulkan, we need to emit transient state (whether
- * surface state base or dynamic state base), and for that we can just get a
- * block and fill it up. These cases are local to a command buffer and the
- * sub-allocator need not be thread safe. The streaming allocator gets a new
- * block when it runs out of space and chains them together so they can be
- * easily freed.
- */
-
-/* Allocations are always at least 64 byte aligned, so 1 is an invalid value.
- * We use it to indicate the free list is empty. */
-#define EMPTY 1
-
-struct anv_mmap_cleanup {
- void *map;
- size_t size;
- uint32_t gem_handle;
-};
-
-#define ANV_MMAP_CLEANUP_INIT ((struct anv_mmap_cleanup){0})
-
-static inline long
-sys_futex(void *addr1, int op, int val1,
- struct timespec *timeout, void *addr2, int val3)
-{
- return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
-}
-
-static inline int
-futex_wake(uint32_t *addr, int count)
-{
- return sys_futex(addr, FUTEX_WAKE, count, NULL, NULL, 0);
-}
-
-static inline int
-futex_wait(uint32_t *addr, int32_t value)
-{
- return sys_futex(addr, FUTEX_WAIT, value, NULL, NULL, 0);
-}
-
-static inline int
-memfd_create(const char *name, unsigned int flags)
-{
- return syscall(SYS_memfd_create, name, flags);
-}
-
-static inline uint32_t
-ilog2_round_up(uint32_t value)
-{
- assert(value != 0);
- return 32 - __builtin_clz(value - 1);
-}
-
-static inline uint32_t
-round_to_power_of_two(uint32_t value)
-{
- return 1 << ilog2_round_up(value);
-}
-
-static bool
-anv_free_list_pop(union anv_free_list *list, void **map, uint32_t *offset)
-{
- union anv_free_list current, next, old;
-
- current = *list;
- while (current.offset != EMPTY) {
- /* We have to add a memory barrier here so that the list head (and
- * offset) gets read before we read the map pointer. This way we
- * know that the map pointer is valid for the given offset at the
- * point where we read it.
- */
- __sync_synchronize();
-
- uint32_t *next_ptr = *map + current.offset;
- next.offset = VG_NOACCESS_READ(next_ptr);
- next.count = current.count + 1;
- old.u64 = __sync_val_compare_and_swap(&list->u64, current.u64, next.u64);
- if (old.u64 == current.u64) {
- *offset = current.offset;
- return true;
- }
- current = old;
- }
-
- return false;
-}
-
-static void
-anv_free_list_push(union anv_free_list *list, void *map, uint32_t offset)
-{
- union anv_free_list current, old, new;
- uint32_t *next_ptr = map + offset;
-
- old = *list;
- do {
- current = old;
- VG_NOACCESS_WRITE(next_ptr, current.offset);
- new.offset = offset;
- new.count = current.count + 1;
- old.u64 = __sync_val_compare_and_swap(&list->u64, current.u64, new.u64);
- } while (old.u64 != current.u64);
-}
-
-/* All pointers in the ptr_free_list are assumed to be page-aligned. This
- * means that the bottom 12 bits should all be zero.
- */
-#define PFL_COUNT(x) ((uintptr_t)(x) & 0xfff)
-#define PFL_PTR(x) ((void *)((uintptr_t)(x) & ~0xfff))
-#define PFL_PACK(ptr, count) ({ \
- assert(((uintptr_t)(ptr) & 0xfff) == 0); \
- (void *)((uintptr_t)(ptr) | (uintptr_t)((count) & 0xfff)); \
-})
-
-static bool
-anv_ptr_free_list_pop(void **list, void **elem)
-{
- void *current = *list;
- while (PFL_PTR(current) != NULL) {
- void **next_ptr = PFL_PTR(current);
- void *new_ptr = VG_NOACCESS_READ(next_ptr);
- unsigned new_count = PFL_COUNT(current) + 1;
- void *new = PFL_PACK(new_ptr, new_count);
- void *old = __sync_val_compare_and_swap(list, current, new);
- if (old == current) {
- *elem = PFL_PTR(current);
- return true;
- }
- current = old;
- }
-
- return false;
-}
-
-static void
-anv_ptr_free_list_push(void **list, void *elem)
-{
- void *old, *current;
- void **next_ptr = elem;
-
- old = *list;
- do {
- current = old;
- VG_NOACCESS_WRITE(next_ptr, PFL_PTR(current));
- unsigned new_count = PFL_COUNT(current) + 1;
- void *new = PFL_PACK(elem, new_count);
- old = __sync_val_compare_and_swap(list, current, new);
- } while (old != current);
-}
-
-static int
-anv_block_pool_grow(struct anv_block_pool *pool);
-
-void
-anv_block_pool_init(struct anv_block_pool *pool,
- struct anv_device *device, uint32_t block_size)
-{
- assert(is_power_of_two(block_size));
-
- pool->device = device;
- pool->bo.gem_handle = 0;
- pool->bo.offset = 0;
- pool->size = 0;
- pool->block_size = block_size;
- pool->next_block = 0;
- pool->free_list = ANV_FREE_LIST_EMPTY;
- anv_vector_init(&pool->mmap_cleanups,
- round_to_power_of_two(sizeof(struct anv_mmap_cleanup)), 128);
-
- /* Immediately grow the pool so we'll have a backing bo. */
- anv_block_pool_grow(pool);
-}
-
-void
-anv_block_pool_finish(struct anv_block_pool *pool)
-{
- struct anv_mmap_cleanup *cleanup;
-
- anv_vector_foreach(cleanup, &pool->mmap_cleanups) {
- if (cleanup->map)
- munmap(cleanup->map, cleanup->size);
- if (cleanup->gem_handle)
- anv_gem_close(pool->device, cleanup->gem_handle);
- }
-
- anv_vector_finish(&pool->mmap_cleanups);
-
- close(pool->fd);
-}
-
-static int
-anv_block_pool_grow(struct anv_block_pool *pool)
-{
- size_t size;
- void *map;
- int gem_handle;
- struct anv_mmap_cleanup *cleanup;
-
- if (pool->size == 0) {
- size = 32 * pool->block_size;
- } else {
- size = pool->size * 2;
- }
-
- cleanup = anv_vector_add(&pool->mmap_cleanups);
- if (!cleanup)
- return -1;
- *cleanup = ANV_MMAP_CLEANUP_INIT;
-
- if (pool->size == 0)
- pool->fd = memfd_create("block pool", MFD_CLOEXEC);
-
- if (pool->fd == -1)
- return -1;
-
- if (ftruncate(pool->fd, size) == -1)
- return -1;
-
- /* First try to see if mremap can grow the map in place. */
- map = MAP_FAILED;
- if (pool->size > 0)
- map = mremap(pool->map, pool->size, size, 0);
- if (map == MAP_FAILED) {
- /* Just leak the old map until we destroy the pool. We can't munmap it
- * without races or imposing locking on the block allocate fast path. On
- * the whole the leaked maps adds up to less than the size of the
- * current map. MAP_POPULATE seems like the right thing to do, but we
- * should try to get some numbers.
- */
- map = mmap(NULL, size, PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_POPULATE, pool->fd, 0);
- cleanup->map = map;
- cleanup->size = size;
- }
- if (map == MAP_FAILED)
- return -1;
-
- gem_handle = anv_gem_userptr(pool->device, map, size);
- if (gem_handle == 0)
- return -1;
- cleanup->gem_handle = gem_handle;
-
- /* Now that we successfull allocated everything, we can write the new
- * values back into pool. */
- pool->map = map;
- pool->bo.gem_handle = gem_handle;
- pool->bo.size = size;
- pool->bo.map = map;
- pool->bo.index = 0;
-
- /* Write size last and after the memory barrier here. We need the memory
- * barrier to make sure map and gem_handle are written before other threads
- * see the new size. A thread could allocate a block and then go try using
- * the old pool->map and access out of bounds. */
-
- __sync_synchronize();
- pool->size = size;
-
- return 0;
-}
-
-uint32_t
-anv_block_pool_alloc(struct anv_block_pool *pool)
-{
- uint32_t offset, block, size;
-
- /* Try free list first. */
- if (anv_free_list_pop(&pool->free_list, &pool->map, &offset)) {
- assert(pool->map);
- return offset;
- }
-
- restart:
- size = pool->size;
- block = __sync_fetch_and_add(&pool->next_block, pool->block_size);
- if (block < size) {
- assert(pool->map);
- return block;
- } else if (block == size) {
- /* We allocated the first block outside the pool, we have to grow it.
- * pool->next_block acts a mutex: threads who try to allocate now will
- * get block indexes above the current limit and hit futex_wait
- * below. */
- int err = anv_block_pool_grow(pool);
- assert(err == 0);
- (void) err;
- futex_wake(&pool->size, INT_MAX);
- } else {
- futex_wait(&pool->size, size);
- __sync_fetch_and_add(&pool->next_block, -pool->block_size);
- goto restart;
- }
-
- return block;
-}
-
-void
-anv_block_pool_free(struct anv_block_pool *pool, uint32_t offset)
-{
- anv_free_list_push(&pool->free_list, pool->map, offset);
-}
-
-static void
-anv_fixed_size_state_pool_init(struct anv_fixed_size_state_pool *pool,
- size_t state_size)
-{
- /* At least a cache line and must divide the block size. */
- assert(state_size >= 64 && is_power_of_two(state_size));
-
- pool->state_size = state_size;
- pool->free_list = ANV_FREE_LIST_EMPTY;
- pool->block.next = 0;
- pool->block.end = 0;
-}
-
-static uint32_t
-anv_fixed_size_state_pool_alloc(struct anv_fixed_size_state_pool *pool,
- struct anv_block_pool *block_pool)
-{
- uint32_t offset;
- struct anv_block_state block, old, new;
-
- /* Try free list first. */
- if (anv_free_list_pop(&pool->free_list, &block_pool->map, &offset))
- return offset;
-
- /* If free list was empty (or somebody raced us and took the items) we
- * allocate a new item from the end of the block */
- restart:
- block.u64 = __sync_fetch_and_add(&pool->block.u64, pool->state_size);
-
- if (block.next < block.end) {
- return block.next;
- } else if (block.next == block.end) {
- new.next = anv_block_pool_alloc(block_pool);
- new.end = new.next + block_pool->block_size;
- old.u64 = __sync_fetch_and_add(&pool->block.u64, new.u64 - block.u64);
- if (old.next != block.next)
- futex_wake(&pool->block.end, INT_MAX);
- return new.next;
- } else {
- futex_wait(&pool->block.end, block.end);
- __sync_fetch_and_add(&pool->block.u64, -pool->state_size);
- goto restart;
- }
-}
-
-static void
-anv_fixed_size_state_pool_free(struct anv_fixed_size_state_pool *pool,
- struct anv_block_pool *block_pool,
- uint32_t offset)
-{
- anv_free_list_push(&pool->free_list, block_pool->map, offset);
-}
-
-void
-anv_state_pool_init(struct anv_state_pool *pool,
- struct anv_block_pool *block_pool)
-{
- pool->block_pool = block_pool;
- for (unsigned i = 0; i < ANV_STATE_BUCKETS; i++) {
- size_t size = 1 << (ANV_MIN_STATE_SIZE_LOG2 + i);
- anv_fixed_size_state_pool_init(&pool->buckets[i], size);
- }
-}
-
-struct anv_state
-anv_state_pool_alloc(struct anv_state_pool *pool, size_t size, size_t align)
-{
- unsigned size_log2 = ilog2_round_up(size < align ? align : size);
- assert(size_log2 <= ANV_MAX_STATE_SIZE_LOG2);
- if (size_log2 < ANV_MIN_STATE_SIZE_LOG2)
- size_log2 = ANV_MIN_STATE_SIZE_LOG2;
- unsigned bucket = size_log2 - ANV_MIN_STATE_SIZE_LOG2;
-
- struct anv_state state;
- state.alloc_size = 1 << size_log2;
- state.offset = anv_fixed_size_state_pool_alloc(&pool->buckets[bucket],
- pool->block_pool);
- state.map = pool->block_pool->map + state.offset;
- VG(VALGRIND_MALLOCLIKE_BLOCK(state.map, size, 0, false));
- return state;
-}
-
-void
-anv_state_pool_free(struct anv_state_pool *pool, struct anv_state state)
-{
- assert(is_power_of_two(state.alloc_size));
- unsigned size_log2 = ilog2_round_up(state.alloc_size);
- assert(size_log2 >= ANV_MIN_STATE_SIZE_LOG2 &&
- size_log2 <= ANV_MAX_STATE_SIZE_LOG2);
- unsigned bucket = size_log2 - ANV_MIN_STATE_SIZE_LOG2;
-
- VG(VALGRIND_FREELIKE_BLOCK(state.map, 0));
- anv_fixed_size_state_pool_free(&pool->buckets[bucket],
- pool->block_pool, state.offset);
-}
-
-#define NULL_BLOCK 1
-struct stream_block {
- uint32_t next;
-
- /* The map for the BO at the time the block was givne to us */
- void *current_map;
-
-#ifdef HAVE_VALGRIND
- void *_vg_ptr;
-#endif
-};
-
-/* The state stream allocator is a one-shot, single threaded allocator for
- * variable sized blocks. We use it for allocating dynamic state.
- */
-void
-anv_state_stream_init(struct anv_state_stream *stream,
- struct anv_block_pool *block_pool)
-{
- stream->block_pool = block_pool;
- stream->next = 0;
- stream->end = 0;
- stream->current_block = NULL_BLOCK;
-}
-
-void
-anv_state_stream_finish(struct anv_state_stream *stream)
-{
- struct stream_block *sb;
- uint32_t block, next_block;
-
- block = stream->current_block;
- while (block != NULL_BLOCK) {
- sb = stream->block_pool->map + block;
- next_block = VG_NOACCESS_READ(&sb->next);
- VG(VALGRIND_FREELIKE_BLOCK(VG_NOACCESS_READ(&sb->_vg_ptr), 0));
- anv_block_pool_free(stream->block_pool, block);
- block = next_block;
- }
-}
-
-struct anv_state
-anv_state_stream_alloc(struct anv_state_stream *stream,
- uint32_t size, uint32_t alignment)
-{
- struct stream_block *sb;
- struct anv_state state;
- uint32_t block;
-
- state.offset = align_u32(stream->next, alignment);
- if (state.offset + size > stream->end) {
- block = anv_block_pool_alloc(stream->block_pool);
- void *current_map = stream->block_pool->map;
- sb = current_map + block;
- VG_NOACCESS_WRITE(&sb->current_map, current_map);
- VG_NOACCESS_WRITE(&sb->next, stream->current_block);
- VG(VG_NOACCESS_WRITE(&sb->_vg_ptr, 0));
- stream->current_block = block;
- stream->next = block + sizeof(*sb);
- stream->end = block + stream->block_pool->block_size;
- state.offset = align_u32(stream->next, alignment);
- assert(state.offset + size <= stream->end);
- }
-
- sb = stream->block_pool->map + stream->current_block;
- void *current_map = VG_NOACCESS_READ(&sb->current_map);
-
- state.map = current_map + state.offset;
- state.alloc_size = size;
-
-#ifdef HAVE_VALGRIND
- void *vg_ptr = VG_NOACCESS_READ(&sb->_vg_ptr);
- if (vg_ptr == NULL) {
- vg_ptr = state.map;
- VG_NOACCESS_WRITE(&sb->_vg_ptr, vg_ptr);
- VALGRIND_MALLOCLIKE_BLOCK(vg_ptr, size, 0, false);
- } else {
- ptrdiff_t vg_offset = vg_ptr - current_map;
- assert(vg_offset >= stream->current_block &&
- vg_offset < stream->end);
- VALGRIND_RESIZEINPLACE_BLOCK(vg_ptr,
- stream->next - vg_offset,
- (state.offset + size) - vg_offset,
- 0);
- }
-#endif
-
- stream->next = state.offset + size;
-
- return state;
-}
-
-struct bo_pool_bo_link {
- struct bo_pool_bo_link *next;
- struct anv_bo bo;
-};
-
-void
-anv_bo_pool_init(struct anv_bo_pool *pool,
- struct anv_device *device, uint32_t bo_size)
-{
- pool->device = device;
- pool->bo_size = bo_size;
- pool->free_list = NULL;
-}
-
-void
-anv_bo_pool_finish(struct anv_bo_pool *pool)
-{
- struct bo_pool_bo_link *link = PFL_PTR(pool->free_list);
- while (link != NULL) {
- struct bo_pool_bo_link link_copy = VG_NOACCESS_READ(link);
-
- /* The anv_gem_m[un]map() functions are also valgrind-safe so they
- * act as an alloc/free. In order to avoid a double-free warning, we
- * need to mark thiss as malloc'd before we unmap it.
- */
- VG(VALGRIND_MALLOCLIKE_BLOCK(link_copy.bo.map, pool->bo_size, 0, false));
-
- anv_gem_munmap(link_copy.bo.map, pool->bo_size);
- anv_gem_close(pool->device, link_copy.bo.gem_handle);
- link = link_copy.next;
- }
-}
-
-VkResult
-anv_bo_pool_alloc(struct anv_bo_pool *pool, struct anv_bo *bo)
-{
- VkResult result;
-
- void *next_free_void;
- if (anv_ptr_free_list_pop(&pool->free_list, &next_free_void)) {
- struct bo_pool_bo_link *next_free = next_free_void;
- *bo = VG_NOACCESS_READ(&next_free->bo);
- assert(bo->map == next_free);
- assert(bo->size == pool->bo_size);
-
- VG(VALGRIND_MALLOCLIKE_BLOCK(bo->map, pool->bo_size, 0, false));
-
- return VK_SUCCESS;
- }
-
- struct anv_bo new_bo;
-
- result = anv_bo_init_new(&new_bo, pool->device, pool->bo_size);
- if (result != VK_SUCCESS)
- return result;
-
- assert(new_bo.size == pool->bo_size);
-
- new_bo.map = anv_gem_mmap(pool->device, new_bo.gem_handle, 0, pool->bo_size);
- if (new_bo.map == NULL) {
- anv_gem_close(pool->device, new_bo.gem_handle);
- return vk_error(VK_ERROR_MEMORY_MAP_FAILED);
- }
-
- /* We don't need to call VALGRIND_MALLOCLIKE_BLOCK here because gem_mmap
- * calls it for us. If we really want to be pedantic we could do a
- * VALGRIND_FREELIKE_BLOCK right after the mmap, but there's no good
- * reason.
- */
-
- *bo = new_bo;
- return VK_SUCCESS;
-}
-
-void
-anv_bo_pool_free(struct anv_bo_pool *pool, const struct anv_bo *bo)
-{
- struct bo_pool_bo_link *link = bo->map;
- link->bo = *bo;
-
- VG(VALGRIND_FREELIKE_BLOCK(bo->map, 0));
- anv_ptr_free_list_push(&pool->free_list, link);
-}
--- /dev/null
+/*
+ * 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.
+ */
+
+#define _DEFAULT_SOURCE
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <values.h>
+#include <assert.h>
+#include <linux/futex.h>
+#include <linux/memfd.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+
+#include "anv_private.h"
+
+#ifdef HAVE_VALGRIND
+#define VG_NOACCESS_READ(__ptr) ({ \
+ VALGRIND_MAKE_MEM_DEFINED((__ptr), sizeof(*(__ptr))); \
+ __typeof(*(__ptr)) __val = *(__ptr); \
+ VALGRIND_MAKE_MEM_NOACCESS((__ptr), sizeof(*(__ptr)));\
+ __val; \
+})
+#define VG_NOACCESS_WRITE(__ptr, __val) ({ \
+ VALGRIND_MAKE_MEM_UNDEFINED((__ptr), sizeof(*(__ptr))); \
+ *(__ptr) = (__val); \
+ VALGRIND_MAKE_MEM_NOACCESS((__ptr), sizeof(*(__ptr))); \
+})
+#else
+#define VG_NOACCESS_READ(__ptr) (*(__ptr))
+#define VG_NOACCESS_WRITE(__ptr, __val) (*(__ptr) = (__val))
+#endif
+
+/* Design goals:
+ *
+ * - Lock free (except when resizing underlying bos)
+ *
+ * - Constant time allocation with typically only one atomic
+ *
+ * - Multiple allocation sizes without fragmentation
+ *
+ * - Can grow while keeping addresses and offset of contents stable
+ *
+ * - All allocations within one bo so we can point one of the
+ * STATE_BASE_ADDRESS pointers at it.
+ *
+ * The overall design is a two-level allocator: top level is a fixed size, big
+ * block (8k) allocator, which operates out of a bo. Allocation is done by
+ * either pulling a block from the free list or growing the used range of the
+ * bo. Growing the range may run out of space in the bo which we then need to
+ * grow. Growing the bo is tricky in a multi-threaded, lockless environment:
+ * we need to keep all pointers and contents in the old map valid. GEM bos in
+ * general can't grow, but we use a trick: we create a memfd and use ftruncate
+ * to grow it as necessary. We mmap the new size and then create a gem bo for
+ * it using the new gem userptr ioctl. Without heavy-handed locking around
+ * our allocation fast-path, there isn't really a way to munmap the old mmap,
+ * so we just keep it around until garbage collection time. While the block
+ * allocator is lockless for normal operations, we block other threads trying
+ * to allocate while we're growing the map. It sholdn't happen often, and
+ * growing is fast anyway.
+ *
+ * At the next level we can use various sub-allocators. The state pool is a
+ * pool of smaller, fixed size objects, which operates much like the block
+ * pool. It uses a free list for freeing objects, but when it runs out of
+ * space it just allocates a new block from the block pool. This allocator is
+ * intended for longer lived state objects such as SURFACE_STATE and most
+ * other persistent state objects in the API. We may need to track more info
+ * with these object and a pointer back to the CPU object (eg VkImage). In
+ * those cases we just allocate a slightly bigger object and put the extra
+ * state after the GPU state object.
+ *
+ * The state stream allocator works similar to how the i965 DRI driver streams
+ * all its state. Even with Vulkan, we need to emit transient state (whether
+ * surface state base or dynamic state base), and for that we can just get a
+ * block and fill it up. These cases are local to a command buffer and the
+ * sub-allocator need not be thread safe. The streaming allocator gets a new
+ * block when it runs out of space and chains them together so they can be
+ * easily freed.
+ */
+
+/* Allocations are always at least 64 byte aligned, so 1 is an invalid value.
+ * We use it to indicate the free list is empty. */
+#define EMPTY 1
+
+struct anv_mmap_cleanup {
+ void *map;
+ size_t size;
+ uint32_t gem_handle;
+};
+
+#define ANV_MMAP_CLEANUP_INIT ((struct anv_mmap_cleanup){0})
+
+static inline long
+sys_futex(void *addr1, int op, int val1,
+ struct timespec *timeout, void *addr2, int val3)
+{
+ return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
+}
+
+static inline int
+futex_wake(uint32_t *addr, int count)
+{
+ return sys_futex(addr, FUTEX_WAKE, count, NULL, NULL, 0);
+}
+
+static inline int
+futex_wait(uint32_t *addr, int32_t value)
+{
+ return sys_futex(addr, FUTEX_WAIT, value, NULL, NULL, 0);
+}
+
+static inline int
+memfd_create(const char *name, unsigned int flags)
+{
+ return syscall(SYS_memfd_create, name, flags);
+}
+
+static inline uint32_t
+ilog2_round_up(uint32_t value)
+{
+ assert(value != 0);
+ return 32 - __builtin_clz(value - 1);
+}
+
+static inline uint32_t
+round_to_power_of_two(uint32_t value)
+{
+ return 1 << ilog2_round_up(value);
+}
+
+static bool
+anv_free_list_pop(union anv_free_list *list, void **map, uint32_t *offset)
+{
+ union anv_free_list current, next, old;
+
+ current = *list;
+ while (current.offset != EMPTY) {
+ /* We have to add a memory barrier here so that the list head (and
+ * offset) gets read before we read the map pointer. This way we
+ * know that the map pointer is valid for the given offset at the
+ * point where we read it.
+ */
+ __sync_synchronize();
+
+ uint32_t *next_ptr = *map + current.offset;
+ next.offset = VG_NOACCESS_READ(next_ptr);
+ next.count = current.count + 1;
+ old.u64 = __sync_val_compare_and_swap(&list->u64, current.u64, next.u64);
+ if (old.u64 == current.u64) {
+ *offset = current.offset;
+ return true;
+ }
+ current = old;
+ }
+
+ return false;
+}
+
+static void
+anv_free_list_push(union anv_free_list *list, void *map, uint32_t offset)
+{
+ union anv_free_list current, old, new;
+ uint32_t *next_ptr = map + offset;
+
+ old = *list;
+ do {
+ current = old;
+ VG_NOACCESS_WRITE(next_ptr, current.offset);
+ new.offset = offset;
+ new.count = current.count + 1;
+ old.u64 = __sync_val_compare_and_swap(&list->u64, current.u64, new.u64);
+ } while (old.u64 != current.u64);
+}
+
+/* All pointers in the ptr_free_list are assumed to be page-aligned. This
+ * means that the bottom 12 bits should all be zero.
+ */
+#define PFL_COUNT(x) ((uintptr_t)(x) & 0xfff)
+#define PFL_PTR(x) ((void *)((uintptr_t)(x) & ~0xfff))
+#define PFL_PACK(ptr, count) ({ \
+ assert(((uintptr_t)(ptr) & 0xfff) == 0); \
+ (void *)((uintptr_t)(ptr) | (uintptr_t)((count) & 0xfff)); \
+})
+
+static bool
+anv_ptr_free_list_pop(void **list, void **elem)
+{
+ void *current = *list;
+ while (PFL_PTR(current) != NULL) {
+ void **next_ptr = PFL_PTR(current);
+ void *new_ptr = VG_NOACCESS_READ(next_ptr);
+ unsigned new_count = PFL_COUNT(current) + 1;
+ void *new = PFL_PACK(new_ptr, new_count);
+ void *old = __sync_val_compare_and_swap(list, current, new);
+ if (old == current) {
+ *elem = PFL_PTR(current);
+ return true;
+ }
+ current = old;
+ }
+
+ return false;
+}
+
+static void
+anv_ptr_free_list_push(void **list, void *elem)
+{
+ void *old, *current;
+ void **next_ptr = elem;
+
+ old = *list;
+ do {
+ current = old;
+ VG_NOACCESS_WRITE(next_ptr, PFL_PTR(current));
+ unsigned new_count = PFL_COUNT(current) + 1;
+ void *new = PFL_PACK(elem, new_count);
+ old = __sync_val_compare_and_swap(list, current, new);
+ } while (old != current);
+}
+
+static int
+anv_block_pool_grow(struct anv_block_pool *pool);
+
+void
+anv_block_pool_init(struct anv_block_pool *pool,
+ struct anv_device *device, uint32_t block_size)
+{
+ assert(is_power_of_two(block_size));
+
+ pool->device = device;
+ pool->bo.gem_handle = 0;
+ pool->bo.offset = 0;
+ pool->size = 0;
+ pool->block_size = block_size;
+ pool->next_block = 0;
+ pool->free_list = ANV_FREE_LIST_EMPTY;
+ anv_vector_init(&pool->mmap_cleanups,
+ round_to_power_of_two(sizeof(struct anv_mmap_cleanup)), 128);
+
+ /* Immediately grow the pool so we'll have a backing bo. */
+ anv_block_pool_grow(pool);
+}
+
+void
+anv_block_pool_finish(struct anv_block_pool *pool)
+{
+ struct anv_mmap_cleanup *cleanup;
+
+ anv_vector_foreach(cleanup, &pool->mmap_cleanups) {
+ if (cleanup->map)
+ munmap(cleanup->map, cleanup->size);
+ if (cleanup->gem_handle)
+ anv_gem_close(pool->device, cleanup->gem_handle);
+ }
+
+ anv_vector_finish(&pool->mmap_cleanups);
+
+ close(pool->fd);
+}
+
+static int
+anv_block_pool_grow(struct anv_block_pool *pool)
+{
+ size_t size;
+ void *map;
+ int gem_handle;
+ struct anv_mmap_cleanup *cleanup;
+
+ if (pool->size == 0) {
+ size = 32 * pool->block_size;
+ } else {
+ size = pool->size * 2;
+ }
+
+ cleanup = anv_vector_add(&pool->mmap_cleanups);
+ if (!cleanup)
+ return -1;
+ *cleanup = ANV_MMAP_CLEANUP_INIT;
+
+ if (pool->size == 0)
+ pool->fd = memfd_create("block pool", MFD_CLOEXEC);
+
+ if (pool->fd == -1)
+ return -1;
+
+ if (ftruncate(pool->fd, size) == -1)
+ return -1;
+
+ /* First try to see if mremap can grow the map in place. */
+ map = MAP_FAILED;
+ if (pool->size > 0)
+ map = mremap(pool->map, pool->size, size, 0);
+ if (map == MAP_FAILED) {
+ /* Just leak the old map until we destroy the pool. We can't munmap it
+ * without races or imposing locking on the block allocate fast path. On
+ * the whole the leaked maps adds up to less than the size of the
+ * current map. MAP_POPULATE seems like the right thing to do, but we
+ * should try to get some numbers.
+ */
+ map = mmap(NULL, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_POPULATE, pool->fd, 0);
+ cleanup->map = map;
+ cleanup->size = size;
+ }
+ if (map == MAP_FAILED)
+ return -1;
+
+ gem_handle = anv_gem_userptr(pool->device, map, size);
+ if (gem_handle == 0)
+ return -1;
+ cleanup->gem_handle = gem_handle;
+
+ /* Now that we successfull allocated everything, we can write the new
+ * values back into pool. */
+ pool->map = map;
+ pool->bo.gem_handle = gem_handle;
+ pool->bo.size = size;
+ pool->bo.map = map;
+ pool->bo.index = 0;
+
+ /* Write size last and after the memory barrier here. We need the memory
+ * barrier to make sure map and gem_handle are written before other threads
+ * see the new size. A thread could allocate a block and then go try using
+ * the old pool->map and access out of bounds. */
+
+ __sync_synchronize();
+ pool->size = size;
+
+ return 0;
+}
+
+uint32_t
+anv_block_pool_alloc(struct anv_block_pool *pool)
+{
+ uint32_t offset, block, size;
+
+ /* Try free list first. */
+ if (anv_free_list_pop(&pool->free_list, &pool->map, &offset)) {
+ assert(pool->map);
+ return offset;
+ }
+
+ restart:
+ size = pool->size;
+ block = __sync_fetch_and_add(&pool->next_block, pool->block_size);
+ if (block < size) {
+ assert(pool->map);
+ return block;
+ } else if (block == size) {
+ /* We allocated the first block outside the pool, we have to grow it.
+ * pool->next_block acts a mutex: threads who try to allocate now will
+ * get block indexes above the current limit and hit futex_wait
+ * below. */
+ int err = anv_block_pool_grow(pool);
+ assert(err == 0);
+ (void) err;
+ futex_wake(&pool->size, INT_MAX);
+ } else {
+ futex_wait(&pool->size, size);
+ __sync_fetch_and_add(&pool->next_block, -pool->block_size);
+ goto restart;
+ }
+
+ return block;
+}
+
+void
+anv_block_pool_free(struct anv_block_pool *pool, uint32_t offset)
+{
+ anv_free_list_push(&pool->free_list, pool->map, offset);
+}
+
+static void
+anv_fixed_size_state_pool_init(struct anv_fixed_size_state_pool *pool,
+ size_t state_size)
+{
+ /* At least a cache line and must divide the block size. */
+ assert(state_size >= 64 && is_power_of_two(state_size));
+
+ pool->state_size = state_size;
+ pool->free_list = ANV_FREE_LIST_EMPTY;
+ pool->block.next = 0;
+ pool->block.end = 0;
+}
+
+static uint32_t
+anv_fixed_size_state_pool_alloc(struct anv_fixed_size_state_pool *pool,
+ struct anv_block_pool *block_pool)
+{
+ uint32_t offset;
+ struct anv_block_state block, old, new;
+
+ /* Try free list first. */
+ if (anv_free_list_pop(&pool->free_list, &block_pool->map, &offset))
+ return offset;
+
+ /* If free list was empty (or somebody raced us and took the items) we
+ * allocate a new item from the end of the block */
+ restart:
+ block.u64 = __sync_fetch_and_add(&pool->block.u64, pool->state_size);
+
+ if (block.next < block.end) {
+ return block.next;
+ } else if (block.next == block.end) {
+ new.next = anv_block_pool_alloc(block_pool);
+ new.end = new.next + block_pool->block_size;
+ old.u64 = __sync_fetch_and_add(&pool->block.u64, new.u64 - block.u64);
+ if (old.next != block.next)
+ futex_wake(&pool->block.end, INT_MAX);
+ return new.next;
+ } else {
+ futex_wait(&pool->block.end, block.end);
+ __sync_fetch_and_add(&pool->block.u64, -pool->state_size);
+ goto restart;
+ }
+}
+
+static void
+anv_fixed_size_state_pool_free(struct anv_fixed_size_state_pool *pool,
+ struct anv_block_pool *block_pool,
+ uint32_t offset)
+{
+ anv_free_list_push(&pool->free_list, block_pool->map, offset);
+}
+
+void
+anv_state_pool_init(struct anv_state_pool *pool,
+ struct anv_block_pool *block_pool)
+{
+ pool->block_pool = block_pool;
+ for (unsigned i = 0; i < ANV_STATE_BUCKETS; i++) {
+ size_t size = 1 << (ANV_MIN_STATE_SIZE_LOG2 + i);
+ anv_fixed_size_state_pool_init(&pool->buckets[i], size);
+ }
+}
+
+struct anv_state
+anv_state_pool_alloc(struct anv_state_pool *pool, size_t size, size_t align)
+{
+ unsigned size_log2 = ilog2_round_up(size < align ? align : size);
+ assert(size_log2 <= ANV_MAX_STATE_SIZE_LOG2);
+ if (size_log2 < ANV_MIN_STATE_SIZE_LOG2)
+ size_log2 = ANV_MIN_STATE_SIZE_LOG2;
+ unsigned bucket = size_log2 - ANV_MIN_STATE_SIZE_LOG2;
+
+ struct anv_state state;
+ state.alloc_size = 1 << size_log2;
+ state.offset = anv_fixed_size_state_pool_alloc(&pool->buckets[bucket],
+ pool->block_pool);
+ state.map = pool->block_pool->map + state.offset;
+ VG(VALGRIND_MALLOCLIKE_BLOCK(state.map, size, 0, false));
+ return state;
+}
+
+void
+anv_state_pool_free(struct anv_state_pool *pool, struct anv_state state)
+{
+ assert(is_power_of_two(state.alloc_size));
+ unsigned size_log2 = ilog2_round_up(state.alloc_size);
+ assert(size_log2 >= ANV_MIN_STATE_SIZE_LOG2 &&
+ size_log2 <= ANV_MAX_STATE_SIZE_LOG2);
+ unsigned bucket = size_log2 - ANV_MIN_STATE_SIZE_LOG2;
+
+ VG(VALGRIND_FREELIKE_BLOCK(state.map, 0));
+ anv_fixed_size_state_pool_free(&pool->buckets[bucket],
+ pool->block_pool, state.offset);
+}
+
+#define NULL_BLOCK 1
+struct stream_block {
+ uint32_t next;
+
+ /* The map for the BO at the time the block was givne to us */
+ void *current_map;
+
+#ifdef HAVE_VALGRIND
+ void *_vg_ptr;
+#endif
+};
+
+/* The state stream allocator is a one-shot, single threaded allocator for
+ * variable sized blocks. We use it for allocating dynamic state.
+ */
+void
+anv_state_stream_init(struct anv_state_stream *stream,
+ struct anv_block_pool *block_pool)
+{
+ stream->block_pool = block_pool;
+ stream->next = 0;
+ stream->end = 0;
+ stream->current_block = NULL_BLOCK;
+}
+
+void
+anv_state_stream_finish(struct anv_state_stream *stream)
+{
+ struct stream_block *sb;
+ uint32_t block, next_block;
+
+ block = stream->current_block;
+ while (block != NULL_BLOCK) {
+ sb = stream->block_pool->map + block;
+ next_block = VG_NOACCESS_READ(&sb->next);
+ VG(VALGRIND_FREELIKE_BLOCK(VG_NOACCESS_READ(&sb->_vg_ptr), 0));
+ anv_block_pool_free(stream->block_pool, block);
+ block = next_block;
+ }
+}
+
+struct anv_state
+anv_state_stream_alloc(struct anv_state_stream *stream,
+ uint32_t size, uint32_t alignment)
+{
+ struct stream_block *sb;
+ struct anv_state state;
+ uint32_t block;
+
+ state.offset = align_u32(stream->next, alignment);
+ if (state.offset + size > stream->end) {
+ block = anv_block_pool_alloc(stream->block_pool);
+ void *current_map = stream->block_pool->map;
+ sb = current_map + block;
+ VG_NOACCESS_WRITE(&sb->current_map, current_map);
+ VG_NOACCESS_WRITE(&sb->next, stream->current_block);
+ VG(VG_NOACCESS_WRITE(&sb->_vg_ptr, 0));
+ stream->current_block = block;
+ stream->next = block + sizeof(*sb);
+ stream->end = block + stream->block_pool->block_size;
+ state.offset = align_u32(stream->next, alignment);
+ assert(state.offset + size <= stream->end);
+ }
+
+ sb = stream->block_pool->map + stream->current_block;
+ void *current_map = VG_NOACCESS_READ(&sb->current_map);
+
+ state.map = current_map + state.offset;
+ state.alloc_size = size;
+
+#ifdef HAVE_VALGRIND
+ void *vg_ptr = VG_NOACCESS_READ(&sb->_vg_ptr);
+ if (vg_ptr == NULL) {
+ vg_ptr = state.map;
+ VG_NOACCESS_WRITE(&sb->_vg_ptr, vg_ptr);
+ VALGRIND_MALLOCLIKE_BLOCK(vg_ptr, size, 0, false);
+ } else {
+ ptrdiff_t vg_offset = vg_ptr - current_map;
+ assert(vg_offset >= stream->current_block &&
+ vg_offset < stream->end);
+ VALGRIND_RESIZEINPLACE_BLOCK(vg_ptr,
+ stream->next - vg_offset,
+ (state.offset + size) - vg_offset,
+ 0);
+ }
+#endif
+
+ stream->next = state.offset + size;
+
+ return state;
+}
+
+struct bo_pool_bo_link {
+ struct bo_pool_bo_link *next;
+ struct anv_bo bo;
+};
+
+void
+anv_bo_pool_init(struct anv_bo_pool *pool,
+ struct anv_device *device, uint32_t bo_size)
+{
+ pool->device = device;
+ pool->bo_size = bo_size;
+ pool->free_list = NULL;
+}
+
+void
+anv_bo_pool_finish(struct anv_bo_pool *pool)
+{
+ struct bo_pool_bo_link *link = PFL_PTR(pool->free_list);
+ while (link != NULL) {
+ struct bo_pool_bo_link link_copy = VG_NOACCESS_READ(link);
+
+ /* The anv_gem_m[un]map() functions are also valgrind-safe so they
+ * act as an alloc/free. In order to avoid a double-free warning, we
+ * need to mark thiss as malloc'd before we unmap it.
+ */
+ VG(VALGRIND_MALLOCLIKE_BLOCK(link_copy.bo.map, pool->bo_size, 0, false));
+
+ anv_gem_munmap(link_copy.bo.map, pool->bo_size);
+ anv_gem_close(pool->device, link_copy.bo.gem_handle);
+ link = link_copy.next;
+ }
+}
+
+VkResult
+anv_bo_pool_alloc(struct anv_bo_pool *pool, struct anv_bo *bo)
+{
+ VkResult result;
+
+ void *next_free_void;
+ if (anv_ptr_free_list_pop(&pool->free_list, &next_free_void)) {
+ struct bo_pool_bo_link *next_free = next_free_void;
+ *bo = VG_NOACCESS_READ(&next_free->bo);
+ assert(bo->map == next_free);
+ assert(bo->size == pool->bo_size);
+
+ VG(VALGRIND_MALLOCLIKE_BLOCK(bo->map, pool->bo_size, 0, false));
+
+ return VK_SUCCESS;
+ }
+
+ struct anv_bo new_bo;
+
+ result = anv_bo_init_new(&new_bo, pool->device, pool->bo_size);
+ if (result != VK_SUCCESS)
+ return result;
+
+ assert(new_bo.size == pool->bo_size);
+
+ new_bo.map = anv_gem_mmap(pool->device, new_bo.gem_handle, 0, pool->bo_size);
+ if (new_bo.map == NULL) {
+ anv_gem_close(pool->device, new_bo.gem_handle);
+ return vk_error(VK_ERROR_MEMORY_MAP_FAILED);
+ }
+
+ /* We don't need to call VALGRIND_MALLOCLIKE_BLOCK here because gem_mmap
+ * calls it for us. If we really want to be pedantic we could do a
+ * VALGRIND_FREELIKE_BLOCK right after the mmap, but there's no good
+ * reason.
+ */
+
+ *bo = new_bo;
+ return VK_SUCCESS;
+}
+
+void
+anv_bo_pool_free(struct anv_bo_pool *pool, const struct anv_bo *bo)
+{
+ struct bo_pool_bo_link *link = bo->map;
+ link->bo = *bo;
+
+ VG(VALGRIND_FREELIKE_BLOCK(bo->map, 0));
+ anv_ptr_free_list_push(&pool->free_list, link);
+}
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <drm.h>
+#include <i915_drm.h>
+
+#include "anv_private.h"
+#include "anv_aub.h"
+
+struct anv_aub_writer {
+ FILE *file;
+ uint32_t offset;
+ int gen;
+};
+
+static void
+aub_out(struct anv_aub_writer *writer, uint32_t data)
+{
+ fwrite(&data, 1, 4, writer->file);
+}
+
+static void
+aub_out_data(struct anv_aub_writer *writer, const void *data, size_t size)
+{
+ fwrite(data, 1, size, writer->file);
+}
+
+static struct anv_aub_writer *
+get_anv_aub_writer(struct anv_device *device)
+{
+ struct anv_aub_writer *writer = device->aub_writer;
+ int entry = 0x200003;
+ int i;
+ int gtt_size = 0x10000;
+ const char *filename;
+
+ if (geteuid() != getuid())
+ return NULL;
+
+ if (writer)
+ return writer;
+
+ writer = malloc(sizeof(*writer));
+ if (writer == NULL)
+ return NULL;
+
+ filename = "intel.aub";
+ writer->gen = device->info.gen;
+ writer->file = fopen(filename, "w+");
+ if (!writer->file) {
+ free(writer);
+ return NULL;
+ }
+
+ /* Start allocating objects from just after the GTT. */
+ writer->offset = gtt_size;
+
+ /* Start with a (required) version packet. */
+ aub_out(writer, CMD_AUB_HEADER | (13 - 2));
+ aub_out(writer,
+ (4 << AUB_HEADER_MAJOR_SHIFT) |
+ (0 << AUB_HEADER_MINOR_SHIFT));
+ for (i = 0; i < 8; i++) {
+ aub_out(writer, 0); /* app name */
+ }
+ aub_out(writer, 0); /* timestamp */
+ aub_out(writer, 0); /* timestamp */
+ aub_out(writer, 0); /* comment len */
+
+ /* Set up the GTT. The max we can handle is 256M */
+ aub_out(writer, CMD_AUB_TRACE_HEADER_BLOCK | ((writer->gen >= 8 ? 6 : 5) - 2));
+ aub_out(writer,
+ AUB_TRACE_MEMTYPE_GTT_ENTRY |
+ AUB_TRACE_TYPE_NOTYPE | AUB_TRACE_OP_DATA_WRITE);
+ aub_out(writer, 0); /* subtype */
+ aub_out(writer, 0); /* offset */
+ aub_out(writer, gtt_size); /* size */
+ if (writer->gen >= 8)
+ aub_out(writer, 0);
+ for (i = 0x000; i < gtt_size; i += 4, entry += 0x1000) {
+ aub_out(writer, entry);
+ }
+
+ return device->aub_writer = writer;
+}
+
+void
+anv_aub_writer_destroy(struct anv_aub_writer *writer)
+{
+ fclose(writer->file);
+ free(writer);
+}
+
+
+/**
+ * Break up large objects into multiple writes. Otherwise a 128kb VBO
+ * would overflow the 16 bits of size field in the packet header and
+ * everything goes badly after that.
+ */
+static void
+aub_write_trace_block(struct anv_aub_writer *writer, uint32_t type,
+ void *virtual, uint32_t size, uint32_t gtt_offset)
+{
+ uint32_t block_size;
+ uint32_t offset;
+ uint32_t subtype = 0;
+ static const char null_block[8 * 4096];
+
+ for (offset = 0; offset < size; offset += block_size) {
+ block_size = size - offset;
+
+ if (block_size > 8 * 4096)
+ block_size = 8 * 4096;
+
+ aub_out(writer,
+ CMD_AUB_TRACE_HEADER_BLOCK |
+ ((writer->gen >= 8 ? 6 : 5) - 2));
+ aub_out(writer,
+ AUB_TRACE_MEMTYPE_GTT |
+ type | AUB_TRACE_OP_DATA_WRITE);
+ aub_out(writer, subtype);
+ aub_out(writer, gtt_offset + offset);
+ aub_out(writer, align_u32(block_size, 4));
+ if (writer->gen >= 8)
+ aub_out(writer, 0);
+
+ if (virtual)
+ aub_out_data(writer, (char *) virtual + offset, block_size);
+ else
+ aub_out_data(writer, null_block, block_size);
+
+ /* Pad to a multiple of 4 bytes. */
+ aub_out_data(writer, null_block, -block_size & 3);
+ }
+}
+
+/*
+ * Make a ringbuffer on fly and dump it
+ */
+static void
+aub_build_dump_ringbuffer(struct anv_aub_writer *writer,
+ uint32_t batch_offset, uint32_t offset,
+ int ring_flag)
+{
+ uint32_t ringbuffer[4096];
+ int ring = AUB_TRACE_TYPE_RING_PRB0; /* The default ring */
+ int ring_count = 0;
+
+ if (ring_flag == I915_EXEC_BSD)
+ ring = AUB_TRACE_TYPE_RING_PRB1;
+ else if (ring_flag == I915_EXEC_BLT)
+ ring = AUB_TRACE_TYPE_RING_PRB2;
+
+ /* Make a ring buffer to execute our batchbuffer. */
+ memset(ringbuffer, 0, sizeof(ringbuffer));
+ if (writer->gen >= 8) {
+ ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START | (3 - 2);
+ ringbuffer[ring_count++] = batch_offset;
+ ringbuffer[ring_count++] = 0;
+ } else {
+ ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START;
+ ringbuffer[ring_count++] = batch_offset;
+ }
+
+ /* Write out the ring. This appears to trigger execution of
+ * the ring in the simulator.
+ */
+ aub_out(writer,
+ CMD_AUB_TRACE_HEADER_BLOCK |
+ ((writer->gen >= 8 ? 6 : 5) - 2));
+ aub_out(writer,
+ AUB_TRACE_MEMTYPE_GTT | ring | AUB_TRACE_OP_COMMAND_WRITE);
+ aub_out(writer, 0); /* general/surface subtype */
+ aub_out(writer, offset);
+ aub_out(writer, ring_count * 4);
+ if (writer->gen >= 8)
+ aub_out(writer, 0);
+
+ /* FIXME: Need some flush operations here? */
+ aub_out_data(writer, ringbuffer, ring_count * 4);
+}
+
+struct aub_bo {
+ uint32_t offset;
+ void *map;
+ void *relocated;
+};
+
+static void
+relocate_bo(struct anv_bo *bo, struct drm_i915_gem_relocation_entry *relocs,
+ size_t num_relocs, struct aub_bo *bos)
+{
+ struct aub_bo *aub_bo = &bos[bo->index];
+ struct drm_i915_gem_relocation_entry *reloc;
+ uint32_t *dw;
+
+ aub_bo->relocated = malloc(bo->size);
+ memcpy(aub_bo->relocated, aub_bo->map, bo->size);
+ for (size_t i = 0; i < num_relocs; i++) {
+ reloc = &relocs[i];
+ assert(reloc->offset < bo->size);
+ dw = aub_bo->relocated + reloc->offset;
+ *dw = bos[reloc->target_handle].offset + reloc->delta;
+ }
+}
+
+void
+anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer)
+{
+ struct anv_device *device = cmd_buffer->device;
+ struct anv_batch *batch = &cmd_buffer->batch;
+ struct anv_aub_writer *writer;
+ struct anv_bo *bo;
+ uint32_t ring_flag = 0;
+ uint32_t offset;
+ struct aub_bo *aub_bos;
+
+ writer = get_anv_aub_writer(device);
+ if (writer == NULL)
+ return;
+
+ aub_bos = malloc(cmd_buffer->exec2_bo_count * sizeof(aub_bos[0]));
+ offset = writer->offset;
+ for (uint32_t i = 0; i < cmd_buffer->exec2_bo_count; i++) {
+ bo = cmd_buffer->exec2_bos[i];
+ if (bo->map)
+ aub_bos[i].map = bo->map;
+ else
+ aub_bos[i].map = anv_gem_mmap(device, bo->gem_handle, 0, bo->size);
+ aub_bos[i].relocated = aub_bos[i].map;
+ aub_bos[i].offset = offset;
+ offset = align_u32(offset + bo->size + 4095, 4096);
+ }
+
+ struct anv_batch_bo *first_bbo;
+ for (struct anv_batch_bo *bbo = cmd_buffer->last_batch_bo;
+ bbo != NULL; bbo = bbo->prev_batch_bo) {
+ /* Keep stashing the current BO until we get to the beginning */
+ first_bbo = bbo;
+
+ /* Handle relocations for this batch BO */
+ relocate_bo(&bbo->bo, &batch->relocs.relocs[bbo->first_reloc],
+ bbo->num_relocs, aub_bos);
+ }
+ assert(first_bbo->prev_batch_bo == NULL);
+
+ for (struct anv_batch_bo *bbo = cmd_buffer->surface_batch_bo;
+ bbo != NULL; bbo = bbo->prev_batch_bo) {
+
+ /* Handle relocations for this surface state BO */
+ relocate_bo(&bbo->bo,
+ &cmd_buffer->surface_relocs.relocs[bbo->first_reloc],
+ bbo->num_relocs, aub_bos);
+ }
+
+ for (uint32_t i = 0; i < cmd_buffer->exec2_bo_count; i++) {
+ bo = cmd_buffer->exec2_bos[i];
+ if (i == cmd_buffer->exec2_bo_count - 1) {
+ assert(bo == &first_bbo->bo);
+ aub_write_trace_block(writer, AUB_TRACE_TYPE_BATCH,
+ aub_bos[i].relocated,
+ first_bbo->length, aub_bos[i].offset);
+ } else {
+ aub_write_trace_block(writer, AUB_TRACE_TYPE_NOTYPE,
+ aub_bos[i].relocated,
+ bo->size, aub_bos[i].offset);
+ }
+ if (aub_bos[i].relocated != aub_bos[i].map)
+ free(aub_bos[i].relocated);
+ if (aub_bos[i].map != bo->map)
+ anv_gem_munmap(aub_bos[i].map, bo->size);
+ }
+
+ /* Dump ring buffer */
+ aub_build_dump_ringbuffer(writer, aub_bos[first_bbo->bo.index].offset,
+ offset, ring_flag);
+
+ free(aub_bos);
+
+ fflush(writer->file);
+}
--- /dev/null
+/*
+ * 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.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file intel_aub.h
+ *
+ * The AUB file is a file format used by Intel's internal simulation
+ * and other validation tools. It can be used at various levels by a
+ * driver to input state to the simulated hardware or a replaying
+ * debugger.
+ *
+ * We choose to dump AUB files using the trace block format for ease
+ * of implementation -- dump out the blocks of memory as plain blobs
+ * and insert ring commands to execute the batchbuffer blob.
+ */
+
+#ifndef _INTEL_AUB_H
+#define _INTEL_AUB_H
+
+#define AUB_MI_NOOP (0)
+#define AUB_MI_BATCH_BUFFER_START (0x31 << 23)
+#define AUB_PIPE_CONTROL (0x7a000002)
+
+/* DW0: instruction type. */
+
+#define CMD_AUB (7 << 29)
+
+#define CMD_AUB_HEADER (CMD_AUB | (1 << 23) | (0x05 << 16))
+/* DW1 */
+# define AUB_HEADER_MAJOR_SHIFT 24
+# define AUB_HEADER_MINOR_SHIFT 16
+
+#define CMD_AUB_TRACE_HEADER_BLOCK (CMD_AUB | (1 << 23) | (0x41 << 16))
+#define CMD_AUB_DUMP_BMP (CMD_AUB | (1 << 23) | (0x9e << 16))
+
+/* DW1 */
+#define AUB_TRACE_OPERATION_MASK 0x000000ff
+#define AUB_TRACE_OP_COMMENT 0x00000000
+#define AUB_TRACE_OP_DATA_WRITE 0x00000001
+#define AUB_TRACE_OP_COMMAND_WRITE 0x00000002
+#define AUB_TRACE_OP_MMIO_WRITE 0x00000003
+// operation = TRACE_DATA_WRITE, Type
+#define AUB_TRACE_TYPE_MASK 0x0000ff00
+#define AUB_TRACE_TYPE_NOTYPE (0 << 8)
+#define AUB_TRACE_TYPE_BATCH (1 << 8)
+#define AUB_TRACE_TYPE_VERTEX_BUFFER (5 << 8)
+#define AUB_TRACE_TYPE_2D_MAP (6 << 8)
+#define AUB_TRACE_TYPE_CUBE_MAP (7 << 8)
+#define AUB_TRACE_TYPE_VOLUME_MAP (9 << 8)
+#define AUB_TRACE_TYPE_1D_MAP (10 << 8)
+#define AUB_TRACE_TYPE_CONSTANT_BUFFER (11 << 8)
+#define AUB_TRACE_TYPE_CONSTANT_URB (12 << 8)
+#define AUB_TRACE_TYPE_INDEX_BUFFER (13 << 8)
+#define AUB_TRACE_TYPE_GENERAL (14 << 8)
+#define AUB_TRACE_TYPE_SURFACE (15 << 8)
+
+
+// operation = TRACE_COMMAND_WRITE, Type =
+#define AUB_TRACE_TYPE_RING_HWB (1 << 8)
+#define AUB_TRACE_TYPE_RING_PRB0 (2 << 8)
+#define AUB_TRACE_TYPE_RING_PRB1 (3 << 8)
+#define AUB_TRACE_TYPE_RING_PRB2 (4 << 8)
+
+// Address space
+#define AUB_TRACE_ADDRESS_SPACE_MASK 0x00ff0000
+#define AUB_TRACE_MEMTYPE_GTT (0 << 16)
+#define AUB_TRACE_MEMTYPE_LOCAL (1 << 16)
+#define AUB_TRACE_MEMTYPE_NONLOCAL (2 << 16)
+#define AUB_TRACE_MEMTYPE_PCI (3 << 16)
+#define AUB_TRACE_MEMTYPE_GTT_ENTRY (4 << 16)
+
+/* DW2 */
+
+/**
+ * aub_state_struct_type enum values are encoded with the top 16 bits
+ * representing the type to be delivered to the .aub file, and the bottom 16
+ * bits representing the subtype. This macro performs the encoding.
+ */
+#define ENCODE_SS_TYPE(type, subtype) (((type) << 16) | (subtype))
+
+enum aub_state_struct_type {
+ AUB_TRACE_VS_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 1),
+ AUB_TRACE_GS_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 2),
+ AUB_TRACE_CLIP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 3),
+ AUB_TRACE_SF_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 4),
+ AUB_TRACE_WM_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 5),
+ AUB_TRACE_CC_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 6),
+ AUB_TRACE_CLIP_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 7),
+ AUB_TRACE_SF_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 8),
+ AUB_TRACE_CC_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x9),
+ AUB_TRACE_SAMPLER_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xa),
+ AUB_TRACE_KERNEL_INSTRUCTIONS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xb),
+ AUB_TRACE_SCRATCH_SPACE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xc),
+ AUB_TRACE_SAMPLER_DEFAULT_COLOR = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xd),
+
+ AUB_TRACE_SCISSOR_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x15),
+ AUB_TRACE_BLEND_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x16),
+ AUB_TRACE_DEPTH_STENCIL_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x17),
+
+ AUB_TRACE_VERTEX_BUFFER = ENCODE_SS_TYPE(AUB_TRACE_TYPE_VERTEX_BUFFER, 0),
+ AUB_TRACE_BINDING_TABLE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_SURFACE, 0x100),
+ AUB_TRACE_SURFACE_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_SURFACE, 0x200),
+ AUB_TRACE_VS_CONSTANTS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_CONSTANT_BUFFER, 0),
+ AUB_TRACE_WM_CONSTANTS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_CONSTANT_BUFFER, 1),
+};
+
+#undef ENCODE_SS_TYPE
+
+/**
+ * Decode a aub_state_struct_type value to determine the type that should be
+ * stored in the .aub file.
+ */
+static inline uint32_t AUB_TRACE_TYPE(enum aub_state_struct_type ss_type)
+{
+ return (ss_type & 0xFFFF0000) >> 16;
+}
+
+/**
+ * Decode a state_struct_type value to determine the subtype that should be
+ * stored in the .aub file.
+ */
+static inline uint32_t AUB_TRACE_SUBTYPE(enum aub_state_struct_type ss_type)
+{
+ return ss_type & 0xFFFF;
+}
+
+/* DW3: address */
+/* DW4: len */
+
+#endif /* _INTEL_AUB_H */
#include <unistd.h>
#include <fcntl.h>
-#include "private.h"
+#include "anv_private.h"
/** \file anv_cmd_buffer.c
*
#include <unistd.h>
#include <fcntl.h>
-#include "private.h"
+#include "anv_private.h"
/** \file anv_cmd_buffer.c
*
--- /dev/null
+/*
+ * 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 <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "anv_private.h"
+
+#include <brw_context.h>
+#include <brw_wm.h> /* brw_new_shader_program is here */
+#include <brw_nir.h>
+
+#include <brw_vs.h>
+#include <brw_gs.h>
+#include <brw_cs.h>
+
+#include <mesa/main/shaderobj.h>
+#include <mesa/main/fbobject.h>
+#include <mesa/main/context.h>
+#include <mesa/program/program.h>
+#include <glsl/program.h>
+
+/* XXX: We need this to keep symbols in nir.h from conflicting with the
+ * generated GEN command packing headers. We need to fix *both* to not
+ * define something as generic as LOAD.
+ */
+#undef LOAD
+
+#include <glsl/nir/nir_spirv.h>
+
+#define SPIR_V_MAGIC_NUMBER 0x07230203
+
+static void
+fail_if(int cond, const char *format, ...)
+{
+ va_list args;
+
+ if (!cond)
+ return;
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+
+ exit(1);
+}
+
+static VkResult
+set_binding_table_layout(struct brw_stage_prog_data *prog_data,
+ struct anv_pipeline *pipeline, uint32_t stage)
+{
+ uint32_t bias, count, k, *map;
+ struct anv_pipeline_layout *layout = pipeline->layout;
+
+ /* No layout is valid for shaders that don't bind any resources. */
+ if (pipeline->layout == NULL)
+ return VK_SUCCESS;
+
+ if (stage == VK_SHADER_STAGE_FRAGMENT)
+ bias = MAX_RTS;
+ else
+ bias = 0;
+
+ count = layout->stage[stage].surface_count;
+ prog_data->map_entries =
+ (uint32_t *) malloc(count * sizeof(prog_data->map_entries[0]));
+ if (prog_data->map_entries == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ k = bias;
+ map = prog_data->map_entries;
+ for (uint32_t i = 0; i < layout->num_sets; i++) {
+ prog_data->bind_map[i].index = map;
+ for (uint32_t j = 0; j < layout->set[i].layout->stage[stage].surface_count; j++)
+ *map++ = k++;
+
+ prog_data->bind_map[i].index_count =
+ layout->set[i].layout->stage[stage].surface_count;
+ }
+
+ return VK_SUCCESS;
+}
+
+static void
+brw_vs_populate_key(struct brw_context *brw,
+ struct brw_vertex_program *vp,
+ struct brw_vs_prog_key *key)
+{
+ struct gl_context *ctx = &brw->ctx;
+ /* BRW_NEW_VERTEX_PROGRAM */
+ struct gl_program *prog = (struct gl_program *) vp;
+
+ memset(key, 0, sizeof(*key));
+
+ /* Just upload the program verbatim for now. Always send it all
+ * the inputs it asks for, whether they are varying or not.
+ */
+ key->base.program_string_id = vp->id;
+ brw_setup_vue_key_clip_info(brw, &key->base,
+ vp->program.Base.UsesClipDistanceOut);
+
+ /* _NEW_POLYGON */
+ if (brw->gen < 6) {
+ key->copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL);
+ }
+
+ if (prog->OutputsWritten & (VARYING_BIT_COL0 | VARYING_BIT_COL1 |
+ VARYING_BIT_BFC0 | VARYING_BIT_BFC1)) {
+ /* _NEW_LIGHT | _NEW_BUFFERS */
+ key->clamp_vertex_color = ctx->Light._ClampVertexColor;
+ }
+
+ /* _NEW_POINT */
+ if (brw->gen < 6 && ctx->Point.PointSprite) {
+ for (int i = 0; i < 8; i++) {
+ if (ctx->Point.CoordReplace[i])
+ key->point_coord_replace |= (1 << i);
+ }
+ }
+
+ /* _NEW_TEXTURE */
+ brw_populate_sampler_prog_key_data(ctx, prog, brw->vs.base.sampler_count,
+ &key->base.tex);
+}
+
+static bool
+really_do_vs_prog(struct brw_context *brw,
+ struct gl_shader_program *prog,
+ struct brw_vertex_program *vp,
+ struct brw_vs_prog_key *key, struct anv_pipeline *pipeline)
+{
+ GLuint program_size;
+ const GLuint *program;
+ struct brw_vs_compile c;
+ struct brw_vs_prog_data *prog_data = &pipeline->vs_prog_data;
+ struct brw_stage_prog_data *stage_prog_data = &prog_data->base.base;
+ void *mem_ctx;
+ struct gl_shader *vs = NULL;
+
+ if (prog)
+ vs = prog->_LinkedShaders[MESA_SHADER_VERTEX];
+
+ memset(&c, 0, sizeof(c));
+ memcpy(&c.key, key, sizeof(*key));
+ memset(prog_data, 0, sizeof(*prog_data));
+
+ mem_ctx = ralloc_context(NULL);
+
+ c.vp = vp;
+
+ /* Allocate the references to the uniforms that will end up in the
+ * prog_data associated with the compiled program, and which will be freed
+ * by the state cache.
+ */
+ int param_count;
+ if (vs) {
+ /* We add padding around uniform values below vec4 size, with the worst
+ * case being a float value that gets blown up to a vec4, so be
+ * conservative here.
+ */
+ param_count = vs->num_uniform_components * 4;
+
+ } else {
+ param_count = vp->program.Base.Parameters->NumParameters * 4;
+ }
+ /* vec4_visitor::setup_uniform_clipplane_values() also uploads user clip
+ * planes as uniforms.
+ */
+ param_count += c.key.base.nr_userclip_plane_consts * 4;
+
+ /* Setting nr_params here NOT to the size of the param and pull_param
+ * arrays, but to the number of uniform components vec4_visitor
+ * needs. vec4_visitor::setup_uniforms() will set it back to a proper value.
+ */
+ stage_prog_data->nr_params = ALIGN(param_count, 4) / 4;
+ if (vs) {
+ stage_prog_data->nr_params += vs->num_samplers;
+ }
+
+ GLbitfield64 outputs_written = vp->program.Base.OutputsWritten;
+ prog_data->inputs_read = vp->program.Base.InputsRead;
+
+ if (c.key.copy_edgeflag) {
+ outputs_written |= BITFIELD64_BIT(VARYING_SLOT_EDGE);
+ prog_data->inputs_read |= VERT_BIT_EDGEFLAG;
+ }
+
+ if (brw->gen < 6) {
+ /* Put dummy slots into the VUE for the SF to put the replaced
+ * point sprite coords in. We shouldn't need these dummy slots,
+ * which take up precious URB space, but it would mean that the SF
+ * doesn't get nice aligned pairs of input coords into output
+ * coords, which would be a pain to handle.
+ */
+ for (int i = 0; i < 8; i++) {
+ if (c.key.point_coord_replace & (1 << i))
+ outputs_written |= BITFIELD64_BIT(VARYING_SLOT_TEX0 + i);
+ }
+
+ /* if back colors are written, allocate slots for front colors too */
+ if (outputs_written & BITFIELD64_BIT(VARYING_SLOT_BFC0))
+ outputs_written |= BITFIELD64_BIT(VARYING_SLOT_COL0);
+ if (outputs_written & BITFIELD64_BIT(VARYING_SLOT_BFC1))
+ outputs_written |= BITFIELD64_BIT(VARYING_SLOT_COL1);
+ }
+
+ /* In order for legacy clipping to work, we need to populate the clip
+ * distance varying slots whenever clipping is enabled, even if the vertex
+ * shader doesn't write to gl_ClipDistance.
+ */
+ if (c.key.base.userclip_active) {
+ outputs_written |= BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST0);
+ outputs_written |= BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST1);
+ }
+
+ brw_compute_vue_map(brw->intelScreen->devinfo,
+ &prog_data->base.vue_map, outputs_written);
+\
+ set_binding_table_layout(&prog_data->base.base, pipeline,
+ VK_SHADER_STAGE_VERTEX);
+
+ /* Emit GEN4 code.
+ */
+ program = brw_vs_emit(brw, prog, &c, prog_data, mem_ctx, &program_size);
+ if (program == NULL) {
+ ralloc_free(mem_ctx);
+ return false;
+ }
+
+ struct anv_state vs_state = anv_state_stream_alloc(&pipeline->program_stream,
+ program_size, 64);
+ memcpy(vs_state.map, program, program_size);
+
+ pipeline->vs_simd8 = vs_state.offset;
+
+ ralloc_free(mem_ctx);
+
+ return true;
+}
+
+void brw_wm_populate_key(struct brw_context *brw,
+ struct brw_fragment_program *fp,
+ struct brw_wm_prog_key *key)
+{
+ struct gl_context *ctx = &brw->ctx;
+ struct gl_program *prog = (struct gl_program *) brw->fragment_program;
+ GLuint lookup = 0;
+ GLuint line_aa;
+ bool program_uses_dfdy = fp->program.UsesDFdy;
+ struct gl_framebuffer draw_buffer;
+ bool multisample_fbo;
+
+ memset(key, 0, sizeof(*key));
+
+ for (int i = 0; i < MAX_SAMPLERS; i++) {
+ /* Assume color sampler, no swizzling. */
+ key->tex.swizzles[i] = SWIZZLE_XYZW;
+ }
+
+ /* A non-zero framebuffer name indicates that the framebuffer was created by
+ * the user rather than the window system. */
+ draw_buffer.Name = 1;
+ draw_buffer.Visual.samples = 1;
+ draw_buffer._NumColorDrawBuffers = 1;
+ draw_buffer._NumColorDrawBuffers = 1;
+ draw_buffer.Width = 400;
+ draw_buffer.Height = 400;
+ ctx->DrawBuffer = &draw_buffer;
+
+ multisample_fbo = ctx->DrawBuffer->Visual.samples > 1;
+
+ /* Build the index for table lookup
+ */
+ if (brw->gen < 6) {
+ /* _NEW_COLOR */
+ if (fp->program.UsesKill || ctx->Color.AlphaEnabled)
+ lookup |= IZ_PS_KILL_ALPHATEST_BIT;
+
+ if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH))
+ lookup |= IZ_PS_COMPUTES_DEPTH_BIT;
+
+ /* _NEW_DEPTH */
+ if (ctx->Depth.Test)
+ lookup |= IZ_DEPTH_TEST_ENABLE_BIT;
+
+ if (ctx->Depth.Test && ctx->Depth.Mask) /* ?? */
+ lookup |= IZ_DEPTH_WRITE_ENABLE_BIT;
+
+ /* _NEW_STENCIL | _NEW_BUFFERS */
+ if (ctx->Stencil._Enabled) {
+ lookup |= IZ_STENCIL_TEST_ENABLE_BIT;
+
+ if (ctx->Stencil.WriteMask[0] ||
+ ctx->Stencil.WriteMask[ctx->Stencil._BackFace])
+ lookup |= IZ_STENCIL_WRITE_ENABLE_BIT;
+ }
+ key->iz_lookup = lookup;
+ }
+
+ line_aa = AA_NEVER;
+
+ /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */
+ if (ctx->Line.SmoothFlag) {
+ if (brw->reduced_primitive == GL_LINES) {
+ line_aa = AA_ALWAYS;
+ }
+ else if (brw->reduced_primitive == GL_TRIANGLES) {
+ if (ctx->Polygon.FrontMode == GL_LINE) {
+ line_aa = AA_SOMETIMES;
+
+ if (ctx->Polygon.BackMode == GL_LINE ||
+ (ctx->Polygon.CullFlag &&
+ ctx->Polygon.CullFaceMode == GL_BACK))
+ line_aa = AA_ALWAYS;
+ }
+ else if (ctx->Polygon.BackMode == GL_LINE) {
+ line_aa = AA_SOMETIMES;
+
+ if ((ctx->Polygon.CullFlag &&
+ ctx->Polygon.CullFaceMode == GL_FRONT))
+ line_aa = AA_ALWAYS;
+ }
+ }
+ }
+
+ key->line_aa = line_aa;
+
+ /* _NEW_HINT */
+ key->high_quality_derivatives =
+ ctx->Hint.FragmentShaderDerivative == GL_NICEST;
+
+ if (brw->gen < 6)
+ key->stats_wm = brw->stats_wm;
+
+ /* _NEW_LIGHT */
+ key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT);
+
+ /* _NEW_FRAG_CLAMP | _NEW_BUFFERS */
+ key->clamp_fragment_color = ctx->Color._ClampFragmentColor;
+
+ /* _NEW_TEXTURE */
+ brw_populate_sampler_prog_key_data(ctx, prog, brw->wm.base.sampler_count,
+ &key->tex);
+
+ /* _NEW_BUFFERS */
+ /*
+ * Include the draw buffer origin and height so that we can calculate
+ * fragment position values relative to the bottom left of the drawable,
+ * from the incoming screen origin relative position we get as part of our
+ * payload.
+ *
+ * This is only needed for the WM_WPOSXY opcode when the fragment program
+ * uses the gl_FragCoord input.
+ *
+ * We could avoid recompiling by including this as a constant referenced by
+ * our program, but if we were to do that it would also be nice to handle
+ * getting that constant updated at batchbuffer submit time (when we
+ * hold the lock and know where the buffer really is) rather than at emit
+ * time when we don't hold the lock and are just guessing. We could also
+ * just avoid using this as key data if the program doesn't use
+ * fragment.position.
+ *
+ * For DRI2 the origin_x/y will always be (0,0) but we still need the
+ * drawable height in order to invert the Y axis.
+ */
+ if (fp->program.Base.InputsRead & VARYING_BIT_POS) {
+ key->drawable_height = ctx->DrawBuffer->Height;
+ }
+
+ if ((fp->program.Base.InputsRead & VARYING_BIT_POS) || program_uses_dfdy) {
+ key->render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer);
+ }
+
+ /* _NEW_BUFFERS */
+ key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers;
+
+ /* _NEW_MULTISAMPLE, _NEW_COLOR, _NEW_BUFFERS */
+ key->replicate_alpha = ctx->DrawBuffer->_NumColorDrawBuffers > 1 &&
+ (ctx->Multisample.SampleAlphaToCoverage || ctx->Color.AlphaEnabled);
+
+ /* _NEW_BUFFERS _NEW_MULTISAMPLE */
+ /* Ignore sample qualifier while computing this flag. */
+ key->persample_shading =
+ _mesa_get_min_invocations_per_fragment(ctx, &fp->program, true) > 1;
+ if (key->persample_shading)
+ key->persample_2x = ctx->DrawBuffer->Visual.samples == 2;
+
+ key->compute_pos_offset =
+ _mesa_get_min_invocations_per_fragment(ctx, &fp->program, false) > 1 &&
+ fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_POS;
+
+ key->compute_sample_id =
+ multisample_fbo &&
+ ctx->Multisample.Enabled &&
+ (fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_ID);
+
+ /* BRW_NEW_VUE_MAP_GEOM_OUT */
+ if (brw->gen < 6 || _mesa_bitcount_64(fp->program.Base.InputsRead &
+ BRW_FS_VARYING_INPUT_MASK) > 16)
+ key->input_slots_valid = brw->vue_map_geom_out.slots_valid;
+
+
+ /* _NEW_COLOR | _NEW_BUFFERS */
+ /* Pre-gen6, the hardware alpha test always used each render
+ * target's alpha to do alpha test, as opposed to render target 0's alpha
+ * like GL requires. Fix that by building the alpha test into the
+ * shader, and we'll skip enabling the fixed function alpha test.
+ */
+ if (brw->gen < 6 && ctx->DrawBuffer->_NumColorDrawBuffers > 1 && ctx->Color.AlphaEnabled) {
+ key->alpha_test_func = ctx->Color.AlphaFunc;
+ key->alpha_test_ref = ctx->Color.AlphaRef;
+ }
+
+ /* The unique fragment program ID */
+ key->program_string_id = fp->id;
+
+ ctx->DrawBuffer = NULL;
+}
+
+static uint8_t
+computed_depth_mode(struct gl_fragment_program *fp)
+{
+ if (fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
+ switch (fp->FragDepthLayout) {
+ case FRAG_DEPTH_LAYOUT_NONE:
+ case FRAG_DEPTH_LAYOUT_ANY:
+ return BRW_PSCDEPTH_ON;
+ case FRAG_DEPTH_LAYOUT_GREATER:
+ return BRW_PSCDEPTH_ON_GE;
+ case FRAG_DEPTH_LAYOUT_LESS:
+ return BRW_PSCDEPTH_ON_LE;
+ case FRAG_DEPTH_LAYOUT_UNCHANGED:
+ return BRW_PSCDEPTH_OFF;
+ }
+ }
+ return BRW_PSCDEPTH_OFF;
+}
+
+static bool
+really_do_wm_prog(struct brw_context *brw,
+ struct gl_shader_program *prog,
+ struct brw_fragment_program *fp,
+ struct brw_wm_prog_key *key, struct anv_pipeline *pipeline)
+{
+ struct gl_context *ctx = &brw->ctx;
+ void *mem_ctx = ralloc_context(NULL);
+ struct brw_wm_prog_data *prog_data = &pipeline->wm_prog_data;
+ struct gl_shader *fs = NULL;
+ unsigned int program_size;
+ const uint32_t *program;
+
+ if (prog)
+ fs = prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
+
+ memset(prog_data, 0, sizeof(*prog_data));
+
+ /* key->alpha_test_func means simulating alpha testing via discards,
+ * so the shader definitely kills pixels.
+ */
+ prog_data->uses_kill = fp->program.UsesKill || key->alpha_test_func;
+
+ prog_data->computed_depth_mode = computed_depth_mode(&fp->program);
+
+ /* Allocate the references to the uniforms that will end up in the
+ * prog_data associated with the compiled program, and which will be freed
+ * by the state cache.
+ */
+ int param_count;
+ if (fs) {
+ param_count = fs->num_uniform_components;
+ } else {
+ param_count = fp->program.Base.Parameters->NumParameters * 4;
+ }
+ /* The backend also sometimes adds params for texture size. */
+ param_count += 2 * ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits;
+ prog_data->base.param =
+ rzalloc_array(NULL, const gl_constant_value *, param_count);
+ prog_data->base.pull_param =
+ rzalloc_array(NULL, const gl_constant_value *, param_count);
+ prog_data->base.nr_params = param_count;
+
+ prog_data->barycentric_interp_modes =
+ brw_compute_barycentric_interp_modes(brw, key->flat_shade,
+ key->persample_shading,
+ &fp->program);
+
+ set_binding_table_layout(&prog_data->base, pipeline,
+ VK_SHADER_STAGE_FRAGMENT);
+ /* This needs to come after shader time and pull constant entries, but we
+ * don't have those set up now, so just put it after the layout entries.
+ */
+ prog_data->binding_table.render_target_start = 0;
+
+ program = brw_wm_fs_emit(brw, mem_ctx, key, prog_data,
+ &fp->program, prog, &program_size);
+ if (program == NULL) {
+ ralloc_free(mem_ctx);
+ return false;
+ }
+
+ struct anv_state ps_state = anv_state_stream_alloc(&pipeline->program_stream,
+ program_size, 64);
+ memcpy(ps_state.map, program, program_size);
+
+ if (prog_data->no_8)
+ pipeline->ps_simd8 = NO_KERNEL;
+ else
+ pipeline->ps_simd8 = ps_state.offset;
+
+ if (prog_data->no_8 || prog_data->prog_offset_16) {
+ pipeline->ps_simd16 = ps_state.offset + prog_data->prog_offset_16;
+ } else {
+ pipeline->ps_simd16 = NO_KERNEL;
+ }
+
+ ralloc_free(mem_ctx);
+
+ return true;
+}
+
+static void
+brw_gs_populate_key(struct brw_context *brw,
+ struct anv_pipeline *pipeline,
+ struct brw_geometry_program *gp,
+ struct brw_gs_prog_key *key)
+{
+ struct gl_context *ctx = &brw->ctx;
+ struct brw_stage_state *stage_state = &brw->gs.base;
+ struct gl_program *prog = &gp->program.Base;
+
+ memset(key, 0, sizeof(*key));
+
+ key->base.program_string_id = gp->id;
+ brw_setup_vue_key_clip_info(brw, &key->base,
+ gp->program.Base.UsesClipDistanceOut);
+
+ /* _NEW_TEXTURE */
+ brw_populate_sampler_prog_key_data(ctx, prog, stage_state->sampler_count,
+ &key->base.tex);
+
+ struct brw_vs_prog_data *prog_data = &pipeline->vs_prog_data;
+
+ /* BRW_NEW_VUE_MAP_VS */
+ key->input_varyings = prog_data->base.vue_map.slots_valid;
+}
+
+static bool
+really_do_gs_prog(struct brw_context *brw,
+ struct gl_shader_program *prog,
+ struct brw_geometry_program *gp,
+ struct brw_gs_prog_key *key, struct anv_pipeline *pipeline)
+{
+ struct brw_gs_compile_output output;
+
+ /* FIXME: We pass the bind map to the compile in the output struct. Need
+ * something better. */
+ set_binding_table_layout(&output.prog_data.base.base,
+ pipeline, VK_SHADER_STAGE_GEOMETRY);
+
+ brw_compile_gs_prog(brw, prog, gp, key, &output);
+
+ struct anv_state gs_state = anv_state_stream_alloc(&pipeline->program_stream,
+ output.program_size, 64);
+ memcpy(gs_state.map, output.program, output.program_size);
+
+ pipeline->gs_vec4 = gs_state.offset;
+ pipeline->gs_vertex_count = gp->program.VerticesIn;
+
+ ralloc_free(output.mem_ctx);
+
+ return true;
+}
+
+static bool
+brw_codegen_cs_prog(struct brw_context *brw,
+ struct gl_shader_program *prog,
+ struct brw_compute_program *cp,
+ struct brw_cs_prog_key *key, struct anv_pipeline *pipeline)
+{
+ struct gl_context *ctx = &brw->ctx;
+ const GLuint *program;
+ void *mem_ctx = ralloc_context(NULL);
+ GLuint program_size;
+ struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
+
+ struct gl_shader *cs = prog->_LinkedShaders[MESA_SHADER_COMPUTE];
+ assert (cs);
+
+ memset(prog_data, 0, sizeof(*prog_data));
+
+ set_binding_table_layout(&prog_data->base, pipeline, VK_SHADER_STAGE_COMPUTE);
+
+ /* Allocate the references to the uniforms that will end up in the
+ * prog_data associated with the compiled program, and which will be freed
+ * by the state cache.
+ */
+ int param_count = cs->num_uniform_components;
+
+ /* The backend also sometimes adds params for texture size. */
+ param_count += 2 * ctx->Const.Program[MESA_SHADER_COMPUTE].MaxTextureImageUnits;
+ prog_data->base.param =
+ rzalloc_array(NULL, const gl_constant_value *, param_count);
+ prog_data->base.pull_param =
+ rzalloc_array(NULL, const gl_constant_value *, param_count);
+ prog_data->base.nr_params = param_count;
+
+ program = brw_cs_emit(brw, mem_ctx, key, prog_data,
+ &cp->program, prog, &program_size);
+ if (program == NULL) {
+ ralloc_free(mem_ctx);
+ return false;
+ }
+
+ if (unlikely(INTEL_DEBUG & DEBUG_CS))
+ fprintf(stderr, "\n");
+
+ struct anv_state cs_state = anv_state_stream_alloc(&pipeline->program_stream,
+ program_size, 64);
+ memcpy(cs_state.map, program, program_size);
+
+ pipeline->cs_simd = cs_state.offset;
+
+ ralloc_free(mem_ctx);
+
+ return true;
+}
+
+static void
+brw_cs_populate_key(struct brw_context *brw,
+ struct brw_compute_program *bcp, struct brw_cs_prog_key *key)
+{
+ memset(key, 0, sizeof(*key));
+
+ /* The unique compute program ID */
+ key->program_string_id = bcp->id;
+}
+
+static void
+fail_on_compile_error(int status, const char *msg)
+{
+ int source, line, column;
+ char error[256];
+
+ if (status)
+ return;
+
+ if (sscanf(msg, "%d:%d(%d): error: %255[^\n]", &source, &line, &column, error) == 4)
+ fail_if(!status, "%d:%s\n", line, error);
+ else
+ fail_if(!status, "%s\n", msg);
+}
+
+struct anv_compiler {
+ struct anv_device *device;
+ struct intel_screen *screen;
+ struct brw_context *brw;
+ struct gl_pipeline_object pipeline;
+};
+
+extern "C" {
+
+struct anv_compiler *
+anv_compiler_create(struct anv_device *device)
+{
+ const struct brw_device_info *devinfo = &device->info;
+ struct anv_compiler *compiler;
+ struct gl_context *ctx;
+
+ compiler = rzalloc(NULL, struct anv_compiler);
+ if (compiler == NULL)
+ return NULL;
+
+ compiler->screen = rzalloc(compiler, struct intel_screen);
+ if (compiler->screen == NULL)
+ goto fail;
+
+ compiler->brw = rzalloc(compiler, struct brw_context);
+ if (compiler->brw == NULL)
+ goto fail;
+
+ compiler->device = device;
+
+ compiler->brw->optionCache.info = NULL;
+ compiler->brw->bufmgr = NULL;
+ compiler->brw->gen = devinfo->gen;
+ compiler->brw->is_g4x = devinfo->is_g4x;
+ compiler->brw->is_baytrail = devinfo->is_baytrail;
+ compiler->brw->is_haswell = devinfo->is_haswell;
+ compiler->brw->is_cherryview = devinfo->is_cherryview;
+
+ /* We need this at least for CS, which will check brw->max_cs_threads
+ * against the work group size. */
+ compiler->brw->max_vs_threads = devinfo->max_vs_threads;
+ compiler->brw->max_hs_threads = devinfo->max_hs_threads;
+ compiler->brw->max_ds_threads = devinfo->max_ds_threads;
+ compiler->brw->max_gs_threads = devinfo->max_gs_threads;
+ compiler->brw->max_wm_threads = devinfo->max_wm_threads;
+ compiler->brw->max_cs_threads = devinfo->max_cs_threads;
+ compiler->brw->urb.size = devinfo->urb.size;
+ compiler->brw->urb.min_vs_entries = devinfo->urb.min_vs_entries;
+ compiler->brw->urb.max_vs_entries = devinfo->urb.max_vs_entries;
+ compiler->brw->urb.max_hs_entries = devinfo->urb.max_hs_entries;
+ compiler->brw->urb.max_ds_entries = devinfo->urb.max_ds_entries;
+ compiler->brw->urb.max_gs_entries = devinfo->urb.max_gs_entries;
+
+ compiler->brw->intelScreen = compiler->screen;
+ compiler->screen->devinfo = &device->info;
+
+ brw_process_intel_debug_variable(compiler->screen);
+
+ compiler->screen->compiler = brw_compiler_create(compiler, &device->info);
+
+ ctx = &compiler->brw->ctx;
+ _mesa_init_shader_object_functions(&ctx->Driver);
+
+ _mesa_init_constants(&ctx->Const, API_OPENGL_CORE);
+
+ brw_initialize_context_constants(compiler->brw);
+
+ intelInitExtensions(ctx);
+
+ /* Set dd::NewShader */
+ brwInitFragProgFuncs(&ctx->Driver);
+
+ ctx->_Shader = &compiler->pipeline;
+
+ compiler->brw->precompile = false;
+
+ return compiler;
+
+ fail:
+ ralloc_free(compiler);
+ return NULL;
+}
+
+void
+anv_compiler_destroy(struct anv_compiler *compiler)
+{
+ _mesa_free_errors_data(&compiler->brw->ctx);
+ ralloc_free(compiler);
+}
+
+/* From gen7_urb.c */
+
+/* FIXME: Add to struct intel_device_info */
+
+static const int gen8_push_size = 32 * 1024;
+
+static void
+gen7_compute_urb_partition(struct anv_pipeline *pipeline)
+{
+ const struct brw_device_info *devinfo = &pipeline->device->info;
+ bool vs_present = pipeline->vs_simd8 != NO_KERNEL;
+ unsigned vs_size = vs_present ? pipeline->vs_prog_data.base.urb_entry_size : 1;
+ unsigned vs_entry_size_bytes = vs_size * 64;
+ bool gs_present = pipeline->gs_vec4 != NO_KERNEL;
+ unsigned gs_size = gs_present ? pipeline->gs_prog_data.base.urb_entry_size : 1;
+ unsigned gs_entry_size_bytes = gs_size * 64;
+
+ /* From p35 of the Ivy Bridge PRM (section 1.7.1: 3DSTATE_URB_GS):
+ *
+ * VS Number of URB Entries must be divisible by 8 if the VS URB Entry
+ * Allocation Size is less than 9 512-bit URB entries.
+ *
+ * Similar text exists for GS.
+ */
+ unsigned vs_granularity = (vs_size < 9) ? 8 : 1;
+ unsigned gs_granularity = (gs_size < 9) ? 8 : 1;
+
+ /* URB allocations must be done in 8k chunks. */
+ unsigned chunk_size_bytes = 8192;
+
+ /* Determine the size of the URB in chunks. */
+ unsigned urb_chunks = devinfo->urb.size * 1024 / chunk_size_bytes;
+
+ /* Reserve space for push constants */
+ unsigned push_constant_bytes = gen8_push_size;
+ unsigned push_constant_chunks =
+ push_constant_bytes / chunk_size_bytes;
+
+ /* Initially, assign each stage the minimum amount of URB space it needs,
+ * and make a note of how much additional space it "wants" (the amount of
+ * additional space it could actually make use of).
+ */
+
+ /* VS has a lower limit on the number of URB entries */
+ unsigned vs_chunks =
+ ALIGN(devinfo->urb.min_vs_entries * vs_entry_size_bytes,
+ chunk_size_bytes) / chunk_size_bytes;
+ unsigned vs_wants =
+ ALIGN(devinfo->urb.max_vs_entries * vs_entry_size_bytes,
+ chunk_size_bytes) / chunk_size_bytes - vs_chunks;
+
+ unsigned gs_chunks = 0;
+ unsigned gs_wants = 0;
+ if (gs_present) {
+ /* There are two constraints on the minimum amount of URB space we can
+ * allocate:
+ *
+ * (1) We need room for at least 2 URB entries, since we always operate
+ * the GS in DUAL_OBJECT mode.
+ *
+ * (2) We can't allocate less than nr_gs_entries_granularity.
+ */
+ gs_chunks = ALIGN(MAX2(gs_granularity, 2) * gs_entry_size_bytes,
+ chunk_size_bytes) / chunk_size_bytes;
+ gs_wants =
+ ALIGN(devinfo->urb.max_gs_entries * gs_entry_size_bytes,
+ chunk_size_bytes) / chunk_size_bytes - gs_chunks;
+ }
+
+ /* There should always be enough URB space to satisfy the minimum
+ * requirements of each stage.
+ */
+ unsigned total_needs = push_constant_chunks + vs_chunks + gs_chunks;
+ assert(total_needs <= urb_chunks);
+
+ /* Mete out remaining space (if any) in proportion to "wants". */
+ unsigned total_wants = vs_wants + gs_wants;
+ unsigned remaining_space = urb_chunks - total_needs;
+ if (remaining_space > total_wants)
+ remaining_space = total_wants;
+ if (remaining_space > 0) {
+ unsigned vs_additional = (unsigned)
+ round(vs_wants * (((double) remaining_space) / total_wants));
+ vs_chunks += vs_additional;
+ remaining_space -= vs_additional;
+ gs_chunks += remaining_space;
+ }
+
+ /* Sanity check that we haven't over-allocated. */
+ assert(push_constant_chunks + vs_chunks + gs_chunks <= urb_chunks);
+
+ /* Finally, compute the number of entries that can fit in the space
+ * allocated to each stage.
+ */
+ unsigned nr_vs_entries = vs_chunks * chunk_size_bytes / vs_entry_size_bytes;
+ unsigned nr_gs_entries = gs_chunks * chunk_size_bytes / gs_entry_size_bytes;
+
+ /* Since we rounded up when computing *_wants, this may be slightly more
+ * than the maximum allowed amount, so correct for that.
+ */
+ nr_vs_entries = MIN2(nr_vs_entries, devinfo->urb.max_vs_entries);
+ nr_gs_entries = MIN2(nr_gs_entries, devinfo->urb.max_gs_entries);
+
+ /* Ensure that we program a multiple of the granularity. */
+ nr_vs_entries = ROUND_DOWN_TO(nr_vs_entries, vs_granularity);
+ nr_gs_entries = ROUND_DOWN_TO(nr_gs_entries, gs_granularity);
+
+ /* Finally, sanity check to make sure we have at least the minimum number
+ * of entries needed for each stage.
+ */
+ assert(nr_vs_entries >= devinfo->urb.min_vs_entries);
+ if (gs_present)
+ assert(nr_gs_entries >= 2);
+
+ /* Lay out the URB in the following order:
+ * - push constants
+ * - VS
+ * - GS
+ */
+ pipeline->urb.vs_start = push_constant_chunks;
+ pipeline->urb.vs_size = vs_size;
+ pipeline->urb.nr_vs_entries = nr_vs_entries;
+
+ pipeline->urb.gs_start = push_constant_chunks + vs_chunks;
+ pipeline->urb.gs_size = gs_size;
+ pipeline->urb.nr_gs_entries = nr_gs_entries;
+}
+
+static const struct {
+ uint32_t token;
+ gl_shader_stage stage;
+ const char *name;
+} stage_info[] = {
+ { GL_VERTEX_SHADER, MESA_SHADER_VERTEX, "vertex" },
+ { GL_TESS_CONTROL_SHADER, (gl_shader_stage)-1,"tess control" },
+ { GL_TESS_EVALUATION_SHADER, (gl_shader_stage)-1, "tess evaluation" },
+ { GL_GEOMETRY_SHADER, MESA_SHADER_GEOMETRY, "geometry" },
+ { GL_FRAGMENT_SHADER, MESA_SHADER_FRAGMENT, "fragment" },
+ { GL_COMPUTE_SHADER, MESA_SHADER_COMPUTE, "compute" },
+};
+
+struct spirv_header{
+ uint32_t magic;
+ uint32_t version;
+ uint32_t gen_magic;
+};
+
+static const char *
+src_as_glsl(const char *data)
+{
+ const struct spirv_header *as_spirv = (const struct spirv_header *)data;
+
+ /* Check alignment */
+ if ((intptr_t)data & 0x3) {
+ return data;
+ }
+
+ if (as_spirv->magic == SPIR_V_MAGIC_NUMBER) {
+ /* LunarG back-door */
+ if (as_spirv->version == 0)
+ return data + 12;
+ else
+ return NULL;
+ } else {
+ return data;
+ }
+}
+
+static void
+anv_compile_shader_glsl(struct anv_compiler *compiler,
+ struct gl_shader_program *program,
+ struct anv_pipeline *pipeline, uint32_t stage)
+{
+ struct brw_context *brw = compiler->brw;
+ struct gl_shader *shader;
+ int name = 0;
+
+ shader = brw_new_shader(&brw->ctx, name, stage_info[stage].token);
+ fail_if(shader == NULL, "failed to create %s shader\n", stage_info[stage].name);
+
+ shader->Source = strdup(src_as_glsl(pipeline->shaders[stage]->module->data));
+ _mesa_glsl_compile_shader(&brw->ctx, shader, false, false);
+ fail_on_compile_error(shader->CompileStatus, shader->InfoLog);
+
+ program->Shaders[program->NumShaders] = shader;
+ program->NumShaders++;
+}
+
+static void
+setup_nir_io(struct gl_program *prog,
+ nir_shader *shader)
+{
+ foreach_list_typed(nir_variable, var, node, &shader->inputs) {
+ prog->InputsRead |= BITFIELD64_BIT(var->data.location);
+ }
+
+ foreach_list_typed(nir_variable, var, node, &shader->outputs) {
+ prog->OutputsWritten |= BITFIELD64_BIT(var->data.location);
+ }
+}
+
+static void
+anv_compile_shader_spirv(struct anv_compiler *compiler,
+ struct gl_shader_program *program,
+ struct anv_pipeline *pipeline, uint32_t stage)
+{
+ struct brw_context *brw = compiler->brw;
+ struct anv_shader *shader = pipeline->shaders[stage];
+ struct gl_shader *mesa_shader;
+ int name = 0;
+
+ mesa_shader = brw_new_shader(&brw->ctx, name, stage_info[stage].token);
+ fail_if(mesa_shader == NULL,
+ "failed to create %s shader\n", stage_info[stage].name);
+
+ switch (stage) {
+ case VK_SHADER_STAGE_VERTEX:
+ mesa_shader->Program = &rzalloc(mesa_shader, struct brw_vertex_program)->program.Base;
+ break;
+ case VK_SHADER_STAGE_GEOMETRY:
+ mesa_shader->Program = &rzalloc(mesa_shader, struct brw_geometry_program)->program.Base;
+ break;
+ case VK_SHADER_STAGE_FRAGMENT:
+ mesa_shader->Program = &rzalloc(mesa_shader, struct brw_fragment_program)->program.Base;
+ break;
+ case VK_SHADER_STAGE_COMPUTE:
+ mesa_shader->Program = &rzalloc(mesa_shader, struct brw_compute_program)->program.Base;
+ break;
+ }
+
+ mesa_shader->Program->Parameters =
+ rzalloc(mesa_shader, struct gl_program_parameter_list);
+
+ mesa_shader->Type = stage_info[stage].token;
+ mesa_shader->Stage = stage_info[stage].stage;
+
+ assert(shader->module->size % 4 == 0);
+
+ struct gl_shader_compiler_options *glsl_options =
+ &compiler->screen->compiler->glsl_compiler_options[stage_info[stage].stage];
+
+ mesa_shader->Program->nir =
+ spirv_to_nir((uint32_t *)shader->module->data, shader->module->size / 4,
+ glsl_options->NirOptions);
+ nir_validate_shader(mesa_shader->Program->nir);
+
+ brw_process_nir(mesa_shader->Program->nir,
+ compiler->screen->devinfo,
+ NULL, mesa_shader->Stage);
+
+ setup_nir_io(mesa_shader->Program, mesa_shader->Program->nir);
+
+ fail_if(mesa_shader->Program->nir == NULL,
+ "failed to translate SPIR-V to NIR\n");
+
+ program->Shaders[program->NumShaders] = mesa_shader;
+ program->NumShaders++;
+}
+
+static void
+add_compiled_stage(struct anv_pipeline *pipeline, uint32_t stage,
+ struct brw_stage_prog_data *prog_data)
+{
+ struct brw_device_info *devinfo = &pipeline->device->info;
+ uint32_t max_threads[] = {
+ [VK_SHADER_STAGE_VERTEX] = devinfo->max_vs_threads,
+ [VK_SHADER_STAGE_TESS_CONTROL] = 0,
+ [VK_SHADER_STAGE_TESS_EVALUATION] = 0,
+ [VK_SHADER_STAGE_GEOMETRY] = devinfo->max_gs_threads,
+ [VK_SHADER_STAGE_FRAGMENT] = devinfo->max_wm_threads,
+ [VK_SHADER_STAGE_COMPUTE] = devinfo->max_cs_threads,
+ };
+
+ pipeline->prog_data[stage] = prog_data;
+ pipeline->active_stages |= 1 << stage;
+ pipeline->scratch_start[stage] = pipeline->total_scratch;
+ pipeline->total_scratch =
+ align_u32(pipeline->total_scratch, 1024) +
+ prog_data->total_scratch * max_threads[stage];
+}
+
+int
+anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline)
+{
+ struct gl_shader_program *program;
+ int name = 0;
+ struct brw_context *brw = compiler->brw;
+
+ pipeline->writes_point_size = false;
+
+ /* When we free the pipeline, we detect stages based on the NULL status
+ * of various prog_data pointers. Make them NULL by default.
+ */
+ memset(pipeline->prog_data, 0, sizeof(pipeline->prog_data));
+ memset(pipeline->scratch_start, 0, sizeof(pipeline->scratch_start));
+
+ brw->use_rep_send = pipeline->use_repclear;
+ brw->no_simd8 = pipeline->use_repclear;
+
+ program = brw->ctx.Driver.NewShaderProgram(name);
+ program->Shaders = (struct gl_shader **)
+ calloc(VK_SHADER_STAGE_NUM, sizeof(struct gl_shader *));
+ fail_if(program == NULL || program->Shaders == NULL,
+ "failed to create program\n");
+
+ bool all_spirv = true;
+ for (unsigned i = 0; i < VK_SHADER_STAGE_NUM; i++) {
+ if (pipeline->shaders[i] == NULL)
+ continue;
+
+ /* You need at least this much for "void main() { }" anyway */
+ assert(pipeline->shaders[i]->module->size >= 12);
+
+ if (src_as_glsl(pipeline->shaders[i]->module->data)) {
+ all_spirv = false;
+ break;
+ }
+
+ assert(pipeline->shaders[i]->module->size % 4 == 0);
+ }
+
+ if (all_spirv) {
+ for (unsigned i = 0; i < VK_SHADER_STAGE_NUM; i++) {
+ if (pipeline->shaders[i])
+ anv_compile_shader_spirv(compiler, program, pipeline, i);
+ }
+
+ for (unsigned i = 0; i < program->NumShaders; i++) {
+ struct gl_shader *shader = program->Shaders[i];
+ program->_LinkedShaders[shader->Stage] = shader;
+ }
+ } else {
+ for (unsigned i = 0; i < VK_SHADER_STAGE_NUM; i++) {
+ if (pipeline->shaders[i])
+ anv_compile_shader_glsl(compiler, program, pipeline, i);
+ }
+
+ _mesa_glsl_link_shader(&brw->ctx, program);
+ fail_on_compile_error(program->LinkStatus,
+ program->InfoLog);
+ }
+
+ bool success;
+ pipeline->active_stages = 0;
+ pipeline->total_scratch = 0;
+
+ if (pipeline->shaders[VK_SHADER_STAGE_VERTEX]) {
+ struct brw_vs_prog_key vs_key;
+ struct gl_vertex_program *vp = (struct gl_vertex_program *)
+ program->_LinkedShaders[MESA_SHADER_VERTEX]->Program;
+ struct brw_vertex_program *bvp = brw_vertex_program(vp);
+
+ brw_vs_populate_key(brw, bvp, &vs_key);
+
+ success = really_do_vs_prog(brw, program, bvp, &vs_key, pipeline);
+ fail_if(!success, "do_wm_prog failed\n");
+ add_compiled_stage(pipeline, VK_SHADER_STAGE_VERTEX,
+ &pipeline->vs_prog_data.base.base);
+
+ if (vp->Base.OutputsWritten & VARYING_SLOT_PSIZ)
+ pipeline->writes_point_size = true;
+ } else {
+ memset(&pipeline->vs_prog_data, 0, sizeof(pipeline->vs_prog_data));
+ pipeline->vs_simd8 = NO_KERNEL;
+ }
+
+
+ if (pipeline->shaders[VK_SHADER_STAGE_GEOMETRY]) {
+ struct brw_gs_prog_key gs_key;
+ struct gl_geometry_program *gp = (struct gl_geometry_program *)
+ program->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program;
+ struct brw_geometry_program *bgp = brw_geometry_program(gp);
+
+ brw_gs_populate_key(brw, pipeline, bgp, &gs_key);
+
+ success = really_do_gs_prog(brw, program, bgp, &gs_key, pipeline);
+ fail_if(!success, "do_gs_prog failed\n");
+ add_compiled_stage(pipeline, VK_SHADER_STAGE_GEOMETRY,
+ &pipeline->gs_prog_data.base.base);
+
+ if (gp->Base.OutputsWritten & VARYING_SLOT_PSIZ)
+ pipeline->writes_point_size = true;
+ } else {
+ pipeline->gs_vec4 = NO_KERNEL;
+ }
+
+ if (pipeline->shaders[VK_SHADER_STAGE_FRAGMENT]) {
+ struct brw_wm_prog_key wm_key;
+ struct gl_fragment_program *fp = (struct gl_fragment_program *)
+ program->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program;
+ struct brw_fragment_program *bfp = brw_fragment_program(fp);
+
+ brw_wm_populate_key(brw, bfp, &wm_key);
+
+ success = really_do_wm_prog(brw, program, bfp, &wm_key, pipeline);
+ fail_if(!success, "do_wm_prog failed\n");
+ add_compiled_stage(pipeline, VK_SHADER_STAGE_FRAGMENT,
+ &pipeline->wm_prog_data.base);
+ }
+
+ if (pipeline->shaders[VK_SHADER_STAGE_COMPUTE]) {
+ struct brw_cs_prog_key cs_key;
+ struct gl_compute_program *cp = (struct gl_compute_program *)
+ program->_LinkedShaders[MESA_SHADER_COMPUTE]->Program;
+ struct brw_compute_program *bcp = brw_compute_program(cp);
+
+ brw_cs_populate_key(brw, bcp, &cs_key);
+
+ success = brw_codegen_cs_prog(brw, program, bcp, &cs_key, pipeline);
+ fail_if(!success, "brw_codegen_cs_prog failed\n");
+ add_compiled_stage(pipeline, VK_SHADER_STAGE_COMPUTE,
+ &pipeline->cs_prog_data.base);
+ }
+
+ /* XXX: Deleting the shader is broken with our current SPIR-V hacks. We
+ * need to fix this ASAP.
+ */
+ if (!all_spirv)
+ brw->ctx.Driver.DeleteShaderProgram(&brw->ctx, program);
+
+ struct anv_device *device = compiler->device;
+ while (device->scratch_block_pool.bo.size < pipeline->total_scratch)
+ anv_block_pool_alloc(&device->scratch_block_pool);
+
+ gen7_compute_urb_partition(pipeline);
+
+ return 0;
+}
+
+/* This badly named function frees the struct anv_pipeline data that the compiler
+ * allocates. Currently just the prog_data structs.
+ */
+void
+anv_compiler_free(struct anv_pipeline *pipeline)
+{
+ for (uint32_t stage = 0; stage < VK_SHADER_STAGE_NUM; stage++) {
+ if (pipeline->prog_data[stage]) {
+ free(pipeline->prog_data[stage]->map_entries);
+ ralloc_free(pipeline->prog_data[stage]->param);
+ ralloc_free(pipeline->prog_data[stage]->pull_param);
+ }
+ }
+}
+
+}
--- /dev/null
+/*
+ * 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 <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "anv_private.h"
+#include "mesa/main/git_sha1.h"
+
+static int
+anv_env_get_int(const char *name)
+{
+ const char *val = getenv(name);
+
+ if (!val)
+ return 0;
+
+ return strtol(val, NULL, 0);
+}
+
+static void
+anv_physical_device_finish(struct anv_physical_device *device)
+{
+ if (device->fd >= 0)
+ close(device->fd);
+}
+
+static VkResult
+anv_physical_device_init(struct anv_physical_device *device,
+ struct anv_instance *instance,
+ const char *path)
+{
+ device->fd = open(path, O_RDWR | O_CLOEXEC);
+ if (device->fd < 0)
+ return vk_error(VK_ERROR_UNAVAILABLE);
+
+ device->instance = instance;
+ device->path = path;
+
+ device->chipset_id = anv_env_get_int("INTEL_DEVID_OVERRIDE");
+ device->no_hw = false;
+ if (device->chipset_id) {
+ /* INTEL_DEVID_OVERRIDE implies INTEL_NO_HW. */
+ device->no_hw = true;
+ } else {
+ device->chipset_id = anv_gem_get_param(device->fd, I915_PARAM_CHIPSET_ID);
+ }
+ if (!device->chipset_id)
+ goto fail;
+
+ device->name = brw_get_device_name(device->chipset_id);
+ device->info = brw_get_device_info(device->chipset_id, -1);
+ if (!device->info)
+ goto fail;
+
+ if (!anv_gem_get_param(device->fd, I915_PARAM_HAS_WAIT_TIMEOUT))
+ goto fail;
+
+ if (!anv_gem_get_param(device->fd, I915_PARAM_HAS_EXECBUF2))
+ goto fail;
+
+ if (!anv_gem_get_param(device->fd, I915_PARAM_HAS_LLC))
+ goto fail;
+
+ if (!anv_gem_get_param(device->fd, I915_PARAM_HAS_EXEC_CONSTANTS))
+ goto fail;
+
+ return VK_SUCCESS;
+
+fail:
+ anv_physical_device_finish(device);
+ return vk_error(VK_ERROR_UNAVAILABLE);
+}
+
+static void *default_alloc(
+ void* pUserData,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocType allocType)
+{
+ return malloc(size);
+}
+
+static void default_free(
+ void* pUserData,
+ void* pMem)
+{
+ free(pMem);
+}
+
+static const VkAllocCallbacks default_alloc_callbacks = {
+ .pUserData = NULL,
+ .pfnAlloc = default_alloc,
+ .pfnFree = default_free
+};
+
+VkResult anv_CreateInstance(
+ const VkInstanceCreateInfo* pCreateInfo,
+ VkInstance* pInstance)
+{
+ struct anv_instance *instance;
+ const VkAllocCallbacks *alloc_callbacks = &default_alloc_callbacks;
+ void *user_data = NULL;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
+
+ if (pCreateInfo->pAllocCb) {
+ alloc_callbacks = pCreateInfo->pAllocCb;
+ user_data = pCreateInfo->pAllocCb->pUserData;
+ }
+ instance = alloc_callbacks->pfnAlloc(user_data, sizeof(*instance), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (!instance)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ instance->pAllocUserData = alloc_callbacks->pUserData;
+ instance->pfnAlloc = alloc_callbacks->pfnAlloc;
+ instance->pfnFree = alloc_callbacks->pfnFree;
+ instance->apiVersion = pCreateInfo->pAppInfo->apiVersion;
+ instance->physicalDeviceCount = 0;
+
+ *pInstance = anv_instance_to_handle(instance);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyInstance(
+ VkInstance _instance)
+{
+ ANV_FROM_HANDLE(anv_instance, instance, _instance);
+
+ if (instance->physicalDeviceCount > 0) {
+ anv_physical_device_finish(&instance->physicalDevice);
+ }
+
+ instance->pfnFree(instance->pAllocUserData, instance);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_EnumeratePhysicalDevices(
+ VkInstance _instance,
+ uint32_t* pPhysicalDeviceCount,
+ VkPhysicalDevice* pPhysicalDevices)
+{
+ ANV_FROM_HANDLE(anv_instance, instance, _instance);
+ VkResult result;
+
+ if (instance->physicalDeviceCount == 0) {
+ result = anv_physical_device_init(&instance->physicalDevice,
+ instance, "/dev/dri/renderD128");
+ if (result != VK_SUCCESS)
+ return result;
+
+ instance->physicalDeviceCount = 1;
+ }
+
+ /* pPhysicalDeviceCount is an out parameter if pPhysicalDevices is NULL;
+ * otherwise it's an inout parameter.
+ *
+ * The Vulkan spec (git aaed022) says:
+ *
+ * pPhysicalDeviceCount is a pointer to an unsigned integer variable
+ * that is initialized with the number of devices the application is
+ * prepared to receive handles to. pname:pPhysicalDevices is pointer to
+ * an array of at least this many VkPhysicalDevice handles [...].
+ *
+ * Upon success, if pPhysicalDevices is NULL, vkEnumeratePhysicalDevices
+ * overwrites the contents of the variable pointed to by
+ * pPhysicalDeviceCount with the number of physical devices in in the
+ * instance; otherwise, vkEnumeratePhysicalDevices overwrites
+ * pPhysicalDeviceCount with the number of physical handles written to
+ * pPhysicalDevices.
+ */
+ if (!pPhysicalDevices) {
+ *pPhysicalDeviceCount = instance->physicalDeviceCount;
+ } else if (*pPhysicalDeviceCount >= 1) {
+ pPhysicalDevices[0] = anv_physical_device_to_handle(&instance->physicalDevice);
+ *pPhysicalDeviceCount = 1;
+ } else {
+ *pPhysicalDeviceCount = 0;
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetPhysicalDeviceFeatures(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures* pFeatures)
+{
+ anv_finishme("Get correct values for PhysicalDeviceFeatures");
+
+ *pFeatures = (VkPhysicalDeviceFeatures) {
+ .robustBufferAccess = false,
+ .fullDrawIndexUint32 = false,
+ .imageCubeArray = false,
+ .independentBlend = false,
+ .geometryShader = true,
+ .tessellationShader = false,
+ .sampleRateShading = false,
+ .dualSourceBlend = true,
+ .logicOp = true,
+ .instancedDrawIndirect = true,
+ .depthClip = false,
+ .depthBiasClamp = false,
+ .fillModeNonSolid = true,
+ .depthBounds = false,
+ .wideLines = true,
+ .largePoints = true,
+ .textureCompressionETC2 = true,
+ .textureCompressionASTC_LDR = true,
+ .textureCompressionBC = true,
+ .pipelineStatisticsQuery = true,
+ .vertexSideEffects = false,
+ .tessellationSideEffects = false,
+ .geometrySideEffects = false,
+ .fragmentSideEffects = false,
+ .shaderTessellationPointSize = false,
+ .shaderGeometryPointSize = true,
+ .shaderTextureGatherExtended = true,
+ .shaderStorageImageExtendedFormats = false,
+ .shaderStorageImageMultisample = false,
+ .shaderStorageBufferArrayConstantIndexing = false,
+ .shaderStorageImageArrayConstantIndexing = false,
+ .shaderUniformBufferArrayDynamicIndexing = true,
+ .shaderSampledImageArrayDynamicIndexing = false,
+ .shaderStorageBufferArrayDynamicIndexing = false,
+ .shaderStorageImageArrayDynamicIndexing = false,
+ .shaderClipDistance = false,
+ .shaderCullDistance = false,
+ .shaderFloat64 = false,
+ .shaderInt64 = false,
+ .shaderFloat16 = false,
+ .shaderInt16 = false,
+ };
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetPhysicalDeviceLimits(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceLimits* pLimits)
+{
+ ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
+ const struct brw_device_info *devinfo = physical_device->info;
+
+ anv_finishme("Get correct values for PhysicalDeviceLimits");
+
+ *pLimits = (VkPhysicalDeviceLimits) {
+ .maxImageDimension1D = (1 << 14),
+ .maxImageDimension2D = (1 << 14),
+ .maxImageDimension3D = (1 << 10),
+ .maxImageDimensionCube = (1 << 14),
+ .maxImageArrayLayers = (1 << 10),
+ .maxTexelBufferSize = (1 << 14),
+ .maxUniformBufferSize = UINT32_MAX,
+ .maxStorageBufferSize = UINT32_MAX,
+ .maxPushConstantsSize = 128,
+ .maxMemoryAllocationCount = UINT32_MAX,
+ .bufferImageGranularity = 64, /* A cache line */
+ .maxBoundDescriptorSets = MAX_SETS,
+ .maxDescriptorSets = UINT32_MAX,
+ .maxPerStageDescriptorSamplers = 64,
+ .maxPerStageDescriptorUniformBuffers = 64,
+ .maxPerStageDescriptorStorageBuffers = 64,
+ .maxPerStageDescriptorSampledImages = 64,
+ .maxPerStageDescriptorStorageImages = 64,
+ .maxDescriptorSetSamplers = 256,
+ .maxDescriptorSetUniformBuffers = 256,
+ .maxDescriptorSetStorageBuffers = 256,
+ .maxDescriptorSetSampledImages = 256,
+ .maxDescriptorSetStorageImages = 256,
+ .maxVertexInputAttributes = 32,
+ .maxVertexInputAttributeOffset = 256,
+ .maxVertexInputBindingStride = 256,
+ .maxVertexOutputComponents = 32,
+ .maxTessGenLevel = 0,
+ .maxTessPatchSize = 0,
+ .maxTessControlPerVertexInputComponents = 0,
+ .maxTessControlPerVertexOutputComponents = 0,
+ .maxTessControlPerPatchOutputComponents = 0,
+ .maxTessControlTotalOutputComponents = 0,
+ .maxTessEvaluationInputComponents = 0,
+ .maxTessEvaluationOutputComponents = 0,
+ .maxGeometryShaderInvocations = 6,
+ .maxGeometryInputComponents = 16,
+ .maxGeometryOutputComponents = 16,
+ .maxGeometryOutputVertices = 16,
+ .maxGeometryTotalOutputComponents = 16,
+ .maxFragmentInputComponents = 16,
+ .maxFragmentOutputBuffers = 8,
+ .maxFragmentDualSourceBuffers = 2,
+ .maxFragmentCombinedOutputResources = 8,
+ .maxComputeSharedMemorySize = 1024,
+ .maxComputeWorkGroupCount = {
+ 16 * devinfo->max_cs_threads,
+ 16 * devinfo->max_cs_threads,
+ 16 * devinfo->max_cs_threads,
+ },
+ .maxComputeWorkGroupInvocations = 16 * devinfo->max_cs_threads,
+ .maxComputeWorkGroupSize = {
+ 16 * devinfo->max_cs_threads,
+ 16 * devinfo->max_cs_threads,
+ 16 * devinfo->max_cs_threads,
+ },
+ .subPixelPrecisionBits = 4 /* FIXME */,
+ .subTexelPrecisionBits = 4 /* FIXME */,
+ .mipmapPrecisionBits = 4 /* FIXME */,
+ .maxDrawIndexedIndexValue = UINT32_MAX,
+ .maxDrawIndirectInstanceCount = UINT32_MAX,
+ .primitiveRestartForPatches = UINT32_MAX,
+ .maxSamplerLodBias = 16,
+ .maxSamplerAnisotropy = 16,
+ .maxViewports = 16,
+ .maxDynamicViewportStates = UINT32_MAX,
+ .maxViewportDimensions = { (1 << 14), (1 << 14) },
+ .viewportBoundsRange = { -1.0, 1.0 }, /* FIXME */
+ .viewportSubPixelBits = 13, /* We take a float? */
+ .minMemoryMapAlignment = 64, /* A cache line */
+ .minTexelBufferOffsetAlignment = 1,
+ .minUniformBufferOffsetAlignment = 1,
+ .minStorageBufferOffsetAlignment = 1,
+ .minTexelOffset = 0, /* FIXME */
+ .maxTexelOffset = 0, /* FIXME */
+ .minTexelGatherOffset = 0, /* FIXME */
+ .maxTexelGatherOffset = 0, /* FIXME */
+ .minInterpolationOffset = 0, /* FIXME */
+ .maxInterpolationOffset = 0, /* FIXME */
+ .subPixelInterpolationOffsetBits = 0, /* FIXME */
+ .maxFramebufferWidth = (1 << 14),
+ .maxFramebufferHeight = (1 << 14),
+ .maxFramebufferLayers = (1 << 10),
+ .maxFramebufferColorSamples = 8,
+ .maxFramebufferDepthSamples = 8,
+ .maxFramebufferStencilSamples = 8,
+ .maxColorAttachments = MAX_RTS,
+ .maxSampledImageColorSamples = 8,
+ .maxSampledImageDepthSamples = 8,
+ .maxSampledImageIntegerSamples = 1,
+ .maxStorageImageSamples = 1,
+ .maxSampleMaskWords = 1,
+ .timestampFrequency = 1000 * 1000 * 1000 / 80,
+ .maxClipDistances = 0 /* FIXME */,
+ .maxCullDistances = 0 /* FIXME */,
+ .maxCombinedClipAndCullDistances = 0 /* FIXME */,
+ .pointSizeRange = { 0.125, 255.875 },
+ .lineWidthRange = { 0.0, 7.9921875 },
+ .pointSizeGranularity = (1.0 / 8.0),
+ .lineWidthGranularity = (1.0 / 128.0),
+ };
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetPhysicalDeviceProperties(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties* pProperties)
+{
+ ANV_FROM_HANDLE(anv_physical_device, pdevice, physicalDevice);
+
+ *pProperties = (VkPhysicalDeviceProperties) {
+ .apiVersion = 1,
+ .driverVersion = 1,
+ .vendorId = 0x8086,
+ .deviceId = pdevice->chipset_id,
+ .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
+ };
+
+ strcpy(pProperties->deviceName, pdevice->name);
+ snprintf((char *)pProperties->pipelineCacheUUID, VK_UUID_LENGTH,
+ "anv-%s", MESA_GIT_SHA1 + 4);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetPhysicalDeviceQueueCount(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pCount)
+{
+ *pCount = 1;
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetPhysicalDeviceQueueProperties(
+ VkPhysicalDevice physicalDevice,
+ uint32_t count,
+ VkPhysicalDeviceQueueProperties* pQueueProperties)
+{
+ assert(count == 1);
+
+ *pQueueProperties = (VkPhysicalDeviceQueueProperties) {
+ .queueFlags = VK_QUEUE_GRAPHICS_BIT |
+ VK_QUEUE_COMPUTE_BIT |
+ VK_QUEUE_DMA_BIT,
+ .queueCount = 1,
+ .supportsTimestamps = true,
+ };
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetPhysicalDeviceMemoryProperties(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties* pMemoryProperties)
+{
+ ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
+
+ size_t aperture_size;
+ size_t heap_size;
+
+ if (anv_gem_get_aperture(physical_device, &aperture_size) == -1)
+ return vk_error(VK_ERROR_UNAVAILABLE);
+
+ /* Reserve some wiggle room for the driver by exposing only 75% of the
+ * aperture to the heap.
+ */
+ heap_size = 3 * aperture_size / 4;
+
+ /* The property flags below are valid only for llc platforms. */
+ pMemoryProperties->memoryTypeCount = 1;
+ pMemoryProperties->memoryTypes[0] = (VkMemoryType) {
+ .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
+ .heapIndex = 1,
+ };
+
+ pMemoryProperties->memoryHeapCount = 1;
+ pMemoryProperties->memoryHeaps[0] = (VkMemoryHeap) {
+ .size = heap_size,
+ .flags = VK_MEMORY_HEAP_HOST_LOCAL,
+ };
+
+ return VK_SUCCESS;
+}
+
+PFN_vkVoidFunction anv_GetInstanceProcAddr(
+ VkInstance instance,
+ const char* pName)
+{
+ return anv_lookup_entrypoint(pName);
+}
+
+PFN_vkVoidFunction anv_GetDeviceProcAddr(
+ VkDevice device,
+ const char* pName)
+{
+ return anv_lookup_entrypoint(pName);
+}
+
+static void
+parse_debug_flags(struct anv_device *device)
+{
+ const char *debug, *p, *end;
+
+ debug = getenv("INTEL_DEBUG");
+ device->dump_aub = false;
+ if (debug) {
+ for (p = debug; *p; p = end + 1) {
+ end = strchrnul(p, ',');
+ if (end - p == 3 && memcmp(p, "aub", 3) == 0)
+ device->dump_aub = true;
+ if (end - p == 5 && memcmp(p, "no_hw", 5) == 0)
+ device->no_hw = true;
+ if (*end == '\0')
+ break;
+ }
+ }
+}
+
+static VkResult
+anv_queue_init(struct anv_device *device, struct anv_queue *queue)
+{
+ queue->device = device;
+ queue->pool = &device->surface_state_pool;
+
+ queue->completed_serial = anv_state_pool_alloc(queue->pool, 4, 4);
+ if (queue->completed_serial.map == NULL)
+ return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
+
+ *(uint32_t *)queue->completed_serial.map = 0;
+ queue->next_serial = 1;
+
+ return VK_SUCCESS;
+}
+
+static void
+anv_queue_finish(struct anv_queue *queue)
+{
+#ifdef HAVE_VALGRIND
+ /* This gets torn down with the device so we only need to do this if
+ * valgrind is present.
+ */
+ anv_state_pool_free(queue->pool, queue->completed_serial);
+#endif
+}
+
+static void
+anv_device_init_border_colors(struct anv_device *device)
+{
+ static const VkClearColorValue border_colors[] = {
+ [VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK] = { .f32 = { 0.0, 0.0, 0.0, 0.0 } },
+ [VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK] = { .f32 = { 0.0, 0.0, 0.0, 1.0 } },
+ [VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE] = { .f32 = { 1.0, 1.0, 1.0, 1.0 } },
+ [VK_BORDER_COLOR_INT_TRANSPARENT_BLACK] = { .u32 = { 0, 0, 0, 0 } },
+ [VK_BORDER_COLOR_INT_OPAQUE_BLACK] = { .u32 = { 0, 0, 0, 1 } },
+ [VK_BORDER_COLOR_INT_OPAQUE_WHITE] = { .u32 = { 1, 1, 1, 1 } },
+ };
+
+ device->border_colors =
+ anv_state_pool_alloc(&device->dynamic_state_pool,
+ sizeof(border_colors), 32);
+ memcpy(device->border_colors.map, border_colors, sizeof(border_colors));
+}
+
+static const uint32_t BATCH_SIZE = 8192;
+
+VkResult anv_CreateDevice(
+ VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo* pCreateInfo,
+ VkDevice* pDevice)
+{
+ ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
+ struct anv_instance *instance = physical_device->instance;
+ struct anv_device *device;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
+
+ device = instance->pfnAlloc(instance->pAllocUserData,
+ sizeof(*device), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (!device)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ device->no_hw = physical_device->no_hw;
+ parse_debug_flags(device);
+
+ device->instance = physical_device->instance;
+
+ /* XXX(chadv): Can we dup() physicalDevice->fd here? */
+ device->fd = open(physical_device->path, O_RDWR | O_CLOEXEC);
+ if (device->fd == -1)
+ goto fail_device;
+
+ device->context_id = anv_gem_create_context(device);
+ if (device->context_id == -1)
+ goto fail_fd;
+
+ anv_bo_pool_init(&device->batch_bo_pool, device, BATCH_SIZE);
+
+ anv_block_pool_init(&device->dynamic_state_block_pool, device, 2048);
+
+ anv_state_pool_init(&device->dynamic_state_pool,
+ &device->dynamic_state_block_pool);
+
+ anv_block_pool_init(&device->instruction_block_pool, device, 2048);
+ anv_block_pool_init(&device->surface_state_block_pool, device, 2048);
+
+ anv_state_pool_init(&device->surface_state_pool,
+ &device->surface_state_block_pool);
+
+ anv_block_pool_init(&device->scratch_block_pool, device, 0x10000);
+
+ device->info = *physical_device->info;
+
+ device->compiler = anv_compiler_create(device);
+ device->aub_writer = NULL;
+
+ pthread_mutex_init(&device->mutex, NULL);
+
+ anv_queue_init(device, &device->queue);
+
+ anv_device_init_meta(device);
+
+ anv_device_init_border_colors(device);
+
+ *pDevice = anv_device_to_handle(device);
+
+ return VK_SUCCESS;
+
+ fail_fd:
+ close(device->fd);
+ fail_device:
+ anv_device_free(device, device);
+
+ return vk_error(VK_ERROR_UNAVAILABLE);
+}
+
+VkResult anv_DestroyDevice(
+ VkDevice _device)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+
+ anv_compiler_destroy(device->compiler);
+
+ anv_queue_finish(&device->queue);
+
+ anv_device_finish_meta(device);
+
+#ifdef HAVE_VALGRIND
+ /* We only need to free these to prevent valgrind errors. The backing
+ * BO will go away in a couple of lines so we don't actually leak.
+ */
+ anv_state_pool_free(&device->dynamic_state_pool, device->border_colors);
+#endif
+
+ anv_bo_pool_finish(&device->batch_bo_pool);
+ anv_block_pool_finish(&device->dynamic_state_block_pool);
+ anv_block_pool_finish(&device->instruction_block_pool);
+ anv_block_pool_finish(&device->surface_state_block_pool);
+
+ close(device->fd);
+
+ if (device->aub_writer)
+ anv_aub_writer_destroy(device->aub_writer);
+
+ anv_device_free(device, device);
+
+ return VK_SUCCESS;
+}
+
+static const VkExtensionProperties global_extensions[] = {
+ {
+ .extName = "VK_WSI_LunarG",
+ .specVersion = 3
+ }
+};
+
+VkResult anv_GetGlobalExtensionProperties(
+ const char* pLayerName,
+ uint32_t* pCount,
+ VkExtensionProperties* pProperties)
+{
+ if (pProperties == NULL) {
+ *pCount = ARRAY_SIZE(global_extensions);
+ return VK_SUCCESS;
+ }
+
+ assert(*pCount < ARRAY_SIZE(global_extensions));
+
+ *pCount = ARRAY_SIZE(global_extensions);
+ memcpy(pProperties, global_extensions, sizeof(global_extensions));
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetPhysicalDeviceExtensionProperties(
+ VkPhysicalDevice physicalDevice,
+ const char* pLayerName,
+ uint32_t* pCount,
+ VkExtensionProperties* pProperties)
+{
+ if (pProperties == NULL) {
+ *pCount = 0;
+ return VK_SUCCESS;
+ }
+
+ /* None supported at this time */
+ return vk_error(VK_ERROR_INVALID_EXTENSION);
+}
+
+VkResult anv_GetGlobalLayerProperties(
+ uint32_t* pCount,
+ VkLayerProperties* pProperties)
+{
+ if (pProperties == NULL) {
+ *pCount = 0;
+ return VK_SUCCESS;
+ }
+
+ /* None supported at this time */
+ return vk_error(VK_ERROR_INVALID_LAYER);
+}
+
+VkResult anv_GetPhysicalDeviceLayerProperties(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pCount,
+ VkLayerProperties* pProperties)
+{
+ if (pProperties == NULL) {
+ *pCount = 0;
+ return VK_SUCCESS;
+ }
+
+ /* None supported at this time */
+ return vk_error(VK_ERROR_INVALID_LAYER);
+}
+
+VkResult anv_GetDeviceQueue(
+ VkDevice _device,
+ uint32_t queueNodeIndex,
+ uint32_t queueIndex,
+ VkQueue* pQueue)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+
+ assert(queueIndex == 0);
+
+ *pQueue = anv_queue_to_handle(&device->queue);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_QueueSubmit(
+ VkQueue _queue,
+ uint32_t cmdBufferCount,
+ const VkCmdBuffer* pCmdBuffers,
+ VkFence _fence)
+{
+ ANV_FROM_HANDLE(anv_queue, queue, _queue);
+ ANV_FROM_HANDLE(anv_fence, fence, _fence);
+ struct anv_device *device = queue->device;
+ int ret;
+
+ for (uint32_t i = 0; i < cmdBufferCount; i++) {
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, pCmdBuffers[i]);
+
+ if (device->dump_aub)
+ anv_cmd_buffer_dump(cmd_buffer);
+
+ if (!device->no_hw) {
+ ret = anv_gem_execbuffer(device, &cmd_buffer->execbuf);
+ if (ret != 0)
+ return vk_error(VK_ERROR_UNKNOWN);
+
+ if (fence) {
+ ret = anv_gem_execbuffer(device, &fence->execbuf);
+ if (ret != 0)
+ return vk_error(VK_ERROR_UNKNOWN);
+ }
+
+ for (uint32_t i = 0; i < cmd_buffer->exec2_bo_count; i++)
+ cmd_buffer->exec2_bos[i]->offset = cmd_buffer->exec2_objects[i].offset;
+ } else {
+ *(uint32_t *)queue->completed_serial.map = cmd_buffer->serial;
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_QueueWaitIdle(
+ VkQueue _queue)
+{
+ ANV_FROM_HANDLE(anv_queue, queue, _queue);
+
+ return vkDeviceWaitIdle(anv_device_to_handle(queue->device));
+}
+
+VkResult anv_DeviceWaitIdle(
+ VkDevice _device)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_state state;
+ struct anv_batch batch;
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 exec2_objects[1];
+ struct anv_bo *bo = NULL;
+ VkResult result;
+ int64_t timeout;
+ int ret;
+
+ state = anv_state_pool_alloc(&device->dynamic_state_pool, 32, 32);
+ bo = &device->dynamic_state_pool.block_pool->bo;
+ batch.start = batch.next = state.map;
+ batch.end = state.map + 32;
+ anv_batch_emit(&batch, GEN8_MI_BATCH_BUFFER_END);
+ anv_batch_emit(&batch, GEN8_MI_NOOP);
+
+ exec2_objects[0].handle = bo->gem_handle;
+ exec2_objects[0].relocation_count = 0;
+ exec2_objects[0].relocs_ptr = 0;
+ exec2_objects[0].alignment = 0;
+ exec2_objects[0].offset = bo->offset;
+ exec2_objects[0].flags = 0;
+ exec2_objects[0].rsvd1 = 0;
+ exec2_objects[0].rsvd2 = 0;
+
+ execbuf.buffers_ptr = (uintptr_t) exec2_objects;
+ execbuf.buffer_count = 1;
+ execbuf.batch_start_offset = state.offset;
+ execbuf.batch_len = batch.next - state.map;
+ execbuf.cliprects_ptr = 0;
+ execbuf.num_cliprects = 0;
+ execbuf.DR1 = 0;
+ execbuf.DR4 = 0;
+
+ execbuf.flags =
+ I915_EXEC_HANDLE_LUT | I915_EXEC_NO_RELOC | I915_EXEC_RENDER;
+ execbuf.rsvd1 = device->context_id;
+ execbuf.rsvd2 = 0;
+
+ if (!device->no_hw) {
+ ret = anv_gem_execbuffer(device, &execbuf);
+ if (ret != 0) {
+ result = vk_error(VK_ERROR_UNKNOWN);
+ goto fail;
+ }
+
+ timeout = INT64_MAX;
+ ret = anv_gem_wait(device, bo->gem_handle, &timeout);
+ if (ret != 0) {
+ result = vk_error(VK_ERROR_UNKNOWN);
+ goto fail;
+ }
+ }
+
+ anv_state_pool_free(&device->dynamic_state_pool, state);
+
+ return VK_SUCCESS;
+
+ fail:
+ anv_state_pool_free(&device->dynamic_state_pool, state);
+
+ return result;
+}
+
+void *
+anv_device_alloc(struct anv_device * device,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocType allocType)
+{
+ return device->instance->pfnAlloc(device->instance->pAllocUserData,
+ size,
+ alignment,
+ allocType);
+}
+
+void
+anv_device_free(struct anv_device * device,
+ void * mem)
+{
+ if (mem == NULL)
+ return;
+
+ return device->instance->pfnFree(device->instance->pAllocUserData,
+ mem);
+}
+
+VkResult
+anv_bo_init_new(struct anv_bo *bo, struct anv_device *device, uint64_t size)
+{
+ bo->gem_handle = anv_gem_create(device, size);
+ if (!bo->gem_handle)
+ return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
+
+ bo->map = NULL;
+ bo->index = 0;
+ bo->offset = 0;
+ bo->size = size;
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_AllocMemory(
+ VkDevice _device,
+ const VkMemoryAllocInfo* pAllocInfo,
+ VkDeviceMemory* pMem)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_device_memory *mem;
+ VkResult result;
+
+ assert(pAllocInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO);
+
+ if (pAllocInfo->memoryTypeIndex != 0) {
+ /* We support exactly one memory heap. */
+ return vk_error(VK_ERROR_INVALID_VALUE);
+ }
+
+ /* FINISHME: Fail if allocation request exceeds heap size. */
+
+ mem = anv_device_alloc(device, sizeof(*mem), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (mem == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ result = anv_bo_init_new(&mem->bo, device, pAllocInfo->allocationSize);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ *pMem = anv_device_memory_to_handle(mem);
+
+ return VK_SUCCESS;
+
+ fail:
+ anv_device_free(device, mem);
+
+ return result;
+}
+
+VkResult anv_FreeMemory(
+ VkDevice _device,
+ VkDeviceMemory _mem)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_device_memory, mem, _mem);
+
+ if (mem->bo.map)
+ anv_gem_munmap(mem->bo.map, mem->bo.size);
+
+ if (mem->bo.gem_handle != 0)
+ anv_gem_close(device, mem->bo.gem_handle);
+
+ anv_device_free(device, mem);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_MapMemory(
+ VkDevice _device,
+ VkDeviceMemory _mem,
+ VkDeviceSize offset,
+ VkDeviceSize size,
+ VkMemoryMapFlags flags,
+ void** ppData)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_device_memory, mem, _mem);
+
+ /* FIXME: Is this supposed to be thread safe? Since vkUnmapMemory() only
+ * takes a VkDeviceMemory pointer, it seems like only one map of the memory
+ * at a time is valid. We could just mmap up front and return an offset
+ * pointer here, but that may exhaust virtual memory on 32 bit
+ * userspace. */
+
+ mem->map = anv_gem_mmap(device, mem->bo.gem_handle, offset, size);
+ mem->map_size = size;
+
+ *ppData = mem->map;
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_UnmapMemory(
+ VkDevice _device,
+ VkDeviceMemory _mem)
+{
+ ANV_FROM_HANDLE(anv_device_memory, mem, _mem);
+
+ anv_gem_munmap(mem->map, mem->map_size);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_FlushMappedMemoryRanges(
+ VkDevice device,
+ uint32_t memRangeCount,
+ const VkMappedMemoryRange* pMemRanges)
+{
+ /* clflush here for !llc platforms */
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_InvalidateMappedMemoryRanges(
+ VkDevice device,
+ uint32_t memRangeCount,
+ const VkMappedMemoryRange* pMemRanges)
+{
+ return anv_FlushMappedMemoryRanges(device, memRangeCount, pMemRanges);
+}
+
+VkResult anv_GetBufferMemoryRequirements(
+ VkDevice device,
+ VkBuffer _buffer,
+ VkMemoryRequirements* pMemoryRequirements)
+{
+ ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
+
+ /* The Vulkan spec (git aaed022) says:
+ *
+ * memoryTypeBits is a bitfield and contains one bit set for every
+ * supported memory type for the resource. The bit `1<<i` is set if and
+ * only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
+ * structure for the physical device is supported.
+ *
+ * We support exactly one memory type.
+ */
+ pMemoryRequirements->memoryTypeBits = 1;
+
+ pMemoryRequirements->size = buffer->size;
+ pMemoryRequirements->alignment = 16;
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetImageMemoryRequirements(
+ VkDevice device,
+ VkImage _image,
+ VkMemoryRequirements* pMemoryRequirements)
+{
+ ANV_FROM_HANDLE(anv_image, image, _image);
+
+ /* The Vulkan spec (git aaed022) says:
+ *
+ * memoryTypeBits is a bitfield and contains one bit set for every
+ * supported memory type for the resource. The bit `1<<i` is set if and
+ * only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
+ * structure for the physical device is supported.
+ *
+ * We support exactly one memory type.
+ */
+ pMemoryRequirements->memoryTypeBits = 1;
+
+ pMemoryRequirements->size = image->size;
+ pMemoryRequirements->alignment = image->alignment;
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetImageSparseMemoryRequirements(
+ VkDevice device,
+ VkImage image,
+ uint32_t* pNumRequirements,
+ VkSparseImageMemoryRequirements* pSparseMemoryRequirements)
+{
+ return vk_error(VK_UNSUPPORTED);
+}
+
+VkResult anv_GetDeviceMemoryCommitment(
+ VkDevice device,
+ VkDeviceMemory memory,
+ VkDeviceSize* pCommittedMemoryInBytes)
+{
+ *pCommittedMemoryInBytes = 0;
+ stub_return(VK_SUCCESS);
+}
+
+VkResult anv_BindBufferMemory(
+ VkDevice device,
+ VkBuffer _buffer,
+ VkDeviceMemory _mem,
+ VkDeviceSize memOffset)
+{
+ ANV_FROM_HANDLE(anv_device_memory, mem, _mem);
+ ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
+
+ buffer->bo = &mem->bo;
+ buffer->offset = memOffset;
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_BindImageMemory(
+ VkDevice device,
+ VkImage _image,
+ VkDeviceMemory _mem,
+ VkDeviceSize memOffset)
+{
+ ANV_FROM_HANDLE(anv_device_memory, mem, _mem);
+ ANV_FROM_HANDLE(anv_image, image, _image);
+
+ image->bo = &mem->bo;
+ image->offset = memOffset;
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_QueueBindSparseBufferMemory(
+ VkQueue queue,
+ VkBuffer buffer,
+ uint32_t numBindings,
+ const VkSparseMemoryBindInfo* pBindInfo)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_QueueBindSparseImageOpaqueMemory(
+ VkQueue queue,
+ VkImage image,
+ uint32_t numBindings,
+ const VkSparseMemoryBindInfo* pBindInfo)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_QueueBindSparseImageMemory(
+ VkQueue queue,
+ VkImage image,
+ uint32_t numBindings,
+ const VkSparseImageMemoryBindInfo* pBindInfo)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_CreateFence(
+ VkDevice _device,
+ const VkFenceCreateInfo* pCreateInfo,
+ VkFence* pFence)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_fence *fence;
+ struct anv_batch batch;
+ VkResult result;
+
+ const uint32_t fence_size = 128;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO);
+
+ fence = anv_device_alloc(device, sizeof(*fence), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (fence == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ result = anv_bo_init_new(&fence->bo, device, fence_size);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ fence->bo.map =
+ anv_gem_mmap(device, fence->bo.gem_handle, 0, fence->bo.size);
+ batch.next = batch.start = fence->bo.map;
+ batch.end = fence->bo.map + fence->bo.size;
+ anv_batch_emit(&batch, GEN8_MI_BATCH_BUFFER_END);
+ anv_batch_emit(&batch, GEN8_MI_NOOP);
+
+ fence->exec2_objects[0].handle = fence->bo.gem_handle;
+ fence->exec2_objects[0].relocation_count = 0;
+ fence->exec2_objects[0].relocs_ptr = 0;
+ fence->exec2_objects[0].alignment = 0;
+ fence->exec2_objects[0].offset = fence->bo.offset;
+ fence->exec2_objects[0].flags = 0;
+ fence->exec2_objects[0].rsvd1 = 0;
+ fence->exec2_objects[0].rsvd2 = 0;
+
+ fence->execbuf.buffers_ptr = (uintptr_t) fence->exec2_objects;
+ fence->execbuf.buffer_count = 1;
+ fence->execbuf.batch_start_offset = 0;
+ fence->execbuf.batch_len = batch.next - fence->bo.map;
+ fence->execbuf.cliprects_ptr = 0;
+ fence->execbuf.num_cliprects = 0;
+ fence->execbuf.DR1 = 0;
+ fence->execbuf.DR4 = 0;
+
+ fence->execbuf.flags =
+ I915_EXEC_HANDLE_LUT | I915_EXEC_NO_RELOC | I915_EXEC_RENDER;
+ fence->execbuf.rsvd1 = device->context_id;
+ fence->execbuf.rsvd2 = 0;
+
+ *pFence = anv_fence_to_handle(fence);
+
+ return VK_SUCCESS;
+
+ fail:
+ anv_device_free(device, fence);
+
+ return result;
+}
+
+VkResult anv_DestroyFence(
+ VkDevice _device,
+ VkFence _fence)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_fence, fence, _fence);
+
+ anv_gem_munmap(fence->bo.map, fence->bo.size);
+ anv_gem_close(device, fence->bo.gem_handle);
+ anv_device_free(device, fence);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_ResetFences(
+ VkDevice _device,
+ uint32_t fenceCount,
+ const VkFence* pFences)
+{
+ for (uint32_t i = 0; i < fenceCount; i++) {
+ ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
+ fence->ready = false;
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetFenceStatus(
+ VkDevice _device,
+ VkFence _fence)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_fence, fence, _fence);
+ int64_t t = 0;
+ int ret;
+
+ if (fence->ready)
+ return VK_SUCCESS;
+
+ ret = anv_gem_wait(device, fence->bo.gem_handle, &t);
+ if (ret == 0) {
+ fence->ready = true;
+ return VK_SUCCESS;
+ }
+
+ return VK_NOT_READY;
+}
+
+VkResult anv_WaitForFences(
+ VkDevice _device,
+ uint32_t fenceCount,
+ const VkFence* pFences,
+ VkBool32 waitAll,
+ uint64_t timeout)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ int64_t t = timeout;
+ int ret;
+
+ /* FIXME: handle !waitAll */
+
+ for (uint32_t i = 0; i < fenceCount; i++) {
+ ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
+ ret = anv_gem_wait(device, fence->bo.gem_handle, &t);
+ if (ret == -1 && errno == ETIME)
+ return VK_TIMEOUT;
+ else if (ret == -1)
+ return vk_error(VK_ERROR_UNKNOWN);
+ }
+
+ return VK_SUCCESS;
+}
+
+// Queue semaphore functions
+
+VkResult anv_CreateSemaphore(
+ VkDevice device,
+ const VkSemaphoreCreateInfo* pCreateInfo,
+ VkSemaphore* pSemaphore)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_DestroySemaphore(
+ VkDevice device,
+ VkSemaphore semaphore)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_QueueSignalSemaphore(
+ VkQueue queue,
+ VkSemaphore semaphore)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_QueueWaitSemaphore(
+ VkQueue queue,
+ VkSemaphore semaphore)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+// Event functions
+
+VkResult anv_CreateEvent(
+ VkDevice device,
+ const VkEventCreateInfo* pCreateInfo,
+ VkEvent* pEvent)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_DestroyEvent(
+ VkDevice device,
+ VkEvent event)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_GetEventStatus(
+ VkDevice device,
+ VkEvent event)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_SetEvent(
+ VkDevice device,
+ VkEvent event)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_ResetEvent(
+ VkDevice device,
+ VkEvent event)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+// Buffer functions
+
+VkResult anv_CreateBuffer(
+ VkDevice _device,
+ const VkBufferCreateInfo* pCreateInfo,
+ VkBuffer* pBuffer)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_buffer *buffer;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
+
+ buffer = anv_device_alloc(device, sizeof(*buffer), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (buffer == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ buffer->size = pCreateInfo->size;
+ buffer->bo = NULL;
+ buffer->offset = 0;
+
+ *pBuffer = anv_buffer_to_handle(buffer);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyBuffer(
+ VkDevice _device,
+ VkBuffer _buffer)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
+
+ anv_device_free(device, buffer);
+
+ return VK_SUCCESS;
+}
+
+// Buffer view functions
+
+void
+anv_fill_buffer_surface_state(void *state, VkFormat format,
+ uint32_t offset, uint32_t range)
+{
+ const struct anv_format *info;
+
+ info = anv_format_for_vk_format(format);
+ /* This assumes RGBA float format. */
+ uint32_t stride = 4;
+ uint32_t num_elements = range / stride;
+
+ struct GEN8_RENDER_SURFACE_STATE surface_state = {
+ .SurfaceType = SURFTYPE_BUFFER,
+ .SurfaceArray = false,
+ .SurfaceFormat = info->surface_format,
+ .SurfaceVerticalAlignment = VALIGN4,
+ .SurfaceHorizontalAlignment = HALIGN4,
+ .TileMode = LINEAR,
+ .VerticalLineStride = 0,
+ .VerticalLineStrideOffset = 0,
+ .SamplerL2BypassModeDisable = true,
+ .RenderCacheReadWriteMode = WriteOnlyCache,
+ .MemoryObjectControlState = GEN8_MOCS,
+ .BaseMipLevel = 0.0,
+ .SurfaceQPitch = 0,
+ .Height = (num_elements >> 7) & 0x3fff,
+ .Width = num_elements & 0x7f,
+ .Depth = (num_elements >> 21) & 0x3f,
+ .SurfacePitch = stride - 1,
+ .MinimumArrayElement = 0,
+ .NumberofMultisamples = MULTISAMPLECOUNT_1,
+ .XOffset = 0,
+ .YOffset = 0,
+ .SurfaceMinLOD = 0,
+ .MIPCountLOD = 0,
+ .AuxiliarySurfaceMode = AUX_NONE,
+ .RedClearColor = 0,
+ .GreenClearColor = 0,
+ .BlueClearColor = 0,
+ .AlphaClearColor = 0,
+ .ShaderChannelSelectRed = SCS_RED,
+ .ShaderChannelSelectGreen = SCS_GREEN,
+ .ShaderChannelSelectBlue = SCS_BLUE,
+ .ShaderChannelSelectAlpha = SCS_ALPHA,
+ .ResourceMinLOD = 0.0,
+ /* FIXME: We assume that the image must be bound at this time. */
+ .SurfaceBaseAddress = { NULL, offset },
+ };
+
+ GEN8_RENDER_SURFACE_STATE_pack(NULL, state, &surface_state);
+}
+
+VkResult anv_CreateBufferView(
+ VkDevice _device,
+ const VkBufferViewCreateInfo* pCreateInfo,
+ VkBufferView* pView)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_buffer, buffer, pCreateInfo->buffer);
+ struct anv_buffer_view *bview;
+ struct anv_surface_view *view;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO);
+
+ bview = anv_device_alloc(device, sizeof(*view), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (bview == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ view = &bview->view;
+ view->bo = buffer->bo;
+ view->offset = buffer->offset + pCreateInfo->offset;
+ view->surface_state =
+ anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
+ view->format = pCreateInfo->format;
+ view->range = pCreateInfo->range;
+
+ anv_fill_buffer_surface_state(view->surface_state.map,
+ pCreateInfo->format,
+ view->offset, pCreateInfo->range);
+
+ *pView = anv_buffer_view_to_handle(bview);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyBufferView(
+ VkDevice _device,
+ VkBufferView _bview)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_buffer_view, bview, _bview);
+
+ anv_surface_view_fini(device, &bview->view);
+ anv_device_free(device, bview);
+
+ return VK_SUCCESS;
+}
+
+// Sampler functions
+
+VkResult anv_CreateSampler(
+ VkDevice _device,
+ const VkSamplerCreateInfo* pCreateInfo,
+ VkSampler* pSampler)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_sampler *sampler;
+ uint32_t mag_filter, min_filter, max_anisotropy;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
+
+ sampler = anv_device_alloc(device, sizeof(*sampler), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (!sampler)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ static const uint32_t vk_to_gen_tex_filter[] = {
+ [VK_TEX_FILTER_NEAREST] = MAPFILTER_NEAREST,
+ [VK_TEX_FILTER_LINEAR] = MAPFILTER_LINEAR
+ };
+
+ static const uint32_t vk_to_gen_mipmap_mode[] = {
+ [VK_TEX_MIPMAP_MODE_BASE] = MIPFILTER_NONE,
+ [VK_TEX_MIPMAP_MODE_NEAREST] = MIPFILTER_NEAREST,
+ [VK_TEX_MIPMAP_MODE_LINEAR] = MIPFILTER_LINEAR
+ };
+
+ static const uint32_t vk_to_gen_tex_address[] = {
+ [VK_TEX_ADDRESS_WRAP] = TCM_WRAP,
+ [VK_TEX_ADDRESS_MIRROR] = TCM_MIRROR,
+ [VK_TEX_ADDRESS_CLAMP] = TCM_CLAMP,
+ [VK_TEX_ADDRESS_MIRROR_ONCE] = TCM_MIRROR_ONCE,
+ [VK_TEX_ADDRESS_CLAMP_BORDER] = TCM_CLAMP_BORDER,
+ };
+
+ static const uint32_t vk_to_gen_compare_op[] = {
+ [VK_COMPARE_OP_NEVER] = PREFILTEROPNEVER,
+ [VK_COMPARE_OP_LESS] = PREFILTEROPLESS,
+ [VK_COMPARE_OP_EQUAL] = PREFILTEROPEQUAL,
+ [VK_COMPARE_OP_LESS_EQUAL] = PREFILTEROPLEQUAL,
+ [VK_COMPARE_OP_GREATER] = PREFILTEROPGREATER,
+ [VK_COMPARE_OP_NOT_EQUAL] = PREFILTEROPNOTEQUAL,
+ [VK_COMPARE_OP_GREATER_EQUAL] = PREFILTEROPGEQUAL,
+ [VK_COMPARE_OP_ALWAYS] = PREFILTEROPALWAYS,
+ };
+
+ if (pCreateInfo->maxAnisotropy > 1) {
+ mag_filter = MAPFILTER_ANISOTROPIC;
+ min_filter = MAPFILTER_ANISOTROPIC;
+ max_anisotropy = (pCreateInfo->maxAnisotropy - 2) / 2;
+ } else {
+ mag_filter = vk_to_gen_tex_filter[pCreateInfo->magFilter];
+ min_filter = vk_to_gen_tex_filter[pCreateInfo->minFilter];
+ max_anisotropy = RATIO21;
+ }
+
+ struct GEN8_SAMPLER_STATE sampler_state = {
+ .SamplerDisable = false,
+ .TextureBorderColorMode = DX10OGL,
+ .LODPreClampMode = 0,
+ .BaseMipLevel = 0.0,
+ .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipMode],
+ .MagModeFilter = mag_filter,
+ .MinModeFilter = min_filter,
+ .TextureLODBias = pCreateInfo->mipLodBias * 256,
+ .AnisotropicAlgorithm = EWAApproximation,
+ .MinLOD = pCreateInfo->minLod,
+ .MaxLOD = pCreateInfo->maxLod,
+ .ChromaKeyEnable = 0,
+ .ChromaKeyIndex = 0,
+ .ChromaKeyMode = 0,
+ .ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
+ .CubeSurfaceControlMode = 0,
+
+ .IndirectStatePointer =
+ device->border_colors.offset +
+ pCreateInfo->borderColor * sizeof(float) * 4,
+
+ .LODClampMagnificationMode = MIPNONE,
+ .MaximumAnisotropy = max_anisotropy,
+ .RAddressMinFilterRoundingEnable = 0,
+ .RAddressMagFilterRoundingEnable = 0,
+ .VAddressMinFilterRoundingEnable = 0,
+ .VAddressMagFilterRoundingEnable = 0,
+ .UAddressMinFilterRoundingEnable = 0,
+ .UAddressMagFilterRoundingEnable = 0,
+ .TrilinearFilterQuality = 0,
+ .NonnormalizedCoordinateEnable = 0,
+ .TCXAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressU],
+ .TCYAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressV],
+ .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressW],
+ };
+
+ GEN8_SAMPLER_STATE_pack(NULL, sampler->state, &sampler_state);
+
+ *pSampler = anv_sampler_to_handle(sampler);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroySampler(
+ VkDevice _device,
+ VkSampler _sampler)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_sampler, sampler, _sampler);
+
+ anv_device_free(device, sampler);
+
+ return VK_SUCCESS;
+}
+
+// Descriptor set functions
+
+VkResult anv_CreateDescriptorSetLayout(
+ VkDevice _device,
+ const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+ VkDescriptorSetLayout* pSetLayout)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_descriptor_set_layout *set_layout;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
+
+ uint32_t sampler_count[VK_SHADER_STAGE_NUM] = { 0, };
+ uint32_t surface_count[VK_SHADER_STAGE_NUM] = { 0, };
+ uint32_t num_dynamic_buffers = 0;
+ uint32_t count = 0;
+ uint32_t stages = 0;
+ uint32_t s;
+
+ for (uint32_t i = 0; i < pCreateInfo->count; i++) {
+ switch (pCreateInfo->pBinding[i].descriptorType) {
+ case VK_DESCRIPTOR_TYPE_SAMPLER:
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
+ sampler_count[s] += pCreateInfo->pBinding[i].arraySize;
+ break;
+ default:
+ break;
+ }
+
+ switch (pCreateInfo->pBinding[i].descriptorType) {
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+ for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
+ surface_count[s] += pCreateInfo->pBinding[i].arraySize;
+ break;
+ default:
+ break;
+ }
+
+ switch (pCreateInfo->pBinding[i].descriptorType) {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ num_dynamic_buffers += pCreateInfo->pBinding[i].arraySize;
+ break;
+ default:
+ break;
+ }
+
+ stages |= pCreateInfo->pBinding[i].stageFlags;
+ count += pCreateInfo->pBinding[i].arraySize;
+ }
+
+ uint32_t sampler_total = 0;
+ uint32_t surface_total = 0;
+ for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
+ sampler_total += sampler_count[s];
+ surface_total += surface_count[s];
+ }
+
+ size_t size = sizeof(*set_layout) +
+ (sampler_total + surface_total) * sizeof(set_layout->entries[0]);
+ set_layout = anv_device_alloc(device, size, 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (!set_layout)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ set_layout->num_dynamic_buffers = num_dynamic_buffers;
+ set_layout->count = count;
+ set_layout->shader_stages = stages;
+
+ struct anv_descriptor_slot *p = set_layout->entries;
+ struct anv_descriptor_slot *sampler[VK_SHADER_STAGE_NUM];
+ struct anv_descriptor_slot *surface[VK_SHADER_STAGE_NUM];
+ for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
+ set_layout->stage[s].surface_count = surface_count[s];
+ set_layout->stage[s].surface_start = surface[s] = p;
+ p += surface_count[s];
+ set_layout->stage[s].sampler_count = sampler_count[s];
+ set_layout->stage[s].sampler_start = sampler[s] = p;
+ p += sampler_count[s];
+ }
+
+ uint32_t descriptor = 0;
+ int8_t dynamic_slot = 0;
+ bool is_dynamic;
+ for (uint32_t i = 0; i < pCreateInfo->count; i++) {
+ switch (pCreateInfo->pBinding[i].descriptorType) {
+ case VK_DESCRIPTOR_TYPE_SAMPLER:
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
+ for (uint32_t j = 0; j < pCreateInfo->pBinding[i].arraySize; j++) {
+ sampler[s]->index = descriptor + j;
+ sampler[s]->dynamic_slot = -1;
+ sampler[s]++;
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (pCreateInfo->pBinding[i].descriptorType) {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ is_dynamic = true;
+ break;
+ default:
+ is_dynamic = false;
+ break;
+ }
+
+ switch (pCreateInfo->pBinding[i].descriptorType) {
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+ for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
+ for (uint32_t j = 0; j < pCreateInfo->pBinding[i].arraySize; j++) {
+ surface[s]->index = descriptor + j;
+ if (is_dynamic)
+ surface[s]->dynamic_slot = dynamic_slot + j;
+ else
+ surface[s]->dynamic_slot = -1;
+ surface[s]++;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (is_dynamic)
+ dynamic_slot += pCreateInfo->pBinding[i].arraySize;
+
+ descriptor += pCreateInfo->pBinding[i].arraySize;
+ }
+
+ *pSetLayout = anv_descriptor_set_layout_to_handle(set_layout);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyDescriptorSetLayout(
+ VkDevice _device,
+ VkDescriptorSetLayout _set_layout)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout, _set_layout);
+
+ anv_device_free(device, set_layout);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_CreateDescriptorPool(
+ VkDevice device,
+ VkDescriptorPoolUsage poolUsage,
+ uint32_t maxSets,
+ const VkDescriptorPoolCreateInfo* pCreateInfo,
+ VkDescriptorPool* pDescriptorPool)
+{
+ anv_finishme("VkDescriptorPool is a stub");
+ pDescriptorPool->handle = 1;
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyDescriptorPool(
+ VkDevice _device,
+ VkDescriptorPool _pool)
+{
+ anv_finishme("VkDescriptorPool is a stub: free the pool's descriptor sets");
+ return VK_SUCCESS;
+}
+
+VkResult anv_ResetDescriptorPool(
+ VkDevice device,
+ VkDescriptorPool descriptorPool)
+{
+ anv_finishme("VkDescriptorPool is a stub: free the pool's descriptor sets");
+ return VK_SUCCESS;
+}
+
+VkResult
+anv_descriptor_set_create(struct anv_device *device,
+ const struct anv_descriptor_set_layout *layout,
+ struct anv_descriptor_set **out_set)
+{
+ struct anv_descriptor_set *set;
+ size_t size = sizeof(*set) + layout->count * sizeof(set->descriptors[0]);
+
+ set = anv_device_alloc(device, size, 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (!set)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ /* A descriptor set may not be 100% filled. Clear the set so we can can
+ * later detect holes in it.
+ */
+ memset(set, 0, size);
+
+ *out_set = set;
+
+ return VK_SUCCESS;
+}
+
+void
+anv_descriptor_set_destroy(struct anv_device *device,
+ struct anv_descriptor_set *set)
+{
+ anv_device_free(device, set);
+}
+
+VkResult anv_AllocDescriptorSets(
+ VkDevice _device,
+ VkDescriptorPool descriptorPool,
+ VkDescriptorSetUsage setUsage,
+ uint32_t count,
+ const VkDescriptorSetLayout* pSetLayouts,
+ VkDescriptorSet* pDescriptorSets,
+ uint32_t* pCount)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+
+ VkResult result;
+ struct anv_descriptor_set *set;
+
+ for (uint32_t i = 0; i < count; i++) {
+ ANV_FROM_HANDLE(anv_descriptor_set_layout, layout, pSetLayouts[i]);
+
+ result = anv_descriptor_set_create(device, layout, &set);
+ if (result != VK_SUCCESS) {
+ *pCount = i;
+ return result;
+ }
+
+ pDescriptorSets[i] = anv_descriptor_set_to_handle(set);
+ }
+
+ *pCount = count;
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_UpdateDescriptorSets(
+ VkDevice device,
+ uint32_t writeCount,
+ const VkWriteDescriptorSet* pDescriptorWrites,
+ uint32_t copyCount,
+ const VkCopyDescriptorSet* pDescriptorCopies)
+{
+ for (uint32_t i = 0; i < writeCount; i++) {
+ const VkWriteDescriptorSet *write = &pDescriptorWrites[i];
+ ANV_FROM_HANDLE(anv_descriptor_set, set, write->destSet);
+
+ switch (write->descriptorType) {
+ case VK_DESCRIPTOR_TYPE_SAMPLER:
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ for (uint32_t j = 0; j < write->count; j++) {
+ set->descriptors[write->destBinding + j].sampler =
+ anv_sampler_from_handle(write->pDescriptors[j].sampler);
+ }
+
+ if (write->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
+ break;
+
+ /* fallthrough */
+
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ for (uint32_t j = 0; j < write->count; j++) {
+ ANV_FROM_HANDLE(anv_image_view, iview,
+ write->pDescriptors[j].imageView);
+ set->descriptors[write->destBinding + j].view = &iview->view;
+ }
+ break;
+
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ anv_finishme("texel buffers not implemented");
+ break;
+
+ case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+ anv_finishme("input attachments not implemented");
+ break;
+
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ for (uint32_t j = 0; j < write->count; j++) {
+ ANV_FROM_HANDLE(anv_buffer_view, bview,
+ write->pDescriptors[j].bufferView);
+ set->descriptors[write->destBinding + j].view = &bview->view;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ for (uint32_t i = 0; i < copyCount; i++) {
+ const VkCopyDescriptorSet *copy = &pDescriptorCopies[i];
+ ANV_FROM_HANDLE(anv_descriptor_set, src, copy->destSet);
+ ANV_FROM_HANDLE(anv_descriptor_set, dest, copy->destSet);
+ for (uint32_t j = 0; j < copy->count; j++) {
+ dest->descriptors[copy->destBinding + j] =
+ src->descriptors[copy->srcBinding + j];
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+// State object functions
+
+static inline int64_t
+clamp_int64(int64_t x, int64_t min, int64_t max)
+{
+ if (x < min)
+ return min;
+ else if (x < max)
+ return x;
+ else
+ return max;
+}
+
+VkResult anv_CreateDynamicViewportState(
+ VkDevice _device,
+ const VkDynamicViewportStateCreateInfo* pCreateInfo,
+ VkDynamicViewportState* pState)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_dynamic_vp_state *state;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_VIEWPORT_STATE_CREATE_INFO);
+
+ state = anv_device_alloc(device, sizeof(*state), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (state == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ unsigned count = pCreateInfo->viewportAndScissorCount;
+ state->sf_clip_vp = anv_state_pool_alloc(&device->dynamic_state_pool,
+ count * 64, 64);
+ state->cc_vp = anv_state_pool_alloc(&device->dynamic_state_pool,
+ count * 8, 32);
+ state->scissor = anv_state_pool_alloc(&device->dynamic_state_pool,
+ count * 32, 32);
+
+ for (uint32_t i = 0; i < pCreateInfo->viewportAndScissorCount; i++) {
+ const VkViewport *vp = &pCreateInfo->pViewports[i];
+ const VkRect2D *s = &pCreateInfo->pScissors[i];
+
+ struct GEN8_SF_CLIP_VIEWPORT sf_clip_viewport = {
+ .ViewportMatrixElementm00 = vp->width / 2,
+ .ViewportMatrixElementm11 = vp->height / 2,
+ .ViewportMatrixElementm22 = (vp->maxDepth - vp->minDepth) / 2,
+ .ViewportMatrixElementm30 = vp->originX + vp->width / 2,
+ .ViewportMatrixElementm31 = vp->originY + vp->height / 2,
+ .ViewportMatrixElementm32 = (vp->maxDepth + vp->minDepth) / 2,
+ .XMinClipGuardband = -1.0f,
+ .XMaxClipGuardband = 1.0f,
+ .YMinClipGuardband = -1.0f,
+ .YMaxClipGuardband = 1.0f,
+ .XMinViewPort = vp->originX,
+ .XMaxViewPort = vp->originX + vp->width - 1,
+ .YMinViewPort = vp->originY,
+ .YMaxViewPort = vp->originY + vp->height - 1,
+ };
+
+ struct GEN8_CC_VIEWPORT cc_viewport = {
+ .MinimumDepth = vp->minDepth,
+ .MaximumDepth = vp->maxDepth
+ };
+
+ /* Since xmax and ymax are inclusive, we have to have xmax < xmin or
+ * ymax < ymin for empty clips. In case clip x, y, width height are all
+ * 0, the clamps below produce 0 for xmin, ymin, xmax, ymax, which isn't
+ * what we want. Just special case empty clips and produce a canonical
+ * empty clip. */
+ static const struct GEN8_SCISSOR_RECT empty_scissor = {
+ .ScissorRectangleYMin = 1,
+ .ScissorRectangleXMin = 1,
+ .ScissorRectangleYMax = 0,
+ .ScissorRectangleXMax = 0
+ };
+
+ const int max = 0xffff;
+ struct GEN8_SCISSOR_RECT scissor = {
+ /* Do this math using int64_t so overflow gets clamped correctly. */
+ .ScissorRectangleYMin = clamp_int64(s->offset.y, 0, max),
+ .ScissorRectangleXMin = clamp_int64(s->offset.x, 0, max),
+ .ScissorRectangleYMax = clamp_int64((uint64_t) s->offset.y + s->extent.height - 1, 0, max),
+ .ScissorRectangleXMax = clamp_int64((uint64_t) s->offset.x + s->extent.width - 1, 0, max)
+ };
+
+ GEN8_SF_CLIP_VIEWPORT_pack(NULL, state->sf_clip_vp.map + i * 64, &sf_clip_viewport);
+ GEN8_CC_VIEWPORT_pack(NULL, state->cc_vp.map + i * 32, &cc_viewport);
+
+ if (s->extent.width <= 0 || s->extent.height <= 0) {
+ GEN8_SCISSOR_RECT_pack(NULL, state->scissor.map + i * 32, &empty_scissor);
+ } else {
+ GEN8_SCISSOR_RECT_pack(NULL, state->scissor.map + i * 32, &scissor);
+ }
+ }
+
+ *pState = anv_dynamic_vp_state_to_handle(state);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyDynamicViewportState(
+ VkDevice _device,
+ VkDynamicViewportState _vp_state)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_dynamic_vp_state, vp_state, _vp_state);
+
+ anv_state_pool_free(&device->dynamic_state_pool, vp_state->sf_clip_vp);
+ anv_state_pool_free(&device->dynamic_state_pool, vp_state->cc_vp);
+ anv_state_pool_free(&device->dynamic_state_pool, vp_state->scissor);
+
+ anv_device_free(device, vp_state);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_CreateDynamicRasterState(
+ VkDevice _device,
+ const VkDynamicRasterStateCreateInfo* pCreateInfo,
+ VkDynamicRasterState* pState)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_dynamic_rs_state *state;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_RASTER_STATE_CREATE_INFO);
+
+ state = anv_device_alloc(device, sizeof(*state), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (state == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ struct GEN8_3DSTATE_SF sf = {
+ GEN8_3DSTATE_SF_header,
+ .LineWidth = pCreateInfo->lineWidth,
+ };
+
+ GEN8_3DSTATE_SF_pack(NULL, state->state_sf, &sf);
+
+ bool enable_bias = pCreateInfo->depthBias != 0.0f ||
+ pCreateInfo->slopeScaledDepthBias != 0.0f;
+ struct GEN8_3DSTATE_RASTER raster = {
+ .GlobalDepthOffsetEnableSolid = enable_bias,
+ .GlobalDepthOffsetEnableWireframe = enable_bias,
+ .GlobalDepthOffsetEnablePoint = enable_bias,
+ .GlobalDepthOffsetConstant = pCreateInfo->depthBias,
+ .GlobalDepthOffsetScale = pCreateInfo->slopeScaledDepthBias,
+ .GlobalDepthOffsetClamp = pCreateInfo->depthBiasClamp
+ };
+
+ GEN8_3DSTATE_RASTER_pack(NULL, state->state_raster, &raster);
+
+ *pState = anv_dynamic_rs_state_to_handle(state);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyDynamicRasterState(
+ VkDevice _device,
+ VkDynamicRasterState _rs_state)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_dynamic_rs_state, rs_state, _rs_state);
+
+ anv_device_free(device, rs_state);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_CreateDynamicColorBlendState(
+ VkDevice _device,
+ const VkDynamicColorBlendStateCreateInfo* pCreateInfo,
+ VkDynamicColorBlendState* pState)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_dynamic_cb_state *state;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_COLOR_BLEND_STATE_CREATE_INFO);
+
+ state = anv_device_alloc(device, sizeof(*state), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (state == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ struct GEN8_COLOR_CALC_STATE color_calc_state = {
+ .BlendConstantColorRed = pCreateInfo->blendConst[0],
+ .BlendConstantColorGreen = pCreateInfo->blendConst[1],
+ .BlendConstantColorBlue = pCreateInfo->blendConst[2],
+ .BlendConstantColorAlpha = pCreateInfo->blendConst[3]
+ };
+
+ GEN8_COLOR_CALC_STATE_pack(NULL, state->state_color_calc, &color_calc_state);
+
+ *pState = anv_dynamic_cb_state_to_handle(state);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyDynamicColorBlendState(
+ VkDevice _device,
+ VkDynamicColorBlendState _cb_state)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_dynamic_cb_state, cb_state, _cb_state);
+
+ anv_device_free(device, cb_state);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_CreateDynamicDepthStencilState(
+ VkDevice _device,
+ const VkDynamicDepthStencilStateCreateInfo* pCreateInfo,
+ VkDynamicDepthStencilState* pState)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_dynamic_ds_state *state;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_DEPTH_STENCIL_STATE_CREATE_INFO);
+
+ state = anv_device_alloc(device, sizeof(*state), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (state == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ struct GEN8_3DSTATE_WM_DEPTH_STENCIL wm_depth_stencil = {
+ GEN8_3DSTATE_WM_DEPTH_STENCIL_header,
+
+ /* Is this what we need to do? */
+ .StencilBufferWriteEnable = pCreateInfo->stencilWriteMask != 0,
+
+ .StencilTestMask = pCreateInfo->stencilReadMask & 0xff,
+ .StencilWriteMask = pCreateInfo->stencilWriteMask & 0xff,
+
+ .BackfaceStencilTestMask = pCreateInfo->stencilReadMask & 0xff,
+ .BackfaceStencilWriteMask = pCreateInfo->stencilWriteMask & 0xff,
+ };
+
+ GEN8_3DSTATE_WM_DEPTH_STENCIL_pack(NULL, state->state_wm_depth_stencil,
+ &wm_depth_stencil);
+
+ struct GEN8_COLOR_CALC_STATE color_calc_state = {
+ .StencilReferenceValue = pCreateInfo->stencilFrontRef,
+ .BackFaceStencilReferenceValue = pCreateInfo->stencilBackRef
+ };
+
+ GEN8_COLOR_CALC_STATE_pack(NULL, state->state_color_calc, &color_calc_state);
+
+ *pState = anv_dynamic_ds_state_to_handle(state);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyDynamicDepthStencilState(
+ VkDevice _device,
+ VkDynamicDepthStencilState _ds_state)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_dynamic_ds_state, ds_state, _ds_state);
+
+ anv_device_free(device, ds_state);
+
+ return VK_SUCCESS;
+}
+
+// Command buffer functions
+
+VkResult anv_CreateCommandPool(
+ VkDevice device,
+ const VkCmdPoolCreateInfo* pCreateInfo,
+ VkCmdPool* pCmdPool)
+{
+ pCmdPool->handle = 7;
+
+ stub_return(VK_SUCCESS);
+}
+
+VkResult anv_DestroyCommandPool(
+ VkDevice device,
+ VkCmdPool cmdPool)
+{
+ stub_return(VK_SUCCESS);
+}
+
+VkResult anv_ResetCommandPool(
+ VkDevice device,
+ VkCmdPool cmdPool,
+ VkCmdPoolResetFlags flags)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_CreateFramebuffer(
+ VkDevice _device,
+ const VkFramebufferCreateInfo* pCreateInfo,
+ VkFramebuffer* pFramebuffer)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_framebuffer *framebuffer;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
+
+ size_t size = sizeof(*framebuffer) +
+ sizeof(struct anv_attachment_view *) * pCreateInfo->attachmentCount;
+ framebuffer = anv_device_alloc(device, size, 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (framebuffer == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ framebuffer->attachment_count = pCreateInfo->attachmentCount;
+ for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
+ ANV_FROM_HANDLE(anv_attachment_view, view,
+ pCreateInfo->pAttachments[i].view);
+
+ framebuffer->attachments[i] = view;
+ }
+
+ framebuffer->width = pCreateInfo->width;
+ framebuffer->height = pCreateInfo->height;
+ framebuffer->layers = pCreateInfo->layers;
+
+ anv_CreateDynamicViewportState(anv_device_to_handle(device),
+ &(VkDynamicViewportStateCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_DYNAMIC_VIEWPORT_STATE_CREATE_INFO,
+ .viewportAndScissorCount = 1,
+ .pViewports = (VkViewport[]) {
+ {
+ .originX = 0,
+ .originY = 0,
+ .width = pCreateInfo->width,
+ .height = pCreateInfo->height,
+ .minDepth = 0,
+ .maxDepth = 1
+ },
+ },
+ .pScissors = (VkRect2D[]) {
+ { { 0, 0 },
+ { pCreateInfo->width, pCreateInfo->height } },
+ }
+ },
+ &framebuffer->vp_state);
+
+ *pFramebuffer = anv_framebuffer_to_handle(framebuffer);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyFramebuffer(
+ VkDevice _device,
+ VkFramebuffer _fb)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_framebuffer, fb, _fb);
+
+ anv_DestroyDynamicViewportState(anv_device_to_handle(device),
+ fb->vp_state);
+ anv_device_free(device, fb);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_CreateRenderPass(
+ VkDevice _device,
+ const VkRenderPassCreateInfo* pCreateInfo,
+ VkRenderPass* pRenderPass)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_render_pass *pass;
+ size_t size;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
+
+ size = sizeof(*pass) +
+ pCreateInfo->subpassCount * sizeof(struct anv_subpass);
+ pass = anv_device_alloc(device, size, 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (pass == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ /* Clear the subpasses along with the parent pass. This required because
+ * each array member of anv_subpass must be a valid pointer if not NULL.
+ */
+ memset(pass, 0, size);
+
+ pass->attachment_count = pCreateInfo->attachmentCount;
+ pass->subpass_count = pCreateInfo->subpassCount;
+
+ size = pCreateInfo->attachmentCount * sizeof(*pass->attachments);
+ pass->attachments = anv_device_alloc(device, size, 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
+ pass->attachments[i].format = pCreateInfo->pAttachments[i].format;
+ pass->attachments[i].samples = pCreateInfo->pAttachments[i].samples;
+ pass->attachments[i].load_op = pCreateInfo->pAttachments[i].loadOp;
+ pass->attachments[i].stencil_load_op = pCreateInfo->pAttachments[i].stencilLoadOp;
+ // pass->attachments[i].store_op = pCreateInfo->pAttachments[i].storeOp;
+ // pass->attachments[i].stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
+ }
+
+ for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
+ const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i];
+ struct anv_subpass *subpass = &pass->subpasses[i];
+
+ subpass->input_count = desc->inputCount;
+ subpass->color_count = desc->colorCount;
+
+ if (desc->inputCount > 0) {
+ subpass->input_attachments =
+ anv_device_alloc(device, desc->inputCount * sizeof(uint32_t),
+ 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+
+ for (uint32_t j = 0; j < desc->inputCount; j++) {
+ subpass->input_attachments[j]
+ = desc->inputAttachments[j].attachment;
+ }
+ }
+
+ if (desc->colorCount > 0) {
+ subpass->color_attachments =
+ anv_device_alloc(device, desc->colorCount * sizeof(uint32_t),
+ 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+
+ for (uint32_t j = 0; j < desc->colorCount; j++) {
+ subpass->color_attachments[j]
+ = desc->colorAttachments[j].attachment;
+ }
+ }
+
+ if (desc->resolveAttachments) {
+ subpass->resolve_attachments =
+ anv_device_alloc(device, desc->colorCount * sizeof(uint32_t),
+ 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+
+ for (uint32_t j = 0; j < desc->colorCount; j++) {
+ subpass->resolve_attachments[j]
+ = desc->resolveAttachments[j].attachment;
+ }
+ }
+
+ subpass->depth_stencil_attachment = desc->depthStencilAttachment.attachment;
+ }
+
+ *pRenderPass = anv_render_pass_to_handle(pass);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyRenderPass(
+ VkDevice _device,
+ VkRenderPass _pass)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_render_pass, pass, _pass);
+
+ anv_device_free(device, pass->attachments);
+
+ for (uint32_t i = 0; i < pass->subpass_count; i++) {
+ /* In VkSubpassCreateInfo, each of the attachment arrays may be null.
+ * Don't free the null arrays.
+ */
+ struct anv_subpass *subpass = &pass->subpasses[i];
+
+ anv_device_free(device, subpass->input_attachments);
+ anv_device_free(device, subpass->color_attachments);
+ anv_device_free(device, subpass->resolve_attachments);
+ }
+
+ anv_device_free(device, pass);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetRenderAreaGranularity(
+ VkDevice device,
+ VkRenderPass renderPass,
+ VkExtent2D* pGranularity)
+{
+ *pGranularity = (VkExtent2D) { 1, 1 };
+
+ return VK_SUCCESS;
+}
+
+void vkCmdDbgMarkerBegin(
+ VkCmdBuffer cmdBuffer,
+ const char* pMarker)
+ __attribute__ ((visibility ("default")));
+
+void vkCmdDbgMarkerEnd(
+ VkCmdBuffer cmdBuffer)
+ __attribute__ ((visibility ("default")));
+
+void vkCmdDbgMarkerBegin(
+ VkCmdBuffer cmdBuffer,
+ const char* pMarker)
+{
+}
+
+void vkCmdDbgMarkerEnd(
+ VkCmdBuffer cmdBuffer)
+{
+}
--- /dev/null
+# coding=utf-8
+#
+# 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.
+#
+
+import fileinput, re, sys
+
+# Each function typedef in the vulkan.h header is all on one line and matches
+# this regepx. We hope that won't change.
+
+p = re.compile('typedef ([^ ]*) *\(VKAPI \*PFN_vk([^(]*)\)(.*);')
+
+entrypoints = []
+
+# We generate a static hash table for entry point lookup
+# (vkGetProcAddress). We use a linear congruential generator for our hash
+# function and a power-of-two size table. The prime numbers are determined
+# experimentally.
+
+none = 0xffff
+hash_size = 256
+u32_mask = 2**32 - 1
+hash_mask = hash_size - 1
+
+prime_factor = 5024183
+prime_step = 19
+
+def hash(name):
+ h = 0;
+ for c in name:
+ h = (h * prime_factor + ord(c)) & u32_mask
+
+ return h
+
+opt_header = False
+opt_code = False
+
+if (sys.argv[1] == "header"):
+ opt_header = True
+ sys.argv.pop()
+elif (sys.argv[1] == "code"):
+ opt_code = True
+ sys.argv.pop()
+
+# Parse the entry points in the header
+
+i = 0
+for line in fileinput.input():
+ m = p.match(line)
+ if (m):
+ if m.group(2) == 'VoidFunction':
+ continue
+ fullname = "vk" + m.group(2)
+ h = hash(fullname)
+ entrypoints.append((m.group(1), m.group(2), m.group(3), i, h))
+ i = i + 1
+
+# For outputting entrypoints.h we generate a anv_EntryPoint() prototype
+# per entry point.
+
+if opt_header:
+ for type, name, args, num, h in entrypoints:
+ print "%s anv_%s%s;" % (type, name, args)
+ print "%s anv_validate_%s%s;" % (type, name, args)
+ exit()
+
+
+
+print """/*
+ * 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.
+ */
+
+/* DO NOT EDIT! This is a generated file. */
+
+#include "anv_private.h"
+
+struct anv_entrypoint {
+ uint32_t name;
+ uint32_t hash;
+ void *function;
+ void *validate;
+};
+
+/* We use a big string constant to avoid lots of reloctions from the entry
+ * point table to lots of little strings. The entries in the entry point table
+ * store the index into this big string.
+ */
+
+static const char strings[] ="""
+
+offsets = []
+i = 0;
+for type, name, args, num, h in entrypoints:
+ print " \"vk%s\\0\"" % name
+ offsets.append(i)
+ i += 2 + len(name) + 1
+print """ ;
+
+/* Weak aliases for all potential validate functions. These will resolve to
+ * NULL if they're not defined, which lets the resolve_entrypoint() function
+ * either pick a validate wrapper if available or just plug in the actual
+ * entry point.
+ */
+"""
+
+for type, name, args, num, h in entrypoints:
+ print "%s anv_validate_%s%s __attribute__ ((weak));" % (type, name, args)
+
+# Now generate the table of all entry points and their validation functions
+
+print "\nstatic const struct anv_entrypoint entrypoints[] = {"
+for type, name, args, num, h in entrypoints:
+ print " { %5d, 0x%08x, anv_%s, anv_validate_%s }," % (offsets[num], h, name, name)
+print "};\n"
+
+print """
+#ifdef DEBUG
+static bool enable_validate = true;
+#else
+static bool enable_validate = false;
+#endif
+
+/* We can't use symbols that need resolving (like, oh, getenv) in the resolve
+ * function. This means that we have to determine whether or not to use the
+ * validation layer sometime before that. The constructor function attribute asks
+ * the dynamic linker to invoke determine_validate() at dlopen() time which
+ * works.
+ */
+static void __attribute__ ((constructor))
+determine_validate(void)
+{
+ const char *s = getenv("ANV_VALIDATE");
+
+ if (s)
+ enable_validate = atoi(s);
+}
+
+static void * __attribute__ ((noinline))
+resolve_entrypoint(uint32_t index)
+{
+ if (enable_validate && entrypoints[index].validate)
+ return entrypoints[index].validate;
+
+ return entrypoints[index].function;
+}
+"""
+
+# Now output ifuncs and their resolve helpers for all entry points. The
+# resolve helper calls resolve_entrypoint() with the entry point index, which
+# lets the resolver look it up in the table.
+
+for type, name, args, num, h in entrypoints:
+ print "static void *resolve_%s(void) { return resolve_entrypoint(%d); }" % (name, num)
+ print "%s vk%s%s\n __attribute__ ((ifunc (\"resolve_%s\"), visibility (\"default\")));\n" % (type, name, args, name)
+
+
+# Now generate the hash table used for entry point look up. This is a
+# uint16_t table of entry point indices. We use 0xffff to indicate an entry
+# in the hash table is empty.
+
+map = [none for f in xrange(hash_size)]
+collisions = [0 for f in xrange(10)]
+for type, name, args, num, h in entrypoints:
+ level = 0
+ while map[h & hash_mask] != none:
+ h = h + prime_step
+ level = level + 1
+ if level > 9:
+ collisions[9] += 1
+ else:
+ collisions[level] += 1
+ map[h & hash_mask] = num
+
+print "/* Hash table stats:"
+print " * size %d entries" % hash_size
+print " * collisions entries"
+for i in xrange(10):
+ if (i == 9):
+ plus = "+"
+ else:
+ plus = " "
+
+ print " * %2d%s %4d" % (i, plus, collisions[i])
+print " */\n"
+
+print "#define none 0x%04x\n" % none
+
+print "static const uint16_t map[] = {"
+for i in xrange(0, hash_size, 8):
+ print " ",
+ for j in xrange(i, i + 8):
+ if map[j] & 0xffff == 0xffff:
+ print " none,",
+ else:
+ print "0x%04x," % (map[j] & 0xffff),
+ print
+
+print "};"
+
+# Finally we generate the hash table lookup function. The hash function and
+# linear probing algorithm matches the hash table generated above.
+
+print """
+void *
+anv_lookup_entrypoint(const char *name)
+{
+ static const uint32_t prime_factor = %d;
+ static const uint32_t prime_step = %d;
+ const struct anv_entrypoint *e;
+ uint32_t hash, h, i;
+ const char *p;
+
+ hash = 0;
+ for (p = name; *p; p++)
+ hash = hash * prime_factor + *p;
+
+ h = hash;
+ do {
+ i = map[h & %d];
+ if (i == none)
+ return NULL;
+ e = &entrypoints[i];
+ h += prime_step;
+ } while (e->hash != hash);
+
+ if (strcmp(name, strings + e->name) != 0)
+ return NULL;
+
+ return resolve_entrypoint(i);
+}
+""" % (prime_factor, prime_step, hash_mask)
--- /dev/null
+/*
+ * 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 "anv_private.h"
+
+#define UNSUPPORTED 0xffff
+
+#define fmt(__vk_fmt, ...) \
+ [__vk_fmt] = { .name = #__vk_fmt, __VA_ARGS__ }
+
+static const struct anv_format anv_formats[] = {
+ fmt(VK_FORMAT_UNDEFINED, RAW, .cpp = 1, .num_channels = 1),
+ fmt(VK_FORMAT_R4G4_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_R4G4_USCALED, UNSUPPORTED),
+ fmt(VK_FORMAT_R4G4B4A4_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_R4G4B4A4_USCALED, UNSUPPORTED),
+ fmt(VK_FORMAT_R5G6B5_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_R5G6B5_USCALED, UNSUPPORTED),
+ fmt(VK_FORMAT_R5G5B5A1_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_R5G5B5A1_USCALED, UNSUPPORTED),
+ fmt(VK_FORMAT_R8_UNORM, R8_UNORM, .cpp = 1, .num_channels = 1),
+ fmt(VK_FORMAT_R8_SNORM, R8_SNORM, .cpp = 1, .num_channels = 1,),
+ fmt(VK_FORMAT_R8_USCALED, R8_USCALED, .cpp = 1, .num_channels = 1),
+ fmt(VK_FORMAT_R8_SSCALED, R8_SSCALED, .cpp = 1, .num_channels = 1),
+ fmt(VK_FORMAT_R8_UINT, R8_UINT, .cpp = 1, .num_channels = 1),
+ fmt(VK_FORMAT_R8_SINT, R8_SINT, .cpp = 1, .num_channels = 1),
+ fmt(VK_FORMAT_R8_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_R8G8_UNORM, R8G8_UNORM, .cpp = 2, .num_channels = 2),
+ fmt(VK_FORMAT_R8G8_SNORM, R8G8_SNORM, .cpp = 2, .num_channels = 2),
+ fmt(VK_FORMAT_R8G8_USCALED, R8G8_USCALED, .cpp = 2, .num_channels = 2),
+ fmt(VK_FORMAT_R8G8_SSCALED, R8G8_SSCALED, .cpp = 2, .num_channels = 2),
+ fmt(VK_FORMAT_R8G8_UINT, R8G8_UINT, .cpp = 2, .num_channels = 2),
+ fmt(VK_FORMAT_R8G8_SINT, R8G8_SINT, .cpp = 2, .num_channels = 2),
+ fmt(VK_FORMAT_R8G8_SRGB, UNSUPPORTED), /* L8A8_UNORM_SRGB */
+ fmt(VK_FORMAT_R8G8B8_UNORM, R8G8B8X8_UNORM, .cpp = 3, .num_channels = 3),
+ fmt(VK_FORMAT_R8G8B8_SNORM, R8G8B8_SNORM, .cpp = 3, .num_channels = 3),
+ fmt(VK_FORMAT_R8G8B8_USCALED, R8G8B8_USCALED, .cpp = 3, .num_channels = 3),
+ fmt(VK_FORMAT_R8G8B8_SSCALED, R8G8B8_SSCALED, .cpp = 3, .num_channels = 3),
+ fmt(VK_FORMAT_R8G8B8_UINT, R8G8B8_UINT, .cpp = 3, .num_channels = 3),
+ fmt(VK_FORMAT_R8G8B8_SINT, R8G8B8_SINT, .cpp = 3, .num_channels = 3),
+ fmt(VK_FORMAT_R8G8B8_SRGB, UNSUPPORTED), /* B8G8R8A8_UNORM_SRGB */
+ fmt(VK_FORMAT_R8G8B8A8_UNORM, R8G8B8A8_UNORM, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R8G8B8A8_SNORM, R8G8B8A8_SNORM, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R8G8B8A8_USCALED, R8G8B8A8_USCALED, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R8G8B8A8_SSCALED, R8G8B8A8_SSCALED, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R8G8B8A8_UINT, R8G8B8A8_UINT, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R8G8B8A8_SINT, R8G8B8A8_SINT, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R8G8B8A8_SRGB, R8G8B8A8_UNORM_SRGB, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R10G10B10A2_UNORM, R10G10B10A2_UNORM, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R10G10B10A2_SNORM, R10G10B10A2_SNORM, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R10G10B10A2_USCALED, R10G10B10A2_USCALED, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R10G10B10A2_SSCALED, R10G10B10A2_SSCALED, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R10G10B10A2_UINT, R10G10B10A2_UINT, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R10G10B10A2_SINT, R10G10B10A2_SINT, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_R16_UNORM, R16_UNORM, .cpp = 2, .num_channels = 1),
+ fmt(VK_FORMAT_R16_SNORM, R16_SNORM, .cpp = 2, .num_channels = 1),
+ fmt(VK_FORMAT_R16_USCALED, R16_USCALED, .cpp = 2, .num_channels = 1),
+ fmt(VK_FORMAT_R16_SSCALED, R16_SSCALED, .cpp = 2, .num_channels = 1),
+ fmt(VK_FORMAT_R16_UINT, R16_UINT, .cpp = 2, .num_channels = 1),
+ fmt(VK_FORMAT_R16_SINT, R16_SINT, .cpp = 2, .num_channels = 1),
+ fmt(VK_FORMAT_R16_SFLOAT, R16_FLOAT, .cpp = 2, .num_channels = 1),
+ fmt(VK_FORMAT_R16G16_UNORM, R16G16_UNORM, .cpp = 4, .num_channels = 2),
+ fmt(VK_FORMAT_R16G16_SNORM, R16G16_SNORM, .cpp = 4, .num_channels = 2),
+ fmt(VK_FORMAT_R16G16_USCALED, R16G16_USCALED, .cpp = 4, .num_channels = 2),
+ fmt(VK_FORMAT_R16G16_SSCALED, R16G16_SSCALED, .cpp = 4, .num_channels = 2),
+ fmt(VK_FORMAT_R16G16_UINT, R16G16_UINT, .cpp = 4, .num_channels = 2),
+ fmt(VK_FORMAT_R16G16_SINT, R16G16_SINT, .cpp = 4, .num_channels = 2),
+ fmt(VK_FORMAT_R16G16_SFLOAT, R16G16_FLOAT, .cpp = 4, .num_channels = 2),
+ fmt(VK_FORMAT_R16G16B16_UNORM, R16G16B16_UNORM, .cpp = 6, .num_channels = 3),
+ fmt(VK_FORMAT_R16G16B16_SNORM, R16G16B16_SNORM, .cpp = 6, .num_channels = 3),
+ fmt(VK_FORMAT_R16G16B16_USCALED, R16G16B16_USCALED, .cpp = 6, .num_channels = 3),
+ fmt(VK_FORMAT_R16G16B16_SSCALED, R16G16B16_SSCALED, .cpp = 6, .num_channels = 3),
+ fmt(VK_FORMAT_R16G16B16_UINT, R16G16B16_UINT, .cpp = 6, .num_channels = 3),
+ fmt(VK_FORMAT_R16G16B16_SINT, R16G16B16_SINT, .cpp = 6, .num_channels = 3),
+ fmt(VK_FORMAT_R16G16B16_SFLOAT, R16G16B16_FLOAT, .cpp = 6, .num_channels = 3),
+ fmt(VK_FORMAT_R16G16B16A16_UNORM, R16G16B16A16_UNORM, .cpp = 8, .num_channels = 4),
+ fmt(VK_FORMAT_R16G16B16A16_SNORM, R16G16B16A16_SNORM, .cpp = 8, .num_channels = 4),
+ fmt(VK_FORMAT_R16G16B16A16_USCALED, R16G16B16A16_USCALED, .cpp = 8, .num_channels = 4),
+ fmt(VK_FORMAT_R16G16B16A16_SSCALED, R16G16B16A16_SSCALED, .cpp = 8, .num_channels = 4),
+ fmt(VK_FORMAT_R16G16B16A16_UINT, R16G16B16A16_UINT, .cpp = 8, .num_channels = 4),
+ fmt(VK_FORMAT_R16G16B16A16_SINT, R16G16B16A16_SINT, .cpp = 8, .num_channels = 4),
+ fmt(VK_FORMAT_R16G16B16A16_SFLOAT, R16G16B16A16_FLOAT, .cpp = 8, .num_channels = 4),
+ fmt(VK_FORMAT_R32_UINT, R32_UINT, .cpp = 4, .num_channels = 1,),
+ fmt(VK_FORMAT_R32_SINT, R32_SINT, .cpp = 4, .num_channels = 1,),
+ fmt(VK_FORMAT_R32_SFLOAT, R32_FLOAT, .cpp = 4, .num_channels = 1,),
+ fmt(VK_FORMAT_R32G32_UINT, R32G32_UINT, .cpp = 8, .num_channels = 2,),
+ fmt(VK_FORMAT_R32G32_SINT, R32G32_SINT, .cpp = 8, .num_channels = 2,),
+ fmt(VK_FORMAT_R32G32_SFLOAT, R32G32_FLOAT, .cpp = 8, .num_channels = 2,),
+ fmt(VK_FORMAT_R32G32B32_UINT, R32G32B32_UINT, .cpp = 12, .num_channels = 3,),
+ fmt(VK_FORMAT_R32G32B32_SINT, R32G32B32_SINT, .cpp = 12, .num_channels = 3,),
+ fmt(VK_FORMAT_R32G32B32_SFLOAT, R32G32B32_FLOAT, .cpp = 12, .num_channels = 3,),
+ fmt(VK_FORMAT_R32G32B32A32_UINT, R32G32B32A32_UINT, .cpp = 16, .num_channels = 4,),
+ fmt(VK_FORMAT_R32G32B32A32_SINT, R32G32B32A32_SINT, .cpp = 16, .num_channels = 4,),
+ fmt(VK_FORMAT_R32G32B32A32_SFLOAT, R32G32B32A32_FLOAT, .cpp = 16, .num_channels = 4,),
+ fmt(VK_FORMAT_R64_SFLOAT, R64_FLOAT, .cpp = 8, .num_channels = 1),
+ fmt(VK_FORMAT_R64G64_SFLOAT, R64G64_FLOAT, .cpp = 16, .num_channels = 2),
+ fmt(VK_FORMAT_R64G64B64_SFLOAT, R64G64B64_FLOAT, .cpp = 24, .num_channels = 3),
+ fmt(VK_FORMAT_R64G64B64A64_SFLOAT, R64G64B64A64_FLOAT, .cpp = 32, .num_channels = 4),
+ fmt(VK_FORMAT_R11G11B10_UFLOAT, R11G11B10_FLOAT, .cpp = 4, .num_channels = 3),
+ fmt(VK_FORMAT_R9G9B9E5_UFLOAT, R9G9B9E5_SHAREDEXP, .cpp = 4, .num_channels = 3),
+
+ fmt(VK_FORMAT_D16_UNORM, R16_UNORM, .cpp = 2, .num_channels = 1, .depth_format = D16_UNORM),
+ fmt(VK_FORMAT_D24_UNORM, R24_UNORM_X8_TYPELESS, .cpp = 4, .num_channels = 1, .depth_format = D24_UNORM_X8_UINT),
+ fmt(VK_FORMAT_D32_SFLOAT, R32_FLOAT, .cpp = 4, .num_channels = 1, .depth_format = D32_FLOAT),
+ fmt(VK_FORMAT_S8_UINT, R8_UINT, .cpp = 1, .num_channels = 1, .has_stencil = true),
+ fmt(VK_FORMAT_D16_UNORM_S8_UINT, R16_UNORM, .cpp = 2, .num_channels = 2, .depth_format = D16_UNORM, .has_stencil = true),
+ fmt(VK_FORMAT_D24_UNORM_S8_UINT, R24_UNORM_X8_TYPELESS, .cpp = 4, .num_channels = 2, .depth_format = D24_UNORM_X8_UINT, .has_stencil = true),
+ fmt(VK_FORMAT_D32_SFLOAT_S8_UINT, R32_FLOAT, .cpp = 4, .num_channels = 2, .depth_format = D32_FLOAT, .has_stencil = true),
+
+ fmt(VK_FORMAT_BC1_RGB_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_BC1_RGB_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_BC1_RGBA_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_BC1_RGBA_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_BC2_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_BC2_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_BC3_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_BC3_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_BC4_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_BC4_SNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_BC5_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_BC5_SNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_BC6H_UFLOAT, UNSUPPORTED),
+ fmt(VK_FORMAT_BC6H_SFLOAT, UNSUPPORTED),
+ fmt(VK_FORMAT_BC7_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_BC7_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ETC2_R8G8B8_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ETC2_R8G8B8_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ETC2_R8G8B8A1_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ETC2_R8G8B8A1_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ETC2_R8G8B8A8_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ETC2_R8G8B8A8_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_EAC_R11_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_EAC_R11_SNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_EAC_R11G11_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_EAC_R11G11_SNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_4x4_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_4x4_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_5x4_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_5x4_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_5x5_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_5x5_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_6x5_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_6x5_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_6x6_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_6x6_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_8x5_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_8x5_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_8x6_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_8x6_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_8x8_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_8x8_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_10x5_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_10x5_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_10x6_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_10x6_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_10x8_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_10x8_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_10x10_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_10x10_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_12x10_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_12x10_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_12x12_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_ASTC_12x12_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_B4G4R4A4_UNORM, B4G4R4A4_UNORM, .cpp = 2, .num_channels = 4),
+ fmt(VK_FORMAT_B5G5R5A1_UNORM, B5G5R5A1_UNORM, .cpp = 2, .num_channels = 4),
+ fmt(VK_FORMAT_B5G6R5_UNORM, B5G6R5_UNORM, .cpp = 2, .num_channels = 3),
+ fmt(VK_FORMAT_B5G6R5_USCALED, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8_UNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8_SNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8_USCALED, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8_SSCALED, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8_UINT, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8_SINT, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8_SRGB, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8A8_UNORM, B8G8R8A8_UNORM, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_B8G8R8A8_SNORM, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8A8_USCALED, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8A8_SSCALED, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8A8_UINT, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8A8_SINT, UNSUPPORTED),
+ fmt(VK_FORMAT_B8G8R8A8_SRGB, B8G8R8A8_UNORM_SRGB, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_B10G10R10A2_UNORM, B10G10R10A2_UNORM, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_B10G10R10A2_SNORM, B10G10R10A2_SNORM, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_B10G10R10A2_USCALED, B10G10R10A2_USCALED, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_B10G10R10A2_SSCALED, B10G10R10A2_SSCALED, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_B10G10R10A2_UINT, B10G10R10A2_UINT, .cpp = 4, .num_channels = 4),
+ fmt(VK_FORMAT_B10G10R10A2_SINT, B10G10R10A2_SINT, .cpp = 4, .num_channels = 4)
+};
+
+#undef fmt
+
+const struct anv_format *
+anv_format_for_vk_format(VkFormat format)
+{
+ return &anv_formats[format];
+}
+
+bool
+anv_is_vk_format_depth_or_stencil(VkFormat format)
+{
+ const struct anv_format *format_info =
+ anv_format_for_vk_format(format);
+
+ if (format_info->depth_format != UNSUPPORTED &&
+ format_info->depth_format != 0)
+ return true;
+
+ return format_info->has_stencil;
+}
+
+// Format capabilities
+
+struct surface_format_info {
+ bool exists;
+ int sampling;
+ int filtering;
+ int shadow_compare;
+ int chroma_key;
+ int render_target;
+ int alpha_blend;
+ int input_vb;
+ int streamed_output_vb;
+ int color_processing;
+};
+
+extern const struct surface_format_info surface_formats[];
+
+VkResult anv_validate_GetPhysicalDeviceFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat _format,
+ VkFormatProperties* pFormatProperties)
+{
+ const struct anv_format *format = anv_format_for_vk_format(_format);
+ fprintf(stderr, "vkGetFormatProperties(%s)\n", format->name);
+ return anv_GetPhysicalDeviceFormatProperties(physicalDevice, _format, pFormatProperties);
+}
+
+VkResult anv_GetPhysicalDeviceFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat _format,
+ VkFormatProperties* pFormatProperties)
+{
+ ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
+ const struct surface_format_info *info;
+ int gen;
+
+ const struct anv_format *format = anv_format_for_vk_format(_format);
+ if (format == NULL)
+ return vk_error(VK_ERROR_INVALID_VALUE);
+
+ gen = physical_device->info->gen * 10;
+ if (physical_device->info->is_haswell)
+ gen += 5;
+
+ if (format->surface_format == UNSUPPORTED)
+ goto unsupported;
+
+ info = &surface_formats[format->surface_format];
+ if (!info->exists)
+ goto unsupported;
+
+ uint32_t linear = 0, tiled = 0;
+ if (info->sampling <= gen) {
+ linear |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
+ tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
+ }
+ if (info->render_target <= gen) {
+ linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
+ tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
+ }
+ if (info->alpha_blend <= gen) {
+ linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
+ tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
+ }
+ if (info->input_vb <= gen) {
+ linear |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
+ }
+
+ pFormatProperties->linearTilingFeatures = linear;
+ pFormatProperties->optimalTilingFeatures = tiled;
+
+ return VK_SUCCESS;
+
+ unsupported:
+ pFormatProperties->linearTilingFeatures = 0;
+ pFormatProperties->optimalTilingFeatures = 0;
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetPhysicalDeviceImageFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkImageType type,
+ VkImageTiling tiling,
+ VkImageUsageFlags usage,
+ VkImageFormatProperties* pImageFormatProperties)
+{
+ /* TODO: We should do something here. Chad? */
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_GetPhysicalDeviceSparseImageFormatProperties(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkImageType type,
+ uint32_t samples,
+ VkImageUsageFlags usage,
+ VkImageTiling tiling,
+ uint32_t* pNumProperties,
+ VkSparseImageFormatProperties* pProperties)
+{
+ stub_return(VK_UNSUPPORTED);
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+#define _DEFAULT_SOURCE
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "anv_private.h"
+
+#define VG_CLEAR(s) VG(memset(&s, 0, sizeof(s)))
+
+static int
+anv_ioctl(int fd, unsigned long request, void *arg)
+{
+ int ret;
+
+ do {
+ ret = ioctl(fd, request, arg);
+ } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+
+ return ret;
+}
+
+/**
+ * Wrapper around DRM_IOCTL_I915_GEM_CREATE.
+ *
+ * Return gem handle, or 0 on failure. Gem handles are never 0.
+ */
+uint32_t
+anv_gem_create(struct anv_device *device, size_t size)
+{
+ struct drm_i915_gem_create gem_create;
+ int ret;
+
+ VG_CLEAR(gem_create);
+ gem_create.size = size;
+
+ ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
+ if (ret != 0) {
+ /* FIXME: What do we do if this fails? */
+ return 0;
+ }
+
+ return gem_create.handle;
+}
+
+void
+anv_gem_close(struct anv_device *device, int gem_handle)
+{
+ struct drm_gem_close close;
+
+ VG_CLEAR(close);
+ close.handle = gem_handle;
+ anv_ioctl(device->fd, DRM_IOCTL_GEM_CLOSE, &close);
+}
+
+/**
+ * Wrapper around DRM_IOCTL_I915_GEM_MMAP.
+ */
+void*
+anv_gem_mmap(struct anv_device *device, uint32_t gem_handle,
+ uint64_t offset, uint64_t size)
+{
+ struct drm_i915_gem_mmap gem_mmap;
+ int ret;
+
+ gem_mmap.handle = gem_handle;
+ VG_CLEAR(gem_mmap.pad);
+ gem_mmap.offset = offset;
+ gem_mmap.size = size;
+ VG_CLEAR(gem_mmap.addr_ptr);
+
+#ifdef I915_MMAP_WC
+ gem_mmap.flags = 0;
+#endif
+
+ ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_mmap);
+ if (ret != 0) {
+ /* FIXME: Is NULL the right error return? Cf MAP_INVALID */
+ return NULL;
+ }
+
+ VG(VALGRIND_MALLOCLIKE_BLOCK(gem_mmap.addr_ptr, gem_mmap.size, 0, 1));
+ return (void *)(uintptr_t) gem_mmap.addr_ptr;
+}
+
+/* This is just a wrapper around munmap, but it also notifies valgrind that
+ * this map is no longer valid. Pair this with anv_gem_mmap().
+ */
+void
+anv_gem_munmap(void *p, uint64_t size)
+{
+ VG(VALGRIND_FREELIKE_BLOCK(p, 0));
+ munmap(p, size);
+}
+
+int
+anv_gem_userptr(struct anv_device *device, void *mem, size_t size)
+{
+ struct drm_i915_gem_userptr userptr;
+ int ret;
+
+ VG_CLEAR(userptr);
+ userptr.user_ptr = (__u64)((unsigned long) mem);
+ userptr.user_size = size;
+ userptr.flags = 0;
+
+ ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_USERPTR, &userptr);
+ if (ret == -1)
+ return 0;
+
+ return userptr.handle;
+}
+
+/**
+ * On error, \a timeout_ns holds the remaining time.
+ */
+int
+anv_gem_wait(struct anv_device *device, int gem_handle, int64_t *timeout_ns)
+{
+ struct drm_i915_gem_wait wait;
+ int ret;
+
+ VG_CLEAR(wait);
+ wait.bo_handle = gem_handle;
+ wait.timeout_ns = *timeout_ns;
+ wait.flags = 0;
+
+ ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_WAIT, &wait);
+ *timeout_ns = wait.timeout_ns;
+
+ return ret;
+}
+
+int
+anv_gem_execbuffer(struct anv_device *device,
+ struct drm_i915_gem_execbuffer2 *execbuf)
+{
+ return anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
+}
+
+int
+anv_gem_set_tiling(struct anv_device *device,
+ int gem_handle, uint32_t stride, uint32_t tiling)
+{
+ struct drm_i915_gem_set_tiling set_tiling;
+ int ret;
+
+ /* set_tiling overwrites the input on the error path, so we have to open
+ * code anv_ioctl.
+ */
+
+ do {
+ VG_CLEAR(set_tiling);
+ set_tiling.handle = gem_handle;
+ set_tiling.tiling_mode = I915_TILING_X;
+ set_tiling.stride = stride;
+
+ ret = ioctl(device->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
+ } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+
+ return ret;
+}
+
+int
+anv_gem_get_param(int fd, uint32_t param)
+{
+ drm_i915_getparam_t gp;
+ int ret, tmp;
+
+ VG_CLEAR(gp);
+ gp.param = param;
+ gp.value = &tmp;
+ ret = anv_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+ if (ret == 0)
+ return tmp;
+
+ return 0;
+}
+
+int
+anv_gem_create_context(struct anv_device *device)
+{
+ struct drm_i915_gem_context_create create;
+ int ret;
+
+ VG_CLEAR(create);
+
+ ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create);
+ if (ret == -1)
+ return -1;
+
+ return create.ctx_id;
+}
+
+int
+anv_gem_destroy_context(struct anv_device *device, int context)
+{
+ struct drm_i915_gem_context_destroy destroy;
+
+ VG_CLEAR(destroy);
+ destroy.ctx_id = context;
+
+ return anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy);
+}
+
+int
+anv_gem_get_aperture(struct anv_physical_device *physical_dev, uint64_t *size)
+{
+ struct drm_i915_gem_get_aperture aperture;
+ int ret;
+
+ VG_CLEAR(aperture);
+ ret = anv_ioctl(physical_dev->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
+ if (ret == -1)
+ return -1;
+
+ *size = aperture.aper_available_size;
+
+ return 0;
+}
+
+int
+anv_gem_handle_to_fd(struct anv_device *device, int gem_handle)
+{
+ struct drm_prime_handle args;
+ int ret;
+
+ VG_CLEAR(args);
+ args.handle = gem_handle;
+ args.flags = DRM_CLOEXEC;
+
+ ret = anv_ioctl(device->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
+ if (ret == -1)
+ return -1;
+
+ return args.fd;
+}
+
+int
+anv_gem_fd_to_handle(struct anv_device *device, int fd)
+{
+ struct drm_prime_handle args;
+ int ret;
+
+ VG_CLEAR(args);
+ args.fd = fd;
+
+ ret = anv_ioctl(device->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
+ if (ret == -1)
+ return 0;
+
+ return args.handle;
+}
--- /dev/null
+/*
+ * 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 <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "anv_private.h"
+
+struct anv_image_view_info {
+ uint8_t surface_type; /**< RENDER_SURFACE_STATE.SurfaceType */
+ bool is_array:1; /**< RENDER_SURFACE_STATE.SurfaceArray */
+ bool is_cube:1; /**< RENDER_SURFACE_STATE.CubeFaceEnable* */
+};
+
+static const uint8_t anv_halign[] = {
+ [4] = HALIGN4,
+ [8] = HALIGN8,
+ [16] = HALIGN16,
+};
+
+static const uint8_t anv_valign[] = {
+ [4] = VALIGN4,
+ [8] = VALIGN8,
+ [16] = VALIGN16,
+};
+
+static const uint8_t anv_surf_type_from_image_type[] = {
+ [VK_IMAGE_TYPE_1D] = SURFTYPE_1D,
+ [VK_IMAGE_TYPE_2D] = SURFTYPE_2D,
+ [VK_IMAGE_TYPE_3D] = SURFTYPE_3D,
+
+};
+
+static const struct anv_image_view_info
+anv_image_view_info_table[] = {
+ #define INFO(s, ...) { .surface_type = s, __VA_ARGS__ }
+ [VK_IMAGE_VIEW_TYPE_1D] = INFO(SURFTYPE_1D),
+ [VK_IMAGE_VIEW_TYPE_2D] = INFO(SURFTYPE_2D),
+ [VK_IMAGE_VIEW_TYPE_3D] = INFO(SURFTYPE_3D),
+ [VK_IMAGE_VIEW_TYPE_CUBE] = INFO(SURFTYPE_CUBE, .is_cube = 1),
+ [VK_IMAGE_VIEW_TYPE_1D_ARRAY] = INFO(SURFTYPE_1D, .is_array = 1),
+ [VK_IMAGE_VIEW_TYPE_2D_ARRAY] = INFO(SURFTYPE_2D, .is_array = 1),
+ [VK_IMAGE_VIEW_TYPE_CUBE_ARRAY] = INFO(SURFTYPE_CUBE, .is_array = 1, .is_cube = 1),
+ #undef INFO
+};
+
+static const struct anv_surf_type_limits {
+ int32_t width;
+ int32_t height;
+ int32_t depth;
+} anv_surf_type_limits[] = {
+ [SURFTYPE_1D] = {16384, 0, 2048},
+ [SURFTYPE_2D] = {16384, 16384, 2048},
+ [SURFTYPE_3D] = {2048, 2048, 2048},
+ [SURFTYPE_CUBE] = {16384, 16384, 340},
+ [SURFTYPE_BUFFER] = {128, 16384, 64},
+ [SURFTYPE_STRBUF] = {128, 16384, 64},
+};
+
+static const struct anv_tile_info {
+ uint32_t width;
+ uint32_t height;
+
+ /**
+ * Alignment for RENDER_SURFACE_STATE.SurfaceBaseAddress.
+ *
+ * To simplify calculations, the alignments defined in the table are
+ * sometimes larger than required. For example, Skylake requires that X and
+ * Y tiled buffers be aligned to 4K, but Broadwell permits smaller
+ * alignment. We choose 4K to accomodate both chipsets. The alignment of
+ * a linear buffer depends on its element type and usage. Linear depth
+ * buffers have the largest alignment, 64B, so we choose that for all linear
+ * buffers.
+ */
+ uint32_t surface_alignment;
+} anv_tile_info_table[] = {
+ [LINEAR] = { 1, 1, 64 },
+ [XMAJOR] = { 512, 8, 4096 },
+ [YMAJOR] = { 128, 32, 4096 },
+ [WMAJOR] = { 128, 32, 4096 },
+};
+
+static uint32_t
+anv_image_choose_tile_mode(const struct anv_image_create_info *anv_info)
+{
+ if (anv_info->force_tile_mode)
+ return anv_info->tile_mode;
+
+ if (anv_info->vk_info->format == VK_FORMAT_S8_UINT)
+ return WMAJOR;
+
+ switch (anv_info->vk_info->tiling) {
+ case VK_IMAGE_TILING_LINEAR:
+ return LINEAR;
+ case VK_IMAGE_TILING_OPTIMAL:
+ return YMAJOR;
+ default:
+ assert(!"bad VKImageTiling");
+ return LINEAR;
+ }
+}
+
+static VkResult
+anv_image_make_surface(const struct anv_image_create_info *create_info,
+ uint64_t *inout_image_size,
+ uint32_t *inout_image_alignment,
+ struct anv_surface *out_surface)
+{
+ /* See RENDER_SURFACE_STATE.SurfaceQPitch */
+ static const uint16_t min_qpitch UNUSED = 0x4;
+ static const uint16_t max_qpitch UNUSED = 0x1ffc;
+
+ const VkExtent3D *restrict extent = &create_info->vk_info->extent;
+ const uint32_t levels = create_info->vk_info->mipLevels;
+ const uint32_t array_size = create_info->vk_info->arraySize;
+
+ const uint8_t tile_mode = anv_image_choose_tile_mode(create_info);
+
+ const struct anv_tile_info *tile_info =
+ &anv_tile_info_table[tile_mode];
+
+ const struct anv_format *format_info =
+ anv_format_for_vk_format(create_info->vk_info->format);
+
+ const uint32_t i = 4; /* FINISHME: Stop hardcoding subimage alignment */
+ const uint32_t j = 4; /* FINISHME: Stop hardcoding subimage alignment */
+ const uint32_t w0 = align_u32(extent->width, i);
+ const uint32_t h0 = align_u32(extent->height, j);
+
+ uint16_t qpitch;
+ uint32_t mt_width;
+ uint32_t mt_height;
+
+ if (levels == 1 && array_size == 1) {
+ qpitch = min_qpitch;
+ mt_width = w0;
+ mt_height = h0;
+ } else {
+ uint32_t w1 = align_u32(anv_minify(extent->width, 1), i);
+ uint32_t h1 = align_u32(anv_minify(extent->height, 1), j);
+ uint32_t w2 = align_u32(anv_minify(extent->width, 2), i);
+
+ qpitch = h0 + h1 + 11 * j;
+ mt_width = MAX(w0, w1 + w2);
+ mt_height = array_size * qpitch;
+ }
+
+ assert(qpitch >= min_qpitch);
+ if (qpitch > max_qpitch) {
+ anv_loge("image qpitch > 0x%x\n", max_qpitch);
+ return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
+ }
+
+ /* From the Broadwell PRM, RENDER_SURFACE_STATE.SurfaceQpitch:
+ *
+ * This field must be set an integer multiple of the Surface Vertical
+ * Alignment.
+ */
+ assert(anv_is_aligned(qpitch, j));
+
+ const uint32_t stride = align_u32(mt_width * format_info->cpp,
+ tile_info->width);
+ const uint32_t size = stride * align_u32(mt_height, tile_info->height);
+ const uint32_t offset = align_u32(*inout_image_size,
+ tile_info->surface_alignment);
+
+ *inout_image_size = offset + size;
+ *inout_image_alignment = MAX(*inout_image_alignment,
+ tile_info->surface_alignment);
+
+ *out_surface = (struct anv_surface) {
+ .offset = offset,
+ .stride = stride,
+ .tile_mode = tile_mode,
+ .qpitch = qpitch,
+ .h_align = i,
+ .v_align = j,
+ };
+
+ return VK_SUCCESS;
+}
+
+VkResult
+anv_image_create(VkDevice _device,
+ const struct anv_image_create_info *create_info,
+ VkImage *pImage)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
+ const VkExtent3D *restrict extent = &pCreateInfo->extent;
+ struct anv_image *image = NULL;
+ VkResult r;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
+
+ /* XXX: We don't handle any of these */
+ anv_assert(pCreateInfo->imageType == VK_IMAGE_TYPE_2D);
+ anv_assert(pCreateInfo->mipLevels > 0);
+ anv_assert(pCreateInfo->arraySize > 0);
+ anv_assert(pCreateInfo->samples == 1);
+ anv_assert(pCreateInfo->extent.width > 0);
+ anv_assert(pCreateInfo->extent.height > 0);
+ anv_assert(pCreateInfo->extent.depth > 0);
+
+ /* TODO(chadv): How should we validate inputs? */
+ const uint8_t surf_type =
+ anv_surf_type_from_image_type[pCreateInfo->imageType];
+
+ const struct anv_surf_type_limits *limits =
+ &anv_surf_type_limits[surf_type];
+
+ if (extent->width > limits->width ||
+ extent->height > limits->height ||
+ extent->depth > limits->depth) {
+ /* TODO(chadv): What is the correct error? */
+ anv_loge("image extent is too large");
+ return vk_error(VK_ERROR_INVALID_MEMORY_SIZE);
+ }
+
+ const struct anv_format *format_info =
+ anv_format_for_vk_format(pCreateInfo->format);
+
+ image = anv_device_alloc(device, sizeof(*image), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (!image)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ memset(image, 0, sizeof(*image));
+ image->type = pCreateInfo->imageType;
+ image->extent = pCreateInfo->extent;
+ image->format = pCreateInfo->format;
+ image->levels = pCreateInfo->mipLevels;
+ image->array_size = pCreateInfo->arraySize;
+ image->surf_type = surf_type;
+
+ if (likely(!format_info->has_stencil || format_info->depth_format)) {
+ /* The image's primary surface is a color or depth surface. */
+ r = anv_image_make_surface(create_info, &image->size, &image->alignment,
+ &image->primary_surface);
+ if (r != VK_SUCCESS)
+ goto fail;
+ }
+
+ if (format_info->has_stencil) {
+ /* From the GPU's perspective, the depth buffer and stencil buffer are
+ * separate buffers. From Vulkan's perspective, though, depth and
+ * stencil reside in the same image. To satisfy Vulkan and the GPU, we
+ * place the depth and stencil buffers in the same bo.
+ */
+ VkImageCreateInfo stencil_info = *pCreateInfo;
+ stencil_info.format = VK_FORMAT_S8_UINT;
+
+ r = anv_image_make_surface(
+ &(struct anv_image_create_info) {
+ .vk_info = &stencil_info,
+ },
+ &image->size, &image->alignment, &image->stencil_surface);
+
+ if (r != VK_SUCCESS)
+ goto fail;
+ }
+
+ *pImage = anv_image_to_handle(image);
+
+ return VK_SUCCESS;
+
+fail:
+ if (image)
+ anv_device_free(device, image);
+
+ return r;
+}
+
+VkResult
+anv_CreateImage(VkDevice device,
+ const VkImageCreateInfo *pCreateInfo,
+ VkImage *pImage)
+{
+ return anv_image_create(device,
+ &(struct anv_image_create_info) {
+ .vk_info = pCreateInfo,
+ },
+ pImage);
+}
+
+VkResult
+anv_DestroyImage(VkDevice _device, VkImage _image)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+
+ anv_device_free(device, anv_image_from_handle(_image));
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetImageSubresourceLayout(
+ VkDevice device,
+ VkImage image,
+ const VkImageSubresource* pSubresource,
+ VkSubresourceLayout* pLayout)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+void
+anv_surface_view_fini(struct anv_device *device,
+ struct anv_surface_view *view)
+{
+ anv_state_pool_free(&device->surface_state_pool, view->surface_state);
+}
+
+void
+anv_image_view_init(struct anv_image_view *iview,
+ struct anv_device *device,
+ const VkImageViewCreateInfo* pCreateInfo,
+ struct anv_cmd_buffer *cmd_buffer)
+{
+ ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
+
+ const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
+ struct anv_surface_view *view = &iview->view;
+ struct anv_surface *surface;
+
+ const struct anv_format *format_info =
+ anv_format_for_vk_format(pCreateInfo->format);
+
+ const struct anv_image_view_info *view_type_info
+ = &anv_image_view_info_table[pCreateInfo->viewType];
+
+ if (pCreateInfo->viewType != VK_IMAGE_VIEW_TYPE_2D)
+ anv_finishme("non-2D image views");
+
+ switch (pCreateInfo->subresourceRange.aspect) {
+ case VK_IMAGE_ASPECT_STENCIL:
+ anv_finishme("stencil image views");
+ abort();
+ break;
+ case VK_IMAGE_ASPECT_DEPTH:
+ case VK_IMAGE_ASPECT_COLOR:
+ view->offset = image->offset;
+ surface = &image->primary_surface;
+ break;
+ default:
+ unreachable("");
+ break;
+ }
+
+ view->bo = image->bo;
+ view->offset = image->offset + surface->offset;
+ view->format = pCreateInfo->format;
+
+ iview->extent = (VkExtent3D) {
+ .width = anv_minify(image->extent.width, range->baseMipLevel),
+ .height = anv_minify(image->extent.height, range->baseMipLevel),
+ .depth = anv_minify(image->extent.depth, range->baseMipLevel),
+ };
+
+ uint32_t depth = 1;
+ if (range->arraySize > 1) {
+ depth = range->arraySize;
+ } else if (image->extent.depth > 1) {
+ depth = image->extent.depth;
+ }
+
+ static const uint32_t vk_to_gen_swizzle[] = {
+ [VK_CHANNEL_SWIZZLE_ZERO] = SCS_ZERO,
+ [VK_CHANNEL_SWIZZLE_ONE] = SCS_ONE,
+ [VK_CHANNEL_SWIZZLE_R] = SCS_RED,
+ [VK_CHANNEL_SWIZZLE_G] = SCS_GREEN,
+ [VK_CHANNEL_SWIZZLE_B] = SCS_BLUE,
+ [VK_CHANNEL_SWIZZLE_A] = SCS_ALPHA
+ };
+
+ struct GEN8_RENDER_SURFACE_STATE surface_state = {
+ .SurfaceType = view_type_info->surface_type,
+ .SurfaceArray = image->array_size > 1,
+ .SurfaceFormat = format_info->surface_format,
+ .SurfaceVerticalAlignment = anv_valign[surface->v_align],
+ .SurfaceHorizontalAlignment = anv_halign[surface->h_align],
+ .TileMode = surface->tile_mode,
+ .VerticalLineStride = 0,
+ .VerticalLineStrideOffset = 0,
+ .SamplerL2BypassModeDisable = true,
+ .RenderCacheReadWriteMode = WriteOnlyCache,
+ .MemoryObjectControlState = GEN8_MOCS,
+
+ /* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
+ * RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
+ * both Base Mip Level fields nonzero".
+ */
+ .BaseMipLevel = 0.0,
+
+ .SurfaceQPitch = surface->qpitch >> 2,
+ .Height = image->extent.height - 1,
+ .Width = image->extent.width - 1,
+ .Depth = depth - 1,
+ .SurfacePitch = surface->stride - 1,
+ .MinimumArrayElement = range->baseArraySlice,
+ .NumberofMultisamples = MULTISAMPLECOUNT_1,
+ .XOffset = 0,
+ .YOffset = 0,
+
+ /* For sampler surfaces, the hardware interprets field MIPCount/LOD as
+ * MIPCount. The range of levels accessible by the sampler engine is
+ * [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
+ */
+ .MIPCountLOD = range->mipLevels - 1,
+ .SurfaceMinLOD = range->baseMipLevel,
+
+ .AuxiliarySurfaceMode = AUX_NONE,
+ .RedClearColor = 0,
+ .GreenClearColor = 0,
+ .BlueClearColor = 0,
+ .AlphaClearColor = 0,
+ .ShaderChannelSelectRed = vk_to_gen_swizzle[pCreateInfo->channels.r],
+ .ShaderChannelSelectGreen = vk_to_gen_swizzle[pCreateInfo->channels.g],
+ .ShaderChannelSelectBlue = vk_to_gen_swizzle[pCreateInfo->channels.b],
+ .ShaderChannelSelectAlpha = vk_to_gen_swizzle[pCreateInfo->channels.a],
+ .ResourceMinLOD = 0.0,
+ .SurfaceBaseAddress = { NULL, view->offset },
+ };
+
+ if (cmd_buffer) {
+ view->surface_state =
+ anv_state_stream_alloc(&cmd_buffer->surface_state_stream, 64, 64);
+ } else {
+ view->surface_state =
+ anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
+ }
+
+ GEN8_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &surface_state);
+}
+
+VkResult
+anv_validate_CreateImageView(VkDevice _device,
+ const VkImageViewCreateInfo *pCreateInfo,
+ VkImageView *pView)
+{
+ ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
+ const VkImageSubresourceRange *subresource;
+ const struct anv_image_view_info *view_info;
+ const struct anv_format *view_format_info;
+ const struct anv_format *image_format_info;
+
+ /* Validate structure type before dereferencing it. */
+ assert(pCreateInfo);
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
+ subresource = &pCreateInfo->subresourceRange;
+
+ /* Validate viewType is in range before using it. */
+ assert(pCreateInfo->viewType >= VK_IMAGE_VIEW_TYPE_BEGIN_RANGE);
+ assert(pCreateInfo->viewType <= VK_IMAGE_VIEW_TYPE_END_RANGE);
+ view_info = &anv_image_view_info_table[pCreateInfo->viewType];
+
+ /* Validate format is in range before using it. */
+ assert(pCreateInfo->format >= VK_FORMAT_BEGIN_RANGE);
+ assert(pCreateInfo->format <= VK_FORMAT_END_RANGE);
+ image_format_info = anv_format_for_vk_format(image->format);
+ view_format_info = anv_format_for_vk_format(pCreateInfo->format);
+
+ /* Validate channel swizzles. */
+ assert(pCreateInfo->channels.r >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
+ assert(pCreateInfo->channels.r <= VK_CHANNEL_SWIZZLE_END_RANGE);
+ assert(pCreateInfo->channels.g >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
+ assert(pCreateInfo->channels.g <= VK_CHANNEL_SWIZZLE_END_RANGE);
+ assert(pCreateInfo->channels.b >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
+ assert(pCreateInfo->channels.b <= VK_CHANNEL_SWIZZLE_END_RANGE);
+ assert(pCreateInfo->channels.a >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
+ assert(pCreateInfo->channels.a <= VK_CHANNEL_SWIZZLE_END_RANGE);
+
+ /* Validate subresource. */
+ assert(subresource->aspect >= VK_IMAGE_ASPECT_BEGIN_RANGE);
+ assert(subresource->aspect <= VK_IMAGE_ASPECT_END_RANGE);
+ assert(subresource->mipLevels > 0);
+ assert(subresource->arraySize > 0);
+ assert(subresource->baseMipLevel < image->levels);
+ assert(subresource->baseMipLevel + subresource->mipLevels <= image->levels);
+ assert(subresource->baseArraySlice < image->array_size);
+ assert(subresource->baseArraySlice + subresource->arraySize <= image->array_size);
+ assert(pView);
+
+ if (view_info->is_cube) {
+ assert(subresource->baseArraySlice % 6 == 0);
+ assert(subresource->arraySize % 6 == 0);
+ }
+
+ /* Validate format. */
+ switch (subresource->aspect) {
+ case VK_IMAGE_ASPECT_COLOR:
+ assert(!image_format_info->depth_format);
+ assert(!image_format_info->has_stencil);
+ assert(!view_format_info->depth_format);
+ assert(!view_format_info->has_stencil);
+ assert(view_format_info->cpp == image_format_info->cpp);
+ break;
+ case VK_IMAGE_ASPECT_DEPTH:
+ assert(image_format_info->depth_format);
+ assert(view_format_info->depth_format);
+ assert(view_format_info->cpp == image_format_info->cpp);
+ break;
+ case VK_IMAGE_ASPECT_STENCIL:
+ /* FINISHME: Is it legal to have an R8 view of S8? */
+ assert(image_format_info->has_stencil);
+ assert(view_format_info->has_stencil);
+ break;
+ default:
+ assert(!"bad VkImageAspect");
+ break;
+ }
+
+ return anv_CreateImageView(_device, pCreateInfo, pView);
+}
+
+VkResult
+anv_CreateImageView(VkDevice _device,
+ const VkImageViewCreateInfo *pCreateInfo,
+ VkImageView *pView)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_image_view *view;
+
+ view = anv_device_alloc(device, sizeof(*view), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (view == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ anv_image_view_init(view, device, pCreateInfo, NULL);
+
+ *pView = anv_image_view_to_handle(view);
+
+ return VK_SUCCESS;
+}
+
+VkResult
+anv_DestroyImageView(VkDevice _device, VkImageView _iview)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_image_view, iview, _iview);
+
+ anv_surface_view_fini(device, &iview->view);
+ anv_device_free(device, iview);
+
+ return VK_SUCCESS;
+}
+
+void
+anv_color_attachment_view_init(struct anv_color_attachment_view *aview,
+ struct anv_device *device,
+ const VkAttachmentViewCreateInfo* pCreateInfo,
+ struct anv_cmd_buffer *cmd_buffer)
+{
+ ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
+ struct anv_surface_view *view = &aview->view;
+ struct anv_surface *surface = &image->primary_surface;
+ const struct anv_format *format_info =
+ anv_format_for_vk_format(pCreateInfo->format);
+
+ aview->base.attachment_type = ANV_ATTACHMENT_VIEW_TYPE_COLOR;
+
+ anv_assert(pCreateInfo->arraySize > 0);
+ anv_assert(pCreateInfo->mipLevel < image->levels);
+ anv_assert(pCreateInfo->baseArraySlice + pCreateInfo->arraySize <= image->array_size);
+
+ view->bo = image->bo;
+ view->offset = image->offset + surface->offset;
+ view->format = pCreateInfo->format;
+
+ aview->base.extent = (VkExtent3D) {
+ .width = anv_minify(image->extent.width, pCreateInfo->mipLevel),
+ .height = anv_minify(image->extent.height, pCreateInfo->mipLevel),
+ .depth = anv_minify(image->extent.depth, pCreateInfo->mipLevel),
+ };
+
+ uint32_t depth = 1;
+ if (pCreateInfo->arraySize > 1) {
+ depth = pCreateInfo->arraySize;
+ } else if (image->extent.depth > 1) {
+ depth = image->extent.depth;
+ }
+
+ if (cmd_buffer) {
+ view->surface_state =
+ anv_state_stream_alloc(&cmd_buffer->surface_state_stream, 64, 64);
+ } else {
+ view->surface_state =
+ anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
+ }
+
+ struct GEN8_RENDER_SURFACE_STATE surface_state = {
+ .SurfaceType = SURFTYPE_2D,
+ .SurfaceArray = image->array_size > 1,
+ .SurfaceFormat = format_info->surface_format,
+ .SurfaceVerticalAlignment = anv_valign[surface->v_align],
+ .SurfaceHorizontalAlignment = anv_halign[surface->h_align],
+ .TileMode = surface->tile_mode,
+ .VerticalLineStride = 0,
+ .VerticalLineStrideOffset = 0,
+ .SamplerL2BypassModeDisable = true,
+ .RenderCacheReadWriteMode = WriteOnlyCache,
+ .MemoryObjectControlState = GEN8_MOCS,
+
+ /* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
+ * RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
+ * both Base Mip Level fields nonzero".
+ */
+ .BaseMipLevel = 0.0,
+
+ .SurfaceQPitch = surface->qpitch >> 2,
+ .Height = image->extent.height - 1,
+ .Width = image->extent.width - 1,
+ .Depth = depth - 1,
+ .SurfacePitch = surface->stride - 1,
+ .MinimumArrayElement = pCreateInfo->baseArraySlice,
+ .NumberofMultisamples = MULTISAMPLECOUNT_1,
+ .XOffset = 0,
+ .YOffset = 0,
+
+ /* For render target surfaces, the hardware interprets field MIPCount/LOD as
+ * LOD. The Broadwell PRM says:
+ *
+ * MIPCountLOD defines the LOD that will be rendered into.
+ * SurfaceMinLOD is ignored.
+ */
+ .SurfaceMinLOD = 0,
+ .MIPCountLOD = pCreateInfo->mipLevel,
+
+ .AuxiliarySurfaceMode = AUX_NONE,
+ .RedClearColor = 0,
+ .GreenClearColor = 0,
+ .BlueClearColor = 0,
+ .AlphaClearColor = 0,
+ .ShaderChannelSelectRed = SCS_RED,
+ .ShaderChannelSelectGreen = SCS_GREEN,
+ .ShaderChannelSelectBlue = SCS_BLUE,
+ .ShaderChannelSelectAlpha = SCS_ALPHA,
+ .ResourceMinLOD = 0.0,
+ .SurfaceBaseAddress = { NULL, view->offset },
+ };
+
+ GEN8_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &surface_state);
+}
+
+static void
+anv_depth_stencil_view_init(struct anv_depth_stencil_view *view,
+ const VkAttachmentViewCreateInfo *pCreateInfo)
+{
+ ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
+ struct anv_surface *depth_surface = &image->primary_surface;
+ struct anv_surface *stencil_surface = &image->stencil_surface;
+ const struct anv_format *format =
+ anv_format_for_vk_format(image->format);
+
+ view->base.attachment_type = ANV_ATTACHMENT_VIEW_TYPE_DEPTH_STENCIL;
+
+ /* XXX: We don't handle any of these */
+ anv_assert(pCreateInfo->mipLevel == 0);
+ anv_assert(pCreateInfo->baseArraySlice == 0);
+ anv_assert(pCreateInfo->arraySize == 1);
+
+ view->bo = image->bo;
+
+ view->depth_stride = depth_surface->stride;
+ view->depth_offset = image->offset + depth_surface->offset;
+ view->depth_format = format->depth_format;
+ view->depth_qpitch = 0; /* FINISHME: QPitch */
+
+ view->stencil_stride = stencil_surface->stride;
+ view->stencil_offset = image->offset + stencil_surface->offset;
+ view->stencil_qpitch = 0; /* FINISHME: QPitch */
+}
+
+VkResult
+anv_CreateAttachmentView(VkDevice _device,
+ const VkAttachmentViewCreateInfo *pCreateInfo,
+ VkAttachmentView *pView)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO);
+
+ if (anv_is_vk_format_depth_or_stencil(pCreateInfo->format)) {
+ struct anv_depth_stencil_view *view =
+ anv_device_alloc(device, sizeof(*view), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (view == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ anv_depth_stencil_view_init(view, pCreateInfo);
+
+ *pView = anv_attachment_view_to_handle(&view->base);
+ } else {
+ struct anv_color_attachment_view *view =
+ anv_device_alloc(device, sizeof(*view), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (view == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ anv_color_attachment_view_init(view, device, pCreateInfo, NULL);
+
+ *pView = anv_attachment_view_to_handle(&view->base);
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult
+anv_DestroyAttachmentView(VkDevice _device, VkAttachmentView _view)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_attachment_view, view, _view);
+
+ if (view->attachment_type == ANV_ATTACHMENT_VIEW_TYPE_COLOR) {
+ struct anv_color_attachment_view *aview =
+ (struct anv_color_attachment_view *)view;
+
+ anv_surface_view_fini(device, &aview->view);
+ }
+
+ anv_device_free(device, view);
+
+ return VK_SUCCESS;
+}
--- /dev/null
+/*
+ * 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 <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "anv_private.h"
+
+VkResult anv_CreateDmaBufImageINTEL(
+ VkDevice _device,
+ const VkDmaBufImageCreateInfo* pCreateInfo,
+ VkDeviceMemory* pMem,
+ VkImage* pImage)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_device_memory *mem;
+ struct anv_image *image;
+ VkResult result;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL);
+
+ mem = anv_device_alloc(device, sizeof(*mem), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (mem == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ mem->bo.gem_handle = anv_gem_fd_to_handle(device, pCreateInfo->fd);
+ if (!mem->bo.gem_handle) {
+ result = vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
+ goto fail;
+ }
+
+ mem->bo.map = NULL;
+ mem->bo.index = 0;
+ mem->bo.offset = 0;
+ mem->bo.size = pCreateInfo->strideInBytes * pCreateInfo->extent.height;
+
+ image = anv_device_alloc(device, sizeof(*image), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (image == NULL) {
+ result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+ goto fail_mem;
+ }
+
+ *image = (struct anv_image) {
+ .bo = &mem->bo,
+ .offset = 0,
+ .type = VK_IMAGE_TYPE_2D,
+ .extent = pCreateInfo->extent,
+ .size = mem->bo.size,
+
+ .primary_surface = {
+ .offset = 0,
+ .stride = pCreateInfo->strideInBytes,
+ .tile_mode = XMAJOR,
+ },
+ };
+
+ assert(image->extent.width > 0);
+ assert(image->extent.height > 0);
+ assert(image->extent.depth == 1);
+
+ *pMem = anv_device_memory_to_handle(mem);
+ *pImage = anv_image_to_handle(image);
+
+ return VK_SUCCESS;
+
+ fail_mem:
+ anv_gem_close(device, mem->bo.gem_handle);
+ fail:
+ anv_device_free(device, mem);
+
+ return result;
+}
--- /dev/null
+/*
+ * 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 <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "anv_private.h"
+#include "anv_meta_spirv.h"
+
+static void
+anv_device_init_meta_clear_state(struct anv_device *device)
+{
+ /* We don't use a vertex shader for clearing, but instead build and pass
+ * the VUEs directly to the rasterization backend.
+ */
+ VkShaderModule fsm = GLSL_VK_SHADER_MODULE(device, FRAGMENT,
+ out vec4 f_color;
+ flat in vec4 v_color;
+ void main()
+ {
+ f_color = v_color;
+ }
+ );
+
+ VkShader fs;
+ anv_CreateShader(anv_device_to_handle(device),
+ &(VkShaderCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
+ .module = fsm,
+ .pName = "main",
+ }, &fs);
+
+ /* We use instanced rendering to clear multiple render targets. We have two
+ * vertex buffers: the first vertex buffer holds per-vertex data and
+ * provides the vertices for the clear rectangle. The second one holds
+ * per-instance data, which consists of the VUE header (which selects the
+ * layer) and the color (Vulkan supports per-RT clear colors).
+ */
+ VkPipelineVertexInputStateCreateInfo vi_create_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+ .bindingCount = 2,
+ .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
+ {
+ .binding = 0,
+ .strideInBytes = 8,
+ .stepRate = VK_VERTEX_INPUT_STEP_RATE_VERTEX
+ },
+ {
+ .binding = 1,
+ .strideInBytes = 32,
+ .stepRate = VK_VERTEX_INPUT_STEP_RATE_INSTANCE
+ },
+ },
+ .attributeCount = 3,
+ .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
+ {
+ /* VUE Header */
+ .location = 0,
+ .binding = 1,
+ .format = VK_FORMAT_R32G32B32A32_UINT,
+ .offsetInBytes = 0
+ },
+ {
+ /* Position */
+ .location = 1,
+ .binding = 0,
+ .format = VK_FORMAT_R32G32_SFLOAT,
+ .offsetInBytes = 0
+ },
+ {
+ /* Color */
+ .location = 2,
+ .binding = 1,
+ .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+ .offsetInBytes = 16
+ }
+ }
+ };
+
+ anv_pipeline_create(anv_device_to_handle(device),
+ &(VkGraphicsPipelineCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+ .stageCount = 1,
+ .pStages = &(VkPipelineShaderStageCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = VK_SHADER_STAGE_FRAGMENT,
+ .shader = fs,
+ .pSpecializationInfo = NULL,
+ },
+ .pVertexInputState = &vi_create_info,
+ .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+ .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
+ .primitiveRestartEnable = false,
+ },
+ .pRasterState = &(VkPipelineRasterStateCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTER_STATE_CREATE_INFO,
+ .depthClipEnable = true,
+ .rasterizerDiscardEnable = false,
+ .fillMode = VK_FILL_MODE_SOLID,
+ .cullMode = VK_CULL_MODE_NONE,
+ .frontFace = VK_FRONT_FACE_CCW
+ },
+ .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+ .attachmentCount = 1,
+ .pAttachments = (VkPipelineColorBlendAttachmentState []) {
+ { .channelWriteMask = VK_CHANNEL_A_BIT |
+ VK_CHANNEL_R_BIT | VK_CHANNEL_G_BIT | VK_CHANNEL_B_BIT },
+ }
+ },
+ .flags = 0,
+ },
+ &(struct anv_pipeline_create_info) {
+ .use_repclear = true,
+ .disable_viewport = true,
+ .use_rectlist = true
+ },
+ &device->meta_state.clear.pipeline);
+
+ anv_DestroyShader(anv_device_to_handle(device), fs);
+}
+
+#define NUM_VB_USED 2
+struct anv_saved_state {
+ struct anv_vertex_binding old_vertex_bindings[NUM_VB_USED];
+ struct anv_descriptor_set *old_descriptor_set0;
+ struct anv_pipeline *old_pipeline;
+ VkDynamicColorBlendState cb_state;
+};
+
+static void
+anv_cmd_buffer_save(struct anv_cmd_buffer *cmd_buffer,
+ struct anv_saved_state *state)
+{
+ state->old_pipeline = cmd_buffer->state.pipeline;
+ state->old_descriptor_set0 = cmd_buffer->state.descriptors[0].set;
+ memcpy(state->old_vertex_bindings, cmd_buffer->state.vertex_bindings,
+ sizeof(state->old_vertex_bindings));
+}
+
+static void
+anv_cmd_buffer_restore(struct anv_cmd_buffer *cmd_buffer,
+ const struct anv_saved_state *state)
+{
+ cmd_buffer->state.pipeline = state->old_pipeline;
+ cmd_buffer->state.descriptors[0].set = state->old_descriptor_set0;
+ memcpy(cmd_buffer->state.vertex_bindings, state->old_vertex_bindings,
+ sizeof(state->old_vertex_bindings));
+
+ cmd_buffer->state.vb_dirty |= (1 << NUM_VB_USED) - 1;
+ cmd_buffer->state.dirty |= ANV_CMD_BUFFER_PIPELINE_DIRTY;
+ cmd_buffer->state.descriptors_dirty |= VK_SHADER_STAGE_VERTEX_BIT;
+}
+
+struct vue_header {
+ uint32_t Reserved;
+ uint32_t RTAIndex;
+ uint32_t ViewportIndex;
+ float PointWidth;
+};
+
+struct clear_instance_data {
+ struct vue_header vue_header;
+ VkClearColorValue color;
+};
+
+static void
+meta_emit_clear(struct anv_cmd_buffer *cmd_buffer,
+ int num_instances,
+ struct clear_instance_data *instance_data)
+{
+ struct anv_device *device = cmd_buffer->device;
+ struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
+ struct anv_state state;
+ uint32_t size;
+
+ const float vertex_data[] = {
+ /* Rect-list coordinates */
+ 0.0, 0.0,
+ fb->width, 0.0,
+ fb->width, fb->height,
+
+ /* Align to 16 bytes */
+ 0.0, 0.0,
+ };
+
+ size = sizeof(vertex_data) + num_instances * sizeof(*instance_data);
+ state = anv_state_stream_alloc(&cmd_buffer->surface_state_stream, size, 16);
+
+ /* Copy in the vertex and instance data */
+ memcpy(state.map, vertex_data, sizeof(vertex_data));
+ memcpy(state.map + sizeof(vertex_data), instance_data,
+ num_instances * sizeof(*instance_data));
+
+ struct anv_buffer vertex_buffer = {
+ .device = cmd_buffer->device,
+ .size = size,
+ .bo = &device->surface_state_block_pool.bo,
+ .offset = state.offset
+ };
+
+ anv_CmdBindVertexBuffers(anv_cmd_buffer_to_handle(cmd_buffer), 0, 2,
+ (VkBuffer[]) {
+ anv_buffer_to_handle(&vertex_buffer),
+ anv_buffer_to_handle(&vertex_buffer)
+ },
+ (VkDeviceSize[]) {
+ 0,
+ sizeof(vertex_data)
+ });
+
+ if (cmd_buffer->state.pipeline != anv_pipeline_from_handle(device->meta_state.clear.pipeline))
+ anv_CmdBindPipeline(anv_cmd_buffer_to_handle(cmd_buffer),
+ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ device->meta_state.clear.pipeline);
+
+ /* We don't need anything here, only set if not already set. */
+ if (cmd_buffer->state.rs_state == NULL)
+ anv_CmdBindDynamicRasterState(anv_cmd_buffer_to_handle(cmd_buffer),
+ device->meta_state.shared.rs_state);
+
+ if (cmd_buffer->state.vp_state == NULL)
+ anv_CmdBindDynamicViewportState(anv_cmd_buffer_to_handle(cmd_buffer),
+ cmd_buffer->state.framebuffer->vp_state);
+
+ if (cmd_buffer->state.ds_state == NULL)
+ anv_CmdBindDynamicDepthStencilState(anv_cmd_buffer_to_handle(cmd_buffer),
+ device->meta_state.shared.ds_state);
+
+ if (cmd_buffer->state.cb_state == NULL)
+ anv_CmdBindDynamicColorBlendState(anv_cmd_buffer_to_handle(cmd_buffer),
+ device->meta_state.shared.cb_state);
+
+ anv_CmdDraw(anv_cmd_buffer_to_handle(cmd_buffer), 0, 3, 0, num_instances);
+}
+
+void
+anv_cmd_buffer_clear_attachments(struct anv_cmd_buffer *cmd_buffer,
+ struct anv_render_pass *pass,
+ const VkClearValue *clear_values)
+{
+ struct anv_saved_state saved_state;
+
+ int num_clear_layers = 0;
+ for (uint32_t i = 0; i < pass->attachment_count; i++) {
+ if (pass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
+ if (anv_is_vk_format_depth_or_stencil(pass->attachments[i].format)) {
+ anv_finishme("Can't clear depth-stencil yet");
+ continue;
+ }
+ num_clear_layers++;
+ }
+ }
+
+ if (num_clear_layers == 0)
+ return;
+
+ struct clear_instance_data instance_data[num_clear_layers];
+ uint32_t color_attachments[num_clear_layers];
+
+ int layer = 0;
+ for (uint32_t i = 0; i < pass->attachment_count; i++) {
+ if (pass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_CLEAR &&
+ !anv_is_vk_format_depth_or_stencil(pass->attachments[i].format)) {
+ instance_data[layer] = (struct clear_instance_data) {
+ .vue_header = {
+ .RTAIndex = i,
+ .ViewportIndex = 0,
+ .PointWidth = 0.0
+ },
+ .color = clear_values[i].color,
+ };
+ color_attachments[layer] = i;
+ layer++;
+ }
+ }
+
+ anv_cmd_buffer_save(cmd_buffer, &saved_state);
+
+ struct anv_subpass subpass = {
+ .input_count = 0,
+ .color_count = num_clear_layers,
+ .color_attachments = color_attachments,
+ .depth_stencil_attachment = VK_ATTACHMENT_UNUSED,
+ };
+
+ anv_cmd_buffer_begin_subpass(cmd_buffer, &subpass);
+
+ meta_emit_clear(cmd_buffer, num_clear_layers, instance_data);
+
+ /* Restore API state */
+ anv_cmd_buffer_restore(cmd_buffer, &saved_state);
+}
+
+static void
+anv_device_init_meta_blit_state(struct anv_device *device)
+{
+ /* We don't use a vertex shader for clearing, but instead build and pass
+ * the VUEs directly to the rasterization backend. However, we do need
+ * to provide GLSL source for the vertex shader so that the compiler
+ * does not dead-code our inputs.
+ */
+ VkShaderModule vsm = GLSL_VK_SHADER_MODULE(device, VERTEX,
+ in vec2 a_pos;
+ in vec2 a_tex_coord;
+ out vec4 v_tex_coord;
+ void main()
+ {
+ v_tex_coord = vec4(a_tex_coord, 0, 1);
+ gl_Position = vec4(a_pos, 0, 1);
+ }
+ );
+
+ VkShaderModule fsm = GLSL_VK_SHADER_MODULE(device, FRAGMENT,
+ out vec4 f_color;
+ in vec4 v_tex_coord;
+ layout(set = 0, binding = 0) uniform sampler2D u_tex;
+ void main()
+ {
+ f_color = texture(u_tex, v_tex_coord.xy);
+ }
+ );
+
+ VkShader vs;
+ anv_CreateShader(anv_device_to_handle(device),
+ &(VkShaderCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
+ .module = vsm,
+ .pName = "main",
+ }, &vs);
+
+ VkShader fs;
+ anv_CreateShader(anv_device_to_handle(device),
+ &(VkShaderCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
+ .module = fsm,
+ .pName = "main",
+ }, &fs);
+
+ VkPipelineVertexInputStateCreateInfo vi_create_info = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+ .bindingCount = 2,
+ .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
+ {
+ .binding = 0,
+ .strideInBytes = 0,
+ .stepRate = VK_VERTEX_INPUT_STEP_RATE_VERTEX
+ },
+ {
+ .binding = 1,
+ .strideInBytes = 16,
+ .stepRate = VK_VERTEX_INPUT_STEP_RATE_VERTEX
+ },
+ },
+ .attributeCount = 3,
+ .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
+ {
+ /* VUE Header */
+ .location = 0,
+ .binding = 0,
+ .format = VK_FORMAT_R32G32B32A32_UINT,
+ .offsetInBytes = 0
+ },
+ {
+ /* Position */
+ .location = 1,
+ .binding = 1,
+ .format = VK_FORMAT_R32G32_SFLOAT,
+ .offsetInBytes = 0
+ },
+ {
+ /* Texture Coordinate */
+ .location = 2,
+ .binding = 1,
+ .format = VK_FORMAT_R32G32_SFLOAT,
+ .offsetInBytes = 8
+ }
+ }
+ };
+
+ VkDescriptorSetLayoutCreateInfo ds_layout_info = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ .count = 1,
+ .pBinding = (VkDescriptorSetLayoutBinding[]) {
+ {
+ .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ .arraySize = 1,
+ .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
+ .pImmutableSamplers = NULL
+ },
+ }
+ };
+ anv_CreateDescriptorSetLayout(anv_device_to_handle(device), &ds_layout_info,
+ &device->meta_state.blit.ds_layout);
+
+ anv_CreatePipelineLayout(anv_device_to_handle(device),
+ &(VkPipelineLayoutCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ .descriptorSetCount = 1,
+ .pSetLayouts = &device->meta_state.blit.ds_layout,
+ },
+ &device->meta_state.blit.pipeline_layout);
+
+ anv_pipeline_create(anv_device_to_handle(device),
+ &(VkGraphicsPipelineCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+ .stageCount = 2,
+ .pStages = (VkPipelineShaderStageCreateInfo[]) {
+ {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = VK_SHADER_STAGE_VERTEX,
+ .shader = vs,
+ .pSpecializationInfo = NULL
+ }, {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ .stage = VK_SHADER_STAGE_FRAGMENT,
+ .shader = fs,
+ .pSpecializationInfo = NULL
+ },
+ },
+ .pVertexInputState = &vi_create_info,
+ .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+ .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
+ .primitiveRestartEnable = false,
+ },
+ .pRasterState = &(VkPipelineRasterStateCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTER_STATE_CREATE_INFO,
+ .depthClipEnable = true,
+ .rasterizerDiscardEnable = false,
+ .fillMode = VK_FILL_MODE_SOLID,
+ .cullMode = VK_CULL_MODE_NONE,
+ .frontFace = VK_FRONT_FACE_CCW
+ },
+ .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+ .attachmentCount = 1,
+ .pAttachments = (VkPipelineColorBlendAttachmentState []) {
+ { .channelWriteMask = VK_CHANNEL_A_BIT |
+ VK_CHANNEL_R_BIT | VK_CHANNEL_G_BIT | VK_CHANNEL_B_BIT },
+ }
+ },
+ .flags = 0,
+ .layout = device->meta_state.blit.pipeline_layout,
+ },
+ &(struct anv_pipeline_create_info) {
+ .use_repclear = false,
+ .disable_viewport = true,
+ .disable_scissor = true,
+ .disable_vs = true,
+ .use_rectlist = true
+ },
+ &device->meta_state.blit.pipeline);
+
+ anv_DestroyShader(anv_device_to_handle(device), vs);
+ anv_DestroyShader(anv_device_to_handle(device), fs);
+}
+
+static void
+meta_prepare_blit(struct anv_cmd_buffer *cmd_buffer,
+ struct anv_saved_state *saved_state)
+{
+ struct anv_device *device = cmd_buffer->device;
+
+ anv_cmd_buffer_save(cmd_buffer, saved_state);
+
+ if (cmd_buffer->state.pipeline != anv_pipeline_from_handle(device->meta_state.blit.pipeline))
+ anv_CmdBindPipeline(anv_cmd_buffer_to_handle(cmd_buffer),
+ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ device->meta_state.blit.pipeline);
+
+ /* We don't need anything here, only set if not already set. */
+ if (cmd_buffer->state.rs_state == NULL)
+ anv_CmdBindDynamicRasterState(anv_cmd_buffer_to_handle(cmd_buffer),
+ device->meta_state.shared.rs_state);
+ if (cmd_buffer->state.ds_state == NULL)
+ anv_CmdBindDynamicDepthStencilState(anv_cmd_buffer_to_handle(cmd_buffer),
+ device->meta_state.shared.ds_state);
+
+ saved_state->cb_state = anv_dynamic_cb_state_to_handle(cmd_buffer->state.cb_state);
+ anv_CmdBindDynamicColorBlendState(anv_cmd_buffer_to_handle(cmd_buffer),
+ device->meta_state.shared.cb_state);
+}
+
+struct blit_region {
+ VkOffset3D src_offset;
+ VkExtent3D src_extent;
+ VkOffset3D dest_offset;
+ VkExtent3D dest_extent;
+};
+
+static void
+meta_emit_blit(struct anv_cmd_buffer *cmd_buffer,
+ struct anv_image_view *src,
+ VkOffset3D src_offset,
+ VkExtent3D src_extent,
+ struct anv_color_attachment_view *dest,
+ VkOffset3D dest_offset,
+ VkExtent3D dest_extent)
+{
+ struct anv_device *device = cmd_buffer->device;
+ VkDescriptorPool dummy_desc_pool = { .handle = 1 };
+
+ struct blit_vb_data {
+ float pos[2];
+ float tex_coord[2];
+ } *vb_data;
+
+ unsigned vb_size = sizeof(struct vue_header) + 3 * sizeof(*vb_data);
+
+ struct anv_state vb_state =
+ anv_state_stream_alloc(&cmd_buffer->surface_state_stream, vb_size, 16);
+ memset(vb_state.map, 0, sizeof(struct vue_header));
+ vb_data = vb_state.map + sizeof(struct vue_header);
+
+ vb_data[0] = (struct blit_vb_data) {
+ .pos = {
+ dest_offset.x + dest_extent.width,
+ dest_offset.y + dest_extent.height,
+ },
+ .tex_coord = {
+ (float)(src_offset.x + src_extent.width) / (float)src->extent.width,
+ (float)(src_offset.y + src_extent.height) / (float)src->extent.height,
+ },
+ };
+
+ vb_data[1] = (struct blit_vb_data) {
+ .pos = {
+ dest_offset.x,
+ dest_offset.y + dest_extent.height,
+ },
+ .tex_coord = {
+ (float)src_offset.x / (float)src->extent.width,
+ (float)(src_offset.y + src_extent.height) / (float)src->extent.height,
+ },
+ };
+
+ vb_data[2] = (struct blit_vb_data) {
+ .pos = {
+ dest_offset.x,
+ dest_offset.y,
+ },
+ .tex_coord = {
+ (float)src_offset.x / (float)src->extent.width,
+ (float)src_offset.y / (float)src->extent.height,
+ },
+ };
+
+ struct anv_buffer vertex_buffer = {
+ .device = device,
+ .size = vb_size,
+ .bo = &device->surface_state_block_pool.bo,
+ .offset = vb_state.offset,
+ };
+
+ anv_CmdBindVertexBuffers(anv_cmd_buffer_to_handle(cmd_buffer), 0, 2,
+ (VkBuffer[]) {
+ anv_buffer_to_handle(&vertex_buffer),
+ anv_buffer_to_handle(&vertex_buffer)
+ },
+ (VkDeviceSize[]) {
+ 0,
+ sizeof(struct vue_header),
+ });
+
+ uint32_t count;
+ VkDescriptorSet set;
+ anv_AllocDescriptorSets(anv_device_to_handle(device), dummy_desc_pool,
+ VK_DESCRIPTOR_SET_USAGE_ONE_SHOT,
+ 1, &device->meta_state.blit.ds_layout, &set, &count);
+ anv_UpdateDescriptorSets(anv_device_to_handle(device),
+ 1, /* writeCount */
+ (VkWriteDescriptorSet[]) {
+ {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .destSet = set,
+ .destBinding = 0,
+ .destArrayElement = 0,
+ .count = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ .pDescriptors = (VkDescriptorInfo[]) {
+ {
+ .imageView = anv_image_view_to_handle(src),
+ .imageLayout = VK_IMAGE_LAYOUT_GENERAL
+ },
+ }
+ }
+ }, 0, NULL);
+
+ VkFramebuffer fb;
+ anv_CreateFramebuffer(anv_device_to_handle(device),
+ &(VkFramebufferCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ .attachmentCount = 1,
+ .pAttachments = (VkAttachmentBindInfo[]) {
+ {
+ .view = anv_attachment_view_to_handle(&dest->base),
+ .layout = VK_IMAGE_LAYOUT_GENERAL
+ }
+ },
+ .width = dest->base.extent.width,
+ .height = dest->base.extent.height,
+ .layers = 1
+ }, &fb);
+
+ VkRenderPass pass;
+ anv_CreateRenderPass(anv_device_to_handle(device),
+ &(VkRenderPassCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ .attachmentCount = 1,
+ .pAttachments = &(VkAttachmentDescription) {
+ .sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION,
+ .format = dest->view.format,
+ .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
+ .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .initialLayout = VK_IMAGE_LAYOUT_GENERAL,
+ .finalLayout = VK_IMAGE_LAYOUT_GENERAL,
+ },
+ .subpassCount = 1,
+ .pSubpasses = &(VkSubpassDescription) {
+ .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION,
+ .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
+ .inputCount = 0,
+ .colorCount = 1,
+ .colorAttachments = &(VkAttachmentReference) {
+ .attachment = 0,
+ .layout = VK_IMAGE_LAYOUT_GENERAL,
+ },
+ .resolveAttachments = NULL,
+ .depthStencilAttachment = (VkAttachmentReference) {
+ .attachment = VK_ATTACHMENT_UNUSED,
+ .layout = VK_IMAGE_LAYOUT_GENERAL,
+ },
+ .preserveCount = 1,
+ .preserveAttachments = &(VkAttachmentReference) {
+ .attachment = 0,
+ .layout = VK_IMAGE_LAYOUT_GENERAL,
+ },
+ },
+ .dependencyCount = 0,
+ }, &pass);
+
+ anv_CmdBeginRenderPass(anv_cmd_buffer_to_handle(cmd_buffer),
+ &(VkRenderPassBeginInfo) {
+ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ .renderPass = pass,
+ .framebuffer = fb,
+ .renderArea = {
+ .offset = { dest_offset.x, dest_offset.y },
+ .extent = { dest_extent.width, dest_extent.height },
+ },
+ .attachmentCount = 1,
+ .pAttachmentClearValues = NULL,
+ }, VK_RENDER_PASS_CONTENTS_INLINE);
+
+ anv_CmdBindDynamicViewportState(anv_cmd_buffer_to_handle(cmd_buffer),
+ anv_framebuffer_from_handle(fb)->vp_state);
+
+ anv_CmdBindDescriptorSets(anv_cmd_buffer_to_handle(cmd_buffer),
+ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ device->meta_state.blit.pipeline_layout, 0, 1,
+ &set, 0, NULL);
+
+ anv_CmdDraw(anv_cmd_buffer_to_handle(cmd_buffer), 0, 3, 0, 1);
+
+ anv_CmdEndRenderPass(anv_cmd_buffer_to_handle(cmd_buffer));
+
+ /* At the point where we emit the draw call, all data from the
+ * descriptor sets, etc. has been used. We are free to delete it.
+ */
+ anv_descriptor_set_destroy(device, anv_descriptor_set_from_handle(set));
+ anv_DestroyFramebuffer(anv_device_to_handle(device), fb);
+ anv_DestroyRenderPass(anv_device_to_handle(device), pass);
+}
+
+static void
+meta_finish_blit(struct anv_cmd_buffer *cmd_buffer,
+ const struct anv_saved_state *saved_state)
+{
+ anv_cmd_buffer_restore(cmd_buffer, saved_state);
+ anv_CmdBindDynamicColorBlendState(anv_cmd_buffer_to_handle(cmd_buffer),
+ saved_state->cb_state);
+}
+
+static VkFormat
+vk_format_for_cpp(int cpp)
+{
+ switch (cpp) {
+ case 1: return VK_FORMAT_R8_UINT;
+ case 2: return VK_FORMAT_R8G8_UINT;
+ case 3: return VK_FORMAT_R8G8B8_UINT;
+ case 4: return VK_FORMAT_R8G8B8A8_UINT;
+ case 6: return VK_FORMAT_R16G16B16_UINT;
+ case 8: return VK_FORMAT_R16G16B16A16_UINT;
+ case 12: return VK_FORMAT_R32G32B32_UINT;
+ case 16: return VK_FORMAT_R32G32B32A32_UINT;
+ default:
+ unreachable("Invalid format cpp");
+ }
+}
+
+static void
+do_buffer_copy(struct anv_cmd_buffer *cmd_buffer,
+ struct anv_bo *src, uint64_t src_offset,
+ struct anv_bo *dest, uint64_t dest_offset,
+ int width, int height, VkFormat copy_format)
+{
+ VkDevice vk_device = anv_device_to_handle(cmd_buffer->device);
+
+ VkImageCreateInfo image_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .imageType = VK_IMAGE_TYPE_2D,
+ .format = copy_format,
+ .extent = {
+ .width = width,
+ .height = height,
+ .depth = 1,
+ },
+ .mipLevels = 1,
+ .arraySize = 1,
+ .samples = 1,
+ .tiling = VK_IMAGE_TILING_LINEAR,
+ .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
+ .flags = 0,
+ };
+
+ VkImage src_image, dest_image;
+ anv_CreateImage(vk_device, &image_info, &src_image);
+ anv_CreateImage(vk_device, &image_info, &dest_image);
+
+ /* We could use a vk call to bind memory, but that would require
+ * creating a dummy memory object etc. so there's really no point.
+ */
+ anv_image_from_handle(src_image)->bo = src;
+ anv_image_from_handle(src_image)->offset = src_offset;
+ anv_image_from_handle(dest_image)->bo = dest;
+ anv_image_from_handle(dest_image)->offset = dest_offset;
+
+ struct anv_image_view src_view;
+ anv_image_view_init(&src_view, cmd_buffer->device,
+ &(VkImageViewCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ .image = src_image,
+ .viewType = VK_IMAGE_VIEW_TYPE_2D,
+ .format = copy_format,
+ .channels = {
+ VK_CHANNEL_SWIZZLE_R,
+ VK_CHANNEL_SWIZZLE_G,
+ VK_CHANNEL_SWIZZLE_B,
+ VK_CHANNEL_SWIZZLE_A
+ },
+ .subresourceRange = {
+ .aspect = VK_IMAGE_ASPECT_COLOR,
+ .baseMipLevel = 0,
+ .mipLevels = 1,
+ .baseArraySlice = 0,
+ .arraySize = 1
+ },
+ },
+ cmd_buffer);
+
+ struct anv_color_attachment_view dest_view;
+ anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
+ &(VkAttachmentViewCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
+ .image = dest_image,
+ .format = copy_format,
+ .mipLevel = 0,
+ .baseArraySlice = 0,
+ .arraySize = 1,
+ },
+ cmd_buffer);
+
+ meta_emit_blit(cmd_buffer,
+ &src_view,
+ (VkOffset3D) { 0, 0, 0 },
+ (VkExtent3D) { width, height, 1 },
+ &dest_view,
+ (VkOffset3D) { 0, 0, 0 },
+ (VkExtent3D) { width, height, 1 });
+
+ anv_DestroyImage(vk_device, src_image);
+ anv_DestroyImage(vk_device, dest_image);
+}
+
+void anv_CmdCopyBuffer(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer srcBuffer,
+ VkBuffer destBuffer,
+ uint32_t regionCount,
+ const VkBufferCopy* pRegions)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_buffer, src_buffer, srcBuffer);
+ ANV_FROM_HANDLE(anv_buffer, dest_buffer, destBuffer);
+
+ struct anv_saved_state saved_state;
+
+ meta_prepare_blit(cmd_buffer, &saved_state);
+
+ for (unsigned r = 0; r < regionCount; r++) {
+ uint64_t src_offset = src_buffer->offset + pRegions[r].srcOffset;
+ uint64_t dest_offset = dest_buffer->offset + pRegions[r].destOffset;
+ uint64_t copy_size = pRegions[r].copySize;
+
+ /* First, we compute the biggest format that can be used with the
+ * given offsets and size.
+ */
+ int cpp = 16;
+
+ int fs = ffs(src_offset) - 1;
+ if (fs != -1)
+ cpp = MIN2(cpp, 1 << fs);
+ assert(src_offset % cpp == 0);
+
+ fs = ffs(dest_offset) - 1;
+ if (fs != -1)
+ cpp = MIN2(cpp, 1 << fs);
+ assert(dest_offset % cpp == 0);
+
+ fs = ffs(pRegions[r].copySize) - 1;
+ if (fs != -1)
+ cpp = MIN2(cpp, 1 << fs);
+ assert(pRegions[r].copySize % cpp == 0);
+
+ VkFormat copy_format = vk_format_for_cpp(cpp);
+
+ /* This is maximum possible width/height our HW can handle */
+ uint64_t max_surface_dim = 1 << 14;
+
+ /* First, we make a bunch of max-sized copies */
+ uint64_t max_copy_size = max_surface_dim * max_surface_dim * cpp;
+ while (copy_size > max_copy_size) {
+ do_buffer_copy(cmd_buffer, src_buffer->bo, src_offset,
+ dest_buffer->bo, dest_offset,
+ max_surface_dim, max_surface_dim, copy_format);
+ copy_size -= max_copy_size;
+ src_offset += max_copy_size;
+ dest_offset += max_copy_size;
+ }
+
+ uint64_t height = copy_size / (max_surface_dim * cpp);
+ assert(height < max_surface_dim);
+ if (height != 0) {
+ uint64_t rect_copy_size = height * max_surface_dim * cpp;
+ do_buffer_copy(cmd_buffer, src_buffer->bo, src_offset,
+ dest_buffer->bo, dest_offset,
+ max_surface_dim, height, copy_format);
+ copy_size -= rect_copy_size;
+ src_offset += rect_copy_size;
+ dest_offset += rect_copy_size;
+ }
+
+ if (copy_size != 0) {
+ do_buffer_copy(cmd_buffer, src_buffer->bo, src_offset,
+ dest_buffer->bo, dest_offset,
+ copy_size / cpp, 1, copy_format);
+ }
+ }
+
+ meta_finish_blit(cmd_buffer, &saved_state);
+}
+
+void anv_CmdCopyImage(
+ VkCmdBuffer cmdBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage destImage,
+ VkImageLayout destImageLayout,
+ uint32_t regionCount,
+ const VkImageCopy* pRegions)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_image, src_image, srcImage);
+
+ struct anv_saved_state saved_state;
+
+ meta_prepare_blit(cmd_buffer, &saved_state);
+
+ for (unsigned r = 0; r < regionCount; r++) {
+ struct anv_image_view src_view;
+ anv_image_view_init(&src_view, cmd_buffer->device,
+ &(VkImageViewCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ .image = srcImage,
+ .viewType = VK_IMAGE_VIEW_TYPE_2D,
+ .format = src_image->format,
+ .channels = {
+ VK_CHANNEL_SWIZZLE_R,
+ VK_CHANNEL_SWIZZLE_G,
+ VK_CHANNEL_SWIZZLE_B,
+ VK_CHANNEL_SWIZZLE_A
+ },
+ .subresourceRange = {
+ .aspect = pRegions[r].srcSubresource.aspect,
+ .baseMipLevel = pRegions[r].srcSubresource.mipLevel,
+ .mipLevels = 1,
+ .baseArraySlice = pRegions[r].srcSubresource.arraySlice,
+ .arraySize = 1
+ },
+ },
+ cmd_buffer);
+
+ struct anv_color_attachment_view dest_view;
+ anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
+ &(VkAttachmentViewCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
+ .image = destImage,
+ .format = src_image->format,
+ .mipLevel = pRegions[r].destSubresource.mipLevel,
+ .baseArraySlice = pRegions[r].destSubresource.arraySlice,
+ .arraySize = 1,
+ },
+ cmd_buffer);
+
+ meta_emit_blit(cmd_buffer,
+ &src_view,
+ pRegions[r].srcOffset,
+ pRegions[r].extent,
+ &dest_view,
+ pRegions[r].destOffset,
+ pRegions[r].extent);
+ }
+
+ meta_finish_blit(cmd_buffer, &saved_state);
+}
+
+void anv_CmdBlitImage(
+ VkCmdBuffer cmdBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage destImage,
+ VkImageLayout destImageLayout,
+ uint32_t regionCount,
+ const VkImageBlit* pRegions,
+ VkTexFilter filter)
+
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_image, src_image, srcImage);
+ ANV_FROM_HANDLE(anv_image, dest_image, destImage);
+
+ struct anv_saved_state saved_state;
+
+ anv_finishme("respect VkTexFilter");
+
+ meta_prepare_blit(cmd_buffer, &saved_state);
+
+ for (unsigned r = 0; r < regionCount; r++) {
+ struct anv_image_view src_view;
+ anv_image_view_init(&src_view, cmd_buffer->device,
+ &(VkImageViewCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ .image = srcImage,
+ .viewType = VK_IMAGE_VIEW_TYPE_2D,
+ .format = src_image->format,
+ .channels = {
+ VK_CHANNEL_SWIZZLE_R,
+ VK_CHANNEL_SWIZZLE_G,
+ VK_CHANNEL_SWIZZLE_B,
+ VK_CHANNEL_SWIZZLE_A
+ },
+ .subresourceRange = {
+ .aspect = pRegions[r].srcSubresource.aspect,
+ .baseMipLevel = pRegions[r].srcSubresource.mipLevel,
+ .mipLevels = 1,
+ .baseArraySlice = pRegions[r].srcSubresource.arraySlice,
+ .arraySize = 1
+ },
+ },
+ cmd_buffer);
+
+ struct anv_color_attachment_view dest_view;
+ anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
+ &(VkAttachmentViewCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
+ .image = destImage,
+ .format = dest_image->format,
+ .mipLevel = pRegions[r].destSubresource.mipLevel,
+ .baseArraySlice = pRegions[r].destSubresource.arraySlice,
+ .arraySize = 1,
+ },
+ cmd_buffer);
+
+ meta_emit_blit(cmd_buffer,
+ &src_view,
+ pRegions[r].srcOffset,
+ pRegions[r].srcExtent,
+ &dest_view,
+ pRegions[r].destOffset,
+ pRegions[r].destExtent);
+ }
+
+ meta_finish_blit(cmd_buffer, &saved_state);
+}
+
+void anv_CmdCopyBufferToImage(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer srcBuffer,
+ VkImage destImage,
+ VkImageLayout destImageLayout,
+ uint32_t regionCount,
+ const VkBufferImageCopy* pRegions)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_buffer, src_buffer, srcBuffer);
+ ANV_FROM_HANDLE(anv_image, dest_image, destImage);
+ VkDevice vk_device = anv_device_to_handle(cmd_buffer->device);
+ struct anv_saved_state saved_state;
+
+ meta_prepare_blit(cmd_buffer, &saved_state);
+
+ for (unsigned r = 0; r < regionCount; r++) {
+ if (pRegions[r].bufferRowLength != 0)
+ anv_finishme("bufferRowLength not supported in CopyBufferToImage");
+ if (pRegions[r].bufferImageHeight != 0)
+ anv_finishme("bufferImageHeight not supported in CopyBufferToImage");
+
+ VkImage srcImage;
+ anv_CreateImage(vk_device,
+ &(VkImageCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .imageType = VK_IMAGE_TYPE_2D,
+ .format = dest_image->format,
+ .extent = {
+ .width = pRegions[r].imageExtent.width,
+ .height = pRegions[r].imageExtent.height,
+ .depth = 1,
+ },
+ .mipLevels = 1,
+ .arraySize = 1,
+ .samples = 1,
+ .tiling = VK_IMAGE_TILING_LINEAR,
+ .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
+ .flags = 0,
+ }, &srcImage);
+
+ ANV_FROM_HANDLE(anv_image, src_image, srcImage);
+
+ /* We could use a vk call to bind memory, but that would require
+ * creating a dummy memory object etc. so there's really no point.
+ */
+ src_image->bo = src_buffer->bo;
+ src_image->offset = src_buffer->offset + pRegions[r].bufferOffset;
+
+ struct anv_image_view src_view;
+ anv_image_view_init(&src_view, cmd_buffer->device,
+ &(VkImageViewCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ .image = anv_image_to_handle(src_image),
+ .viewType = VK_IMAGE_VIEW_TYPE_2D,
+ .format = dest_image->format,
+ .channels = {
+ VK_CHANNEL_SWIZZLE_R,
+ VK_CHANNEL_SWIZZLE_G,
+ VK_CHANNEL_SWIZZLE_B,
+ VK_CHANNEL_SWIZZLE_A
+ },
+ .subresourceRange = {
+ .aspect = pRegions[r].imageSubresource.aspect,
+ .baseMipLevel = 0,
+ .mipLevels = 1,
+ .baseArraySlice = 0,
+ .arraySize = 1
+ },
+ },
+ cmd_buffer);
+
+ struct anv_color_attachment_view dest_view;
+ anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
+ &(VkAttachmentViewCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
+ .image = anv_image_to_handle(dest_image),
+ .format = dest_image->format,
+ .mipLevel = pRegions[r].imageSubresource.mipLevel,
+ .baseArraySlice = pRegions[r].imageSubresource.arraySlice,
+ .arraySize = 1,
+ },
+ cmd_buffer);
+
+ meta_emit_blit(cmd_buffer,
+ &src_view,
+ (VkOffset3D) { 0, 0, 0 },
+ pRegions[r].imageExtent,
+ &dest_view,
+ pRegions[r].imageOffset,
+ pRegions[r].imageExtent);
+
+ anv_DestroyImage(vk_device, srcImage);
+ }
+
+ meta_finish_blit(cmd_buffer, &saved_state);
+}
+
+void anv_CmdCopyImageToBuffer(
+ VkCmdBuffer cmdBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkBuffer destBuffer,
+ uint32_t regionCount,
+ const VkBufferImageCopy* pRegions)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_image, src_image, srcImage);
+ ANV_FROM_HANDLE(anv_buffer, dest_buffer, destBuffer);
+ VkDevice vk_device = anv_device_to_handle(cmd_buffer->device);
+ struct anv_saved_state saved_state;
+
+ meta_prepare_blit(cmd_buffer, &saved_state);
+
+ for (unsigned r = 0; r < regionCount; r++) {
+ if (pRegions[r].bufferRowLength != 0)
+ anv_finishme("bufferRowLength not supported in CopyBufferToImage");
+ if (pRegions[r].bufferImageHeight != 0)
+ anv_finishme("bufferImageHeight not supported in CopyBufferToImage");
+
+ struct anv_image_view src_view;
+ anv_image_view_init(&src_view, cmd_buffer->device,
+ &(VkImageViewCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ .image = srcImage,
+ .viewType = VK_IMAGE_VIEW_TYPE_2D,
+ .format = src_image->format,
+ .channels = {
+ VK_CHANNEL_SWIZZLE_R,
+ VK_CHANNEL_SWIZZLE_G,
+ VK_CHANNEL_SWIZZLE_B,
+ VK_CHANNEL_SWIZZLE_A
+ },
+ .subresourceRange = {
+ .aspect = pRegions[r].imageSubresource.aspect,
+ .baseMipLevel = pRegions[r].imageSubresource.mipLevel,
+ .mipLevels = 1,
+ .baseArraySlice = pRegions[r].imageSubresource.arraySlice,
+ .arraySize = 1
+ },
+ },
+ cmd_buffer);
+
+ VkImage destImage;
+ anv_CreateImage(vk_device,
+ &(VkImageCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .imageType = VK_IMAGE_TYPE_2D,
+ .format = src_image->format,
+ .extent = {
+ .width = pRegions[r].imageExtent.width,
+ .height = pRegions[r].imageExtent.height,
+ .depth = 1,
+ },
+ .mipLevels = 1,
+ .arraySize = 1,
+ .samples = 1,
+ .tiling = VK_IMAGE_TILING_LINEAR,
+ .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
+ .flags = 0,
+ }, &destImage);
+
+ ANV_FROM_HANDLE(anv_image, dest_image, destImage);
+
+ /* We could use a vk call to bind memory, but that would require
+ * creating a dummy memory object etc. so there's really no point.
+ */
+ dest_image->bo = dest_buffer->bo;
+ dest_image->offset = dest_buffer->offset + pRegions[r].bufferOffset;
+
+ struct anv_color_attachment_view dest_view;
+ anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
+ &(VkAttachmentViewCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
+ .image = destImage,
+ .format = src_image->format,
+ .mipLevel = 0,
+ .baseArraySlice = 0,
+ .arraySize = 1,
+ },
+ cmd_buffer);
+
+ meta_emit_blit(cmd_buffer,
+ &src_view,
+ pRegions[r].imageOffset,
+ pRegions[r].imageExtent,
+ &dest_view,
+ (VkOffset3D) { 0, 0, 0 },
+ pRegions[r].imageExtent);
+
+ anv_DestroyImage(vk_device, destImage);
+ }
+
+ meta_finish_blit(cmd_buffer, &saved_state);
+}
+
+void anv_CmdUpdateBuffer(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer destBuffer,
+ VkDeviceSize destOffset,
+ VkDeviceSize dataSize,
+ const uint32_t* pData)
+{
+ stub();
+}
+
+void anv_CmdFillBuffer(
+ VkCmdBuffer cmdBuffer,
+ VkBuffer destBuffer,
+ VkDeviceSize destOffset,
+ VkDeviceSize fillSize,
+ uint32_t data)
+{
+ stub();
+}
+
+void anv_CmdClearColorImage(
+ VkCmdBuffer cmdBuffer,
+ VkImage _image,
+ VkImageLayout imageLayout,
+ const VkClearColorValue* pColor,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange* pRanges)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_image, image, _image);
+ struct anv_saved_state saved_state;
+
+ anv_cmd_buffer_save(cmd_buffer, &saved_state);
+
+ for (uint32_t r = 0; r < rangeCount; r++) {
+ for (uint32_t l = 0; l < pRanges[r].mipLevels; l++) {
+ for (uint32_t s = 0; s < pRanges[r].arraySize; s++) {
+ struct anv_color_attachment_view view;
+ anv_color_attachment_view_init(&view, cmd_buffer->device,
+ &(VkAttachmentViewCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
+ .image = _image,
+ .format = image->format,
+ .mipLevel = pRanges[r].baseMipLevel + l,
+ .baseArraySlice = pRanges[r].baseArraySlice + s,
+ .arraySize = 1,
+ },
+ cmd_buffer);
+
+ VkFramebuffer fb;
+ anv_CreateFramebuffer(anv_device_to_handle(cmd_buffer->device),
+ &(VkFramebufferCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ .attachmentCount = 1,
+ .pAttachments = (VkAttachmentBindInfo[]) {
+ {
+ .view = anv_attachment_view_to_handle(&view.base),
+ .layout = VK_IMAGE_LAYOUT_GENERAL
+ }
+ },
+ .width = view.base.extent.width,
+ .height = view.base.extent.height,
+ .layers = 1
+ }, &fb);
+
+ VkRenderPass pass;
+ anv_CreateRenderPass(anv_device_to_handle(cmd_buffer->device),
+ &(VkRenderPassCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ .attachmentCount = 1,
+ .pAttachments = &(VkAttachmentDescription) {
+ .sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION,
+ .format = view.view.format,
+ .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
+ .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .initialLayout = VK_IMAGE_LAYOUT_GENERAL,
+ .finalLayout = VK_IMAGE_LAYOUT_GENERAL,
+ },
+ .subpassCount = 1,
+ .pSubpasses = &(VkSubpassDescription) {
+ .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION,
+ .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
+ .inputCount = 0,
+ .colorCount = 1,
+ .colorAttachments = &(VkAttachmentReference) {
+ .attachment = 0,
+ .layout = VK_IMAGE_LAYOUT_GENERAL,
+ },
+ .resolveAttachments = NULL,
+ .depthStencilAttachment = (VkAttachmentReference) {
+ .attachment = VK_ATTACHMENT_UNUSED,
+ .layout = VK_IMAGE_LAYOUT_GENERAL,
+ },
+ .preserveCount = 1,
+ .preserveAttachments = &(VkAttachmentReference) {
+ .attachment = 0,
+ .layout = VK_IMAGE_LAYOUT_GENERAL,
+ },
+ },
+ .dependencyCount = 0,
+ }, &pass);
+
+ anv_CmdBeginRenderPass(anv_cmd_buffer_to_handle(cmd_buffer),
+ &(VkRenderPassBeginInfo) {
+ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ .renderArea = {
+ .offset = { 0, 0, },
+ .extent = {
+ .width = view.base.extent.width,
+ .height = view.base.extent.height,
+ },
+ },
+ .renderPass = pass,
+ .framebuffer = fb,
+ .attachmentCount = 1,
+ .pAttachmentClearValues = NULL,
+ }, VK_RENDER_PASS_CONTENTS_INLINE);
+
+ struct clear_instance_data instance_data = {
+ .vue_header = {
+ .RTAIndex = 0,
+ .ViewportIndex = 0,
+ .PointWidth = 0.0
+ },
+ .color = *pColor,
+ };
+
+ meta_emit_clear(cmd_buffer, 1, &instance_data);
+
+ anv_CmdEndRenderPass(anv_cmd_buffer_to_handle(cmd_buffer));
+ }
+ }
+ }
+
+ /* Restore API state */
+ anv_cmd_buffer_restore(cmd_buffer, &saved_state);
+}
+
+void anv_CmdClearDepthStencilImage(
+ VkCmdBuffer cmdBuffer,
+ VkImage image,
+ VkImageLayout imageLayout,
+ float depth,
+ uint32_t stencil,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange* pRanges)
+{
+ stub();
+}
+
+void anv_CmdClearColorAttachment(
+ VkCmdBuffer cmdBuffer,
+ uint32_t colorAttachment,
+ VkImageLayout imageLayout,
+ const VkClearColorValue* pColor,
+ uint32_t rectCount,
+ const VkRect3D* pRects)
+{
+ stub();
+}
+
+void anv_CmdClearDepthStencilAttachment(
+ VkCmdBuffer cmdBuffer,
+ VkImageAspectFlags imageAspectMask,
+ VkImageLayout imageLayout,
+ float depth,
+ uint32_t stencil,
+ uint32_t rectCount,
+ const VkRect3D* pRects)
+{
+ stub();
+}
+
+void anv_CmdResolveImage(
+ VkCmdBuffer cmdBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage destImage,
+ VkImageLayout destImageLayout,
+ uint32_t regionCount,
+ const VkImageResolve* pRegions)
+{
+ stub();
+}
+
+void
+anv_device_init_meta(struct anv_device *device)
+{
+ anv_device_init_meta_clear_state(device);
+ anv_device_init_meta_blit_state(device);
+
+ anv_CreateDynamicRasterState(anv_device_to_handle(device),
+ &(VkDynamicRasterStateCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_DYNAMIC_RASTER_STATE_CREATE_INFO,
+ },
+ &device->meta_state.shared.rs_state);
+
+ anv_CreateDynamicColorBlendState(anv_device_to_handle(device),
+ &(VkDynamicColorBlendStateCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_DYNAMIC_COLOR_BLEND_STATE_CREATE_INFO
+ },
+ &device->meta_state.shared.cb_state);
+
+ anv_CreateDynamicDepthStencilState(anv_device_to_handle(device),
+ &(VkDynamicDepthStencilStateCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_DYNAMIC_DEPTH_STENCIL_STATE_CREATE_INFO
+ },
+ &device->meta_state.shared.ds_state);
+}
+
+void
+anv_device_finish_meta(struct anv_device *device)
+{
+ /* Clear */
+ anv_DestroyPipeline(anv_device_to_handle(device),
+ device->meta_state.clear.pipeline);
+
+ /* Blit */
+ anv_DestroyPipeline(anv_device_to_handle(device),
+ device->meta_state.blit.pipeline);
+ anv_DestroyPipelineLayout(anv_device_to_handle(device),
+ device->meta_state.blit.pipeline_layout);
+ anv_DestroyDescriptorSetLayout(anv_device_to_handle(device),
+ device->meta_state.blit.ds_layout);
+
+ /* Shared */
+ anv_DestroyDynamicRasterState(anv_device_to_handle(device),
+ device->meta_state.shared.rs_state);
+ anv_DestroyDynamicColorBlendState(anv_device_to_handle(device),
+ device->meta_state.shared.cb_state);
+ anv_DestroyDynamicDepthStencilState(anv_device_to_handle(device),
+ device->meta_state.shared.ds_state);
+}
--- /dev/null
+/*
+ * 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 <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "anv_private.h"
+
+// Shader functions
+
+VkResult anv_CreateShaderModule(
+ VkDevice _device,
+ const VkShaderModuleCreateInfo* pCreateInfo,
+ VkShaderModule* pShaderModule)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_shader_module *module;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
+ assert(pCreateInfo->flags == 0);
+
+ module = anv_device_alloc(device, sizeof(*module) + pCreateInfo->codeSize, 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (module == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ module->size = pCreateInfo->codeSize;
+ memcpy(module->data, pCreateInfo->pCode, module->size);
+
+ *pShaderModule = anv_shader_module_to_handle(module);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyShaderModule(
+ VkDevice _device,
+ VkShaderModule _module)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_shader_module, module, _module);
+
+ anv_device_free(device, module);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_CreateShader(
+ VkDevice _device,
+ const VkShaderCreateInfo* pCreateInfo,
+ VkShader* pShader)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_shader_module, module, pCreateInfo->module);
+ struct anv_shader *shader;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_CREATE_INFO);
+ assert(pCreateInfo->flags == 0);
+
+ size_t name_len = strlen(pCreateInfo->pName);
+
+ if (strcmp(pCreateInfo->pName, "main") != 0) {
+ anv_finishme("Multiple shaders per module not really supported");
+ }
+
+ shader = anv_device_alloc(device, sizeof(*shader) + name_len + 1, 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (shader == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ shader->module = module;
+ memcpy(shader->entrypoint, pCreateInfo->pName, name_len + 1);
+
+ *pShader = anv_shader_to_handle(shader);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyShader(
+ VkDevice _device,
+ VkShader _shader)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_shader, shader, _shader);
+
+ anv_device_free(device, shader);
+
+ return VK_SUCCESS;
+}
+
+
+VkResult anv_CreatePipelineCache(
+ VkDevice device,
+ const VkPipelineCacheCreateInfo* pCreateInfo,
+ VkPipelineCache* pPipelineCache)
+{
+ pPipelineCache->handle = 1;
+
+ stub_return(VK_SUCCESS);
+}
+
+VkResult anv_DestroyPipelineCache(
+ VkDevice _device,
+ VkPipelineCache _cache)
+{
+ /* VkPipelineCache is a dummy object. */
+ return VK_SUCCESS;
+}
+
+size_t anv_GetPipelineCacheSize(
+ VkDevice device,
+ VkPipelineCache pipelineCache)
+{
+ stub_return(0);
+}
+
+VkResult anv_GetPipelineCacheData(
+ VkDevice device,
+ VkPipelineCache pipelineCache,
+ void* pData)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+VkResult anv_MergePipelineCaches(
+ VkDevice device,
+ VkPipelineCache destCache,
+ uint32_t srcCacheCount,
+ const VkPipelineCache* pSrcCaches)
+{
+ stub_return(VK_UNSUPPORTED);
+}
+
+// Pipeline functions
+
+static void
+emit_vertex_input(struct anv_pipeline *pipeline,
+ const VkPipelineVertexInputStateCreateInfo *info)
+{
+ const uint32_t num_dwords = 1 + info->attributeCount * 2;
+ uint32_t *p;
+ bool instancing_enable[32];
+
+ pipeline->vb_used = 0;
+ for (uint32_t i = 0; i < info->bindingCount; i++) {
+ const VkVertexInputBindingDescription *desc =
+ &info->pVertexBindingDescriptions[i];
+
+ pipeline->vb_used |= 1 << desc->binding;
+ pipeline->binding_stride[desc->binding] = desc->strideInBytes;
+
+ /* Step rate is programmed per vertex element (attribute), not
+ * binding. Set up a map of which bindings step per instance, for
+ * reference by vertex element setup. */
+ switch (desc->stepRate) {
+ default:
+ case VK_VERTEX_INPUT_STEP_RATE_VERTEX:
+ instancing_enable[desc->binding] = false;
+ break;
+ case VK_VERTEX_INPUT_STEP_RATE_INSTANCE:
+ instancing_enable[desc->binding] = true;
+ break;
+ }
+ }
+
+ p = anv_batch_emitn(&pipeline->batch, num_dwords,
+ GEN8_3DSTATE_VERTEX_ELEMENTS);
+
+ for (uint32_t i = 0; i < info->attributeCount; i++) {
+ const VkVertexInputAttributeDescription *desc =
+ &info->pVertexAttributeDescriptions[i];
+ const struct anv_format *format = anv_format_for_vk_format(desc->format);
+
+ struct GEN8_VERTEX_ELEMENT_STATE element = {
+ .VertexBufferIndex = desc->binding,
+ .Valid = true,
+ .SourceElementFormat = format->surface_format,
+ .EdgeFlagEnable = false,
+ .SourceElementOffset = desc->offsetInBytes,
+ .Component0Control = VFCOMP_STORE_SRC,
+ .Component1Control = format->num_channels >= 2 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
+ .Component2Control = format->num_channels >= 3 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
+ .Component3Control = format->num_channels >= 4 ? VFCOMP_STORE_SRC : VFCOMP_STORE_1_FP
+ };
+ GEN8_VERTEX_ELEMENT_STATE_pack(NULL, &p[1 + i * 2], &element);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_INSTANCING,
+ .InstancingEnable = instancing_enable[desc->binding],
+ .VertexElementIndex = i,
+ /* Vulkan so far doesn't have an instance divisor, so
+ * this is always 1 (ignored if not instancing). */
+ .InstanceDataStepRate = 1);
+ }
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_SGVS,
+ .VertexIDEnable = pipeline->vs_prog_data.uses_vertexid,
+ .VertexIDComponentNumber = 2,
+ .VertexIDElementOffset = info->bindingCount,
+ .InstanceIDEnable = pipeline->vs_prog_data.uses_instanceid,
+ .InstanceIDComponentNumber = 3,
+ .InstanceIDElementOffset = info->bindingCount);
+}
+
+static void
+emit_ia_state(struct anv_pipeline *pipeline,
+ const VkPipelineInputAssemblyStateCreateInfo *info,
+ const struct anv_pipeline_create_info *extra)
+{
+ static const uint32_t vk_to_gen_primitive_type[] = {
+ [VK_PRIMITIVE_TOPOLOGY_POINT_LIST] = _3DPRIM_POINTLIST,
+ [VK_PRIMITIVE_TOPOLOGY_LINE_LIST] = _3DPRIM_LINELIST,
+ [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP] = _3DPRIM_LINESTRIP,
+ [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST] = _3DPRIM_TRILIST,
+ [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP] = _3DPRIM_TRISTRIP,
+ [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN] = _3DPRIM_TRIFAN,
+ [VK_PRIMITIVE_TOPOLOGY_LINE_LIST_ADJ] = _3DPRIM_LINELIST_ADJ,
+ [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_ADJ] = _3DPRIM_LINESTRIP_ADJ,
+ [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_ADJ] = _3DPRIM_TRILIST_ADJ,
+ [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_ADJ] = _3DPRIM_TRISTRIP_ADJ,
+ [VK_PRIMITIVE_TOPOLOGY_PATCH] = _3DPRIM_PATCHLIST_1
+ };
+ uint32_t topology = vk_to_gen_primitive_type[info->topology];
+
+ if (extra && extra->use_rectlist)
+ topology = _3DPRIM_RECTLIST;
+
+ struct GEN8_3DSTATE_VF vf = {
+ GEN8_3DSTATE_VF_header,
+ .IndexedDrawCutIndexEnable = info->primitiveRestartEnable,
+ };
+ GEN8_3DSTATE_VF_pack(NULL, pipeline->state_vf, &vf);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_TOPOLOGY,
+ .PrimitiveTopologyType = topology);
+}
+
+static void
+emit_rs_state(struct anv_pipeline *pipeline,
+ const VkPipelineRasterStateCreateInfo *info,
+ const struct anv_pipeline_create_info *extra)
+{
+ static const uint32_t vk_to_gen_cullmode[] = {
+ [VK_CULL_MODE_NONE] = CULLMODE_NONE,
+ [VK_CULL_MODE_FRONT] = CULLMODE_FRONT,
+ [VK_CULL_MODE_BACK] = CULLMODE_BACK,
+ [VK_CULL_MODE_FRONT_AND_BACK] = CULLMODE_BOTH
+ };
+
+ static const uint32_t vk_to_gen_fillmode[] = {
+ [VK_FILL_MODE_POINTS] = RASTER_POINT,
+ [VK_FILL_MODE_WIREFRAME] = RASTER_WIREFRAME,
+ [VK_FILL_MODE_SOLID] = RASTER_SOLID
+ };
+
+ static const uint32_t vk_to_gen_front_face[] = {
+ [VK_FRONT_FACE_CCW] = CounterClockwise,
+ [VK_FRONT_FACE_CW] = Clockwise
+ };
+
+ struct GEN8_3DSTATE_SF sf = {
+ GEN8_3DSTATE_SF_header,
+ .ViewportTransformEnable = !(extra && extra->disable_viewport),
+ .TriangleStripListProvokingVertexSelect = 0,
+ .LineStripListProvokingVertexSelect = 0,
+ .TriangleFanProvokingVertexSelect = 0,
+ .PointWidthSource = pipeline->writes_point_size ? Vertex : State,
+ .PointWidth = 1.0,
+ };
+
+ /* FINISHME: VkBool32 rasterizerDiscardEnable; */
+
+ GEN8_3DSTATE_SF_pack(NULL, pipeline->state_sf, &sf);
+
+ struct GEN8_3DSTATE_RASTER raster = {
+ GEN8_3DSTATE_RASTER_header,
+ .FrontWinding = vk_to_gen_front_face[info->frontFace],
+ .CullMode = vk_to_gen_cullmode[info->cullMode],
+ .FrontFaceFillMode = vk_to_gen_fillmode[info->fillMode],
+ .BackFaceFillMode = vk_to_gen_fillmode[info->fillMode],
+ .ScissorRectangleEnable = !(extra && extra->disable_scissor),
+ .ViewportZClipTestEnable = info->depthClipEnable
+ };
+
+ GEN8_3DSTATE_RASTER_pack(NULL, pipeline->state_raster, &raster);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE,
+ .ForceVertexURBEntryReadLength = false,
+ .ForceVertexURBEntryReadOffset = false,
+ .PointSpriteTextureCoordinateOrigin = UPPERLEFT,
+ .NumberofSFOutputAttributes =
+ pipeline->wm_prog_data.num_varying_inputs);
+
+}
+
+static void
+emit_cb_state(struct anv_pipeline *pipeline,
+ const VkPipelineColorBlendStateCreateInfo *info)
+{
+ struct anv_device *device = pipeline->device;
+
+ static const uint32_t vk_to_gen_logic_op[] = {
+ [VK_LOGIC_OP_COPY] = LOGICOP_COPY,
+ [VK_LOGIC_OP_CLEAR] = LOGICOP_CLEAR,
+ [VK_LOGIC_OP_AND] = LOGICOP_AND,
+ [VK_LOGIC_OP_AND_REVERSE] = LOGICOP_AND_REVERSE,
+ [VK_LOGIC_OP_AND_INVERTED] = LOGICOP_AND_INVERTED,
+ [VK_LOGIC_OP_NOOP] = LOGICOP_NOOP,
+ [VK_LOGIC_OP_XOR] = LOGICOP_XOR,
+ [VK_LOGIC_OP_OR] = LOGICOP_OR,
+ [VK_LOGIC_OP_NOR] = LOGICOP_NOR,
+ [VK_LOGIC_OP_EQUIV] = LOGICOP_EQUIV,
+ [VK_LOGIC_OP_INVERT] = LOGICOP_INVERT,
+ [VK_LOGIC_OP_OR_REVERSE] = LOGICOP_OR_REVERSE,
+ [VK_LOGIC_OP_COPY_INVERTED] = LOGICOP_COPY_INVERTED,
+ [VK_LOGIC_OP_OR_INVERTED] = LOGICOP_OR_INVERTED,
+ [VK_LOGIC_OP_NAND] = LOGICOP_NAND,
+ [VK_LOGIC_OP_SET] = LOGICOP_SET,
+ };
+
+ static const uint32_t vk_to_gen_blend[] = {
+ [VK_BLEND_ZERO] = BLENDFACTOR_ZERO,
+ [VK_BLEND_ONE] = BLENDFACTOR_ONE,
+ [VK_BLEND_SRC_COLOR] = BLENDFACTOR_SRC_COLOR,
+ [VK_BLEND_ONE_MINUS_SRC_COLOR] = BLENDFACTOR_INV_SRC_COLOR,
+ [VK_BLEND_DEST_COLOR] = BLENDFACTOR_DST_COLOR,
+ [VK_BLEND_ONE_MINUS_DEST_COLOR] = BLENDFACTOR_INV_DST_COLOR,
+ [VK_BLEND_SRC_ALPHA] = BLENDFACTOR_SRC_ALPHA,
+ [VK_BLEND_ONE_MINUS_SRC_ALPHA] = BLENDFACTOR_INV_SRC_ALPHA,
+ [VK_BLEND_DEST_ALPHA] = BLENDFACTOR_DST_ALPHA,
+ [VK_BLEND_ONE_MINUS_DEST_ALPHA] = BLENDFACTOR_INV_DST_ALPHA,
+ [VK_BLEND_CONSTANT_COLOR] = BLENDFACTOR_CONST_COLOR,
+ [VK_BLEND_ONE_MINUS_CONSTANT_COLOR] = BLENDFACTOR_INV_CONST_COLOR,
+ [VK_BLEND_CONSTANT_ALPHA] = BLENDFACTOR_CONST_ALPHA,
+ [VK_BLEND_ONE_MINUS_CONSTANT_ALPHA] = BLENDFACTOR_INV_CONST_ALPHA,
+ [VK_BLEND_SRC_ALPHA_SATURATE] = BLENDFACTOR_SRC_ALPHA_SATURATE,
+ [VK_BLEND_SRC1_COLOR] = BLENDFACTOR_SRC1_COLOR,
+ [VK_BLEND_ONE_MINUS_SRC1_COLOR] = BLENDFACTOR_INV_SRC1_COLOR,
+ [VK_BLEND_SRC1_ALPHA] = BLENDFACTOR_SRC1_ALPHA,
+ [VK_BLEND_ONE_MINUS_SRC1_ALPHA] = BLENDFACTOR_INV_SRC1_ALPHA,
+ };
+
+ static const uint32_t vk_to_gen_blend_op[] = {
+ [VK_BLEND_OP_ADD] = BLENDFUNCTION_ADD,
+ [VK_BLEND_OP_SUBTRACT] = BLENDFUNCTION_SUBTRACT,
+ [VK_BLEND_OP_REVERSE_SUBTRACT] = BLENDFUNCTION_REVERSE_SUBTRACT,
+ [VK_BLEND_OP_MIN] = BLENDFUNCTION_MIN,
+ [VK_BLEND_OP_MAX] = BLENDFUNCTION_MAX,
+ };
+
+ uint32_t num_dwords = 1 + info->attachmentCount * 2;
+ pipeline->blend_state =
+ anv_state_pool_alloc(&device->dynamic_state_pool, num_dwords * 4, 64);
+
+ struct GEN8_BLEND_STATE blend_state = {
+ .AlphaToCoverageEnable = info->alphaToCoverageEnable,
+ };
+
+ uint32_t *state = pipeline->blend_state.map;
+ GEN8_BLEND_STATE_pack(NULL, state, &blend_state);
+
+ for (uint32_t i = 0; i < info->attachmentCount; i++) {
+ const VkPipelineColorBlendAttachmentState *a = &info->pAttachments[i];
+
+ struct GEN8_BLEND_STATE_ENTRY entry = {
+ .LogicOpEnable = info->logicOpEnable,
+ .LogicOpFunction = vk_to_gen_logic_op[info->logicOp],
+ .ColorBufferBlendEnable = a->blendEnable,
+ .PreBlendSourceOnlyClampEnable = false,
+ .PreBlendColorClampEnable = false,
+ .PostBlendColorClampEnable = false,
+ .SourceBlendFactor = vk_to_gen_blend[a->srcBlendColor],
+ .DestinationBlendFactor = vk_to_gen_blend[a->destBlendColor],
+ .ColorBlendFunction = vk_to_gen_blend_op[a->blendOpColor],
+ .SourceAlphaBlendFactor = vk_to_gen_blend[a->srcBlendAlpha],
+ .DestinationAlphaBlendFactor = vk_to_gen_blend[a->destBlendAlpha],
+ .AlphaBlendFunction = vk_to_gen_blend_op[a->blendOpAlpha],
+ .WriteDisableAlpha = !(a->channelWriteMask & VK_CHANNEL_A_BIT),
+ .WriteDisableRed = !(a->channelWriteMask & VK_CHANNEL_R_BIT),
+ .WriteDisableGreen = !(a->channelWriteMask & VK_CHANNEL_G_BIT),
+ .WriteDisableBlue = !(a->channelWriteMask & VK_CHANNEL_B_BIT),
+ };
+
+ GEN8_BLEND_STATE_ENTRY_pack(NULL, state + i * 2 + 1, &entry);
+ }
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_BLEND_STATE_POINTERS,
+ .BlendStatePointer = pipeline->blend_state.offset,
+ .BlendStatePointerValid = true);
+}
+
+static const uint32_t vk_to_gen_compare_op[] = {
+ [VK_COMPARE_OP_NEVER] = COMPAREFUNCTION_NEVER,
+ [VK_COMPARE_OP_LESS] = COMPAREFUNCTION_LESS,
+ [VK_COMPARE_OP_EQUAL] = COMPAREFUNCTION_EQUAL,
+ [VK_COMPARE_OP_LESS_EQUAL] = COMPAREFUNCTION_LEQUAL,
+ [VK_COMPARE_OP_GREATER] = COMPAREFUNCTION_GREATER,
+ [VK_COMPARE_OP_NOT_EQUAL] = COMPAREFUNCTION_NOTEQUAL,
+ [VK_COMPARE_OP_GREATER_EQUAL] = COMPAREFUNCTION_GEQUAL,
+ [VK_COMPARE_OP_ALWAYS] = COMPAREFUNCTION_ALWAYS,
+};
+
+static const uint32_t vk_to_gen_stencil_op[] = {
+ [VK_STENCIL_OP_KEEP] = 0,
+ [VK_STENCIL_OP_ZERO] = 0,
+ [VK_STENCIL_OP_REPLACE] = 0,
+ [VK_STENCIL_OP_INC_CLAMP] = 0,
+ [VK_STENCIL_OP_DEC_CLAMP] = 0,
+ [VK_STENCIL_OP_INVERT] = 0,
+ [VK_STENCIL_OP_INC_WRAP] = 0,
+ [VK_STENCIL_OP_DEC_WRAP] = 0
+};
+
+static void
+emit_ds_state(struct anv_pipeline *pipeline,
+ const VkPipelineDepthStencilStateCreateInfo *info)
+{
+ if (info == NULL) {
+ /* We're going to OR this together with the dynamic state. We need
+ * to make sure it's initialized to something useful.
+ */
+ memset(pipeline->state_wm_depth_stencil, 0,
+ sizeof(pipeline->state_wm_depth_stencil));
+ return;
+ }
+
+ /* VkBool32 depthBoundsEnable; // optional (depth_bounds_test) */
+
+ struct GEN8_3DSTATE_WM_DEPTH_STENCIL wm_depth_stencil = {
+ .DepthTestEnable = info->depthTestEnable,
+ .DepthBufferWriteEnable = info->depthWriteEnable,
+ .DepthTestFunction = vk_to_gen_compare_op[info->depthCompareOp],
+ .DoubleSidedStencilEnable = true,
+
+ .StencilTestEnable = info->stencilTestEnable,
+ .StencilFailOp = vk_to_gen_stencil_op[info->front.stencilFailOp],
+ .StencilPassDepthPassOp = vk_to_gen_stencil_op[info->front.stencilPassOp],
+ .StencilPassDepthFailOp = vk_to_gen_stencil_op[info->front.stencilDepthFailOp],
+ .StencilTestFunction = vk_to_gen_compare_op[info->front.stencilCompareOp],
+ .BackfaceStencilFailOp = vk_to_gen_stencil_op[info->back.stencilFailOp],
+ .BackfaceStencilPassDepthPassOp = vk_to_gen_stencil_op[info->back.stencilPassOp],
+ .BackfaceStencilPassDepthFailOp =vk_to_gen_stencil_op[info->back.stencilDepthFailOp],
+ .BackfaceStencilTestFunction = vk_to_gen_compare_op[info->back.stencilCompareOp],
+ };
+
+ GEN8_3DSTATE_WM_DEPTH_STENCIL_pack(NULL, pipeline->state_wm_depth_stencil, &wm_depth_stencil);
+}
+
+VkResult
+anv_pipeline_create(
+ VkDevice _device,
+ const VkGraphicsPipelineCreateInfo* pCreateInfo,
+ const struct anv_pipeline_create_info * extra,
+ VkPipeline* pPipeline)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_pipeline *pipeline;
+ VkResult result;
+ uint32_t offset, length;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
+
+ pipeline = anv_device_alloc(device, sizeof(*pipeline), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (pipeline == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ pipeline->device = device;
+ pipeline->layout = anv_pipeline_layout_from_handle(pCreateInfo->layout);
+ memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
+
+ result = anv_reloc_list_init(&pipeline->batch.relocs, device);
+ if (result != VK_SUCCESS) {
+ anv_device_free(device, pipeline);
+ return result;
+ }
+ pipeline->batch.next = pipeline->batch.start = pipeline->batch_data;
+ pipeline->batch.end = pipeline->batch.start + sizeof(pipeline->batch_data);
+
+ anv_state_stream_init(&pipeline->program_stream,
+ &device->instruction_block_pool);
+
+ for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
+ pipeline->shaders[pCreateInfo->pStages[i].stage] =
+ anv_shader_from_handle(pCreateInfo->pStages[i].shader);
+ }
+
+ if (pCreateInfo->pTessellationState)
+ anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO");
+ if (pCreateInfo->pViewportState)
+ anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO");
+ if (pCreateInfo->pMultisampleState)
+ anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO");
+
+ pipeline->use_repclear = extra && extra->use_repclear;
+
+ anv_compiler_run(device->compiler, pipeline);
+
+ /* FIXME: The compiler dead-codes FS inputs when we don't have a VS, so we
+ * hard code this to num_attributes - 2. This is because the attributes
+ * include VUE header and position, which aren't counted as varying
+ * inputs. */
+ if (pipeline->vs_simd8 == NO_KERNEL) {
+ pipeline->wm_prog_data.num_varying_inputs =
+ pCreateInfo->pVertexInputState->attributeCount - 2;
+ }
+
+ assert(pCreateInfo->pVertexInputState);
+ emit_vertex_input(pipeline, pCreateInfo->pVertexInputState);
+ assert(pCreateInfo->pInputAssemblyState);
+ emit_ia_state(pipeline, pCreateInfo->pInputAssemblyState, extra);
+ assert(pCreateInfo->pRasterState);
+ emit_rs_state(pipeline, pCreateInfo->pRasterState, extra);
+ emit_ds_state(pipeline, pCreateInfo->pDepthStencilState);
+ emit_cb_state(pipeline, pCreateInfo->pColorBlendState);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_STATISTICS,
+ .StatisticsEnable = true);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_HS, .Enable = false);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_TE, .TEEnable = false);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_DS, .FunctionEnable = false);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_STREAMOUT, .SOFunctionEnable = false);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_VS,
+ .ConstantBufferOffset = 0,
+ .ConstantBufferSize = 4);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_GS,
+ .ConstantBufferOffset = 4,
+ .ConstantBufferSize = 4);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_PS,
+ .ConstantBufferOffset = 8,
+ .ConstantBufferSize = 4);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_WM_CHROMAKEY,
+ .ChromaKeyKillEnable = false);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE_SWIZ);
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_AA_LINE_PARAMETERS);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_CLIP,
+ .ClipEnable = true,
+ .ViewportXYClipTestEnable = !(extra && extra->disable_viewport),
+ .MinimumPointWidth = 0.125,
+ .MaximumPointWidth = 255.875);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_WM,
+ .StatisticsEnable = true,
+ .LineEndCapAntialiasingRegionWidth = _05pixels,
+ .LineAntialiasingRegionWidth = _10pixels,
+ .EarlyDepthStencilControl = NORMAL,
+ .ForceThreadDispatchEnable = NORMAL,
+ .PointRasterizationRule = RASTRULE_UPPER_RIGHT,
+ .BarycentricInterpolationMode =
+ pipeline->wm_prog_data.barycentric_interp_modes);
+
+ uint32_t samples = 1;
+ uint32_t log2_samples = __builtin_ffs(samples) - 1;
+ bool enable_sampling = samples > 1 ? true : false;
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_MULTISAMPLE,
+ .PixelPositionOffsetEnable = enable_sampling,
+ .PixelLocation = CENTER,
+ .NumberofMultisamples = log2_samples);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SAMPLE_MASK,
+ .SampleMask = 0xffff);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_VS,
+ .VSURBStartingAddress = pipeline->urb.vs_start,
+ .VSURBEntryAllocationSize = pipeline->urb.vs_size - 1,
+ .VSNumberofURBEntries = pipeline->urb.nr_vs_entries);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_GS,
+ .GSURBStartingAddress = pipeline->urb.gs_start,
+ .GSURBEntryAllocationSize = pipeline->urb.gs_size - 1,
+ .GSNumberofURBEntries = pipeline->urb.nr_gs_entries);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_HS,
+ .HSURBStartingAddress = pipeline->urb.vs_start,
+ .HSURBEntryAllocationSize = 0,
+ .HSNumberofURBEntries = 0);
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_DS,
+ .DSURBStartingAddress = pipeline->urb.vs_start,
+ .DSURBEntryAllocationSize = 0,
+ .DSNumberofURBEntries = 0);
+
+ const struct brw_gs_prog_data *gs_prog_data = &pipeline->gs_prog_data;
+ offset = 1;
+ length = (gs_prog_data->base.vue_map.num_slots + 1) / 2 - offset;
+
+ if (pipeline->gs_vec4 == NO_KERNEL)
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_GS, .Enable = false);
+ else
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_GS,
+ .SingleProgramFlow = false,
+ .KernelStartPointer = pipeline->gs_vec4,
+ .VectorMaskEnable = Vmask,
+ .SamplerCount = 0,
+ .BindingTableEntryCount = 0,
+ .ExpectedVertexCount = pipeline->gs_vertex_count,
+
+ .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_GEOMETRY],
+ .PerThreadScratchSpace = ffs(gs_prog_data->base.base.total_scratch / 2048),
+
+ .OutputVertexSize = gs_prog_data->output_vertex_size_hwords * 2 - 1,
+ .OutputTopology = gs_prog_data->output_topology,
+ .VertexURBEntryReadLength = gs_prog_data->base.urb_read_length,
+ .DispatchGRFStartRegisterForURBData =
+ gs_prog_data->base.base.dispatch_grf_start_reg,
+
+ .MaximumNumberofThreads = device->info.max_gs_threads,
+ .ControlDataHeaderSize = gs_prog_data->control_data_header_size_hwords,
+ //pipeline->gs_prog_data.dispatch_mode |
+ .StatisticsEnable = true,
+ .IncludePrimitiveID = gs_prog_data->include_primitive_id,
+ .ReorderMode = TRAILING,
+ .Enable = true,
+
+ .ControlDataFormat = gs_prog_data->control_data_format,
+
+ /* FIXME: mesa sets this based on ctx->Transform.ClipPlanesEnabled:
+ * UserClipDistanceClipTestEnableBitmask_3DSTATE_GS(v)
+ * UserClipDistanceCullTestEnableBitmask(v)
+ */
+
+ .VertexURBEntryOutputReadOffset = offset,
+ .VertexURBEntryOutputLength = length);
+
+ const struct brw_vue_prog_data *vue_prog_data = &pipeline->vs_prog_data.base;
+ /* Skip the VUE header and position slots */
+ offset = 1;
+ length = (vue_prog_data->vue_map.num_slots + 1) / 2 - offset;
+
+ if (pipeline->vs_simd8 == NO_KERNEL || (extra && extra->disable_vs))
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
+ .FunctionEnable = false,
+ .VertexURBEntryOutputReadOffset = 1,
+ /* Even if VS is disabled, SBE still gets the amount of
+ * vertex data to read from this field. We use attribute
+ * count - 1, as we don't count the VUE header here. */
+ .VertexURBEntryOutputLength =
+ DIV_ROUND_UP(pCreateInfo->pVertexInputState->attributeCount - 1, 2));
+ else
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
+ .KernelStartPointer = pipeline->vs_simd8,
+ .SingleVertexDispatch = Multiple,
+ .VectorMaskEnable = Dmask,
+ .SamplerCount = 0,
+ .BindingTableEntryCount =
+ vue_prog_data->base.binding_table.size_bytes / 4,
+ .ThreadDispatchPriority = Normal,
+ .FloatingPointMode = IEEE754,
+ .IllegalOpcodeExceptionEnable = false,
+ .AccessesUAV = false,
+ .SoftwareExceptionEnable = false,
+
+ .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_VERTEX],
+ .PerThreadScratchSpace = ffs(vue_prog_data->base.total_scratch / 2048),
+
+ .DispatchGRFStartRegisterForURBData =
+ vue_prog_data->base.dispatch_grf_start_reg,
+ .VertexURBEntryReadLength = vue_prog_data->urb_read_length,
+ .VertexURBEntryReadOffset = 0,
+
+ .MaximumNumberofThreads = device->info.max_vs_threads - 1,
+ .StatisticsEnable = false,
+ .SIMD8DispatchEnable = true,
+ .VertexCacheDisable = false,
+ .FunctionEnable = true,
+
+ .VertexURBEntryOutputReadOffset = offset,
+ .VertexURBEntryOutputLength = length,
+ .UserClipDistanceClipTestEnableBitmask = 0,
+ .UserClipDistanceCullTestEnableBitmask = 0);
+
+ const struct brw_wm_prog_data *wm_prog_data = &pipeline->wm_prog_data;
+ uint32_t ksp0, ksp2, grf_start0, grf_start2;
+
+ ksp2 = 0;
+ grf_start2 = 0;
+ if (pipeline->ps_simd8 != NO_KERNEL) {
+ ksp0 = pipeline->ps_simd8;
+ grf_start0 = wm_prog_data->base.dispatch_grf_start_reg;
+ if (pipeline->ps_simd16 != NO_KERNEL) {
+ ksp2 = pipeline->ps_simd16;
+ grf_start2 = wm_prog_data->dispatch_grf_start_reg_16;
+ }
+ } else if (pipeline->ps_simd16 != NO_KERNEL) {
+ ksp0 = pipeline->ps_simd16;
+ grf_start0 = wm_prog_data->dispatch_grf_start_reg_16;
+ } else {
+ unreachable("no ps shader");
+ }
+
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PS,
+ .KernelStartPointer0 = ksp0,
+
+ .SingleProgramFlow = false,
+ .VectorMaskEnable = true,
+ .SamplerCount = 1,
+
+ .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
+ .PerThreadScratchSpace = ffs(wm_prog_data->base.total_scratch / 2048),
+
+ .MaximumNumberofThreadsPerPSD = 64 - 2,
+ .PositionXYOffsetSelect = wm_prog_data->uses_pos_offset ?
+ POSOFFSET_SAMPLE: POSOFFSET_NONE,
+ .PushConstantEnable = wm_prog_data->base.nr_params > 0,
+ ._8PixelDispatchEnable = pipeline->ps_simd8 != NO_KERNEL,
+ ._16PixelDispatchEnable = pipeline->ps_simd16 != NO_KERNEL,
+ ._32PixelDispatchEnable = false,
+
+ .DispatchGRFStartRegisterForConstantSetupData0 = grf_start0,
+ .DispatchGRFStartRegisterForConstantSetupData1 = 0,
+ .DispatchGRFStartRegisterForConstantSetupData2 = grf_start2,
+
+ .KernelStartPointer1 = 0,
+ .KernelStartPointer2 = ksp2);
+
+ bool per_sample_ps = false;
+ anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PS_EXTRA,
+ .PixelShaderValid = true,
+ .PixelShaderKillsPixel = wm_prog_data->uses_kill,
+ .PixelShaderComputedDepthMode = wm_prog_data->computed_depth_mode,
+ .AttributeEnable = wm_prog_data->num_varying_inputs > 0,
+ .oMaskPresenttoRenderTarget = wm_prog_data->uses_omask,
+ .PixelShaderIsPerSample = per_sample_ps);
+
+ *pPipeline = anv_pipeline_to_handle(pipeline);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyPipeline(
+ VkDevice _device,
+ VkPipeline _pipeline)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_pipeline, pipeline, _pipeline);
+
+ anv_compiler_free(pipeline);
+ anv_reloc_list_finish(&pipeline->batch.relocs, pipeline->device);
+ anv_state_stream_finish(&pipeline->program_stream);
+ anv_state_pool_free(&device->dynamic_state_pool, pipeline->blend_state);
+ anv_device_free(pipeline->device, pipeline);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_CreateGraphicsPipelines(
+ VkDevice _device,
+ VkPipelineCache pipelineCache,
+ uint32_t count,
+ const VkGraphicsPipelineCreateInfo* pCreateInfos,
+ VkPipeline* pPipelines)
+{
+ VkResult result = VK_SUCCESS;
+
+ unsigned i = 0;
+ for (; i < count; i++) {
+ result = anv_pipeline_create(_device, &pCreateInfos[i],
+ NULL, &pPipelines[i]);
+ if (result != VK_SUCCESS) {
+ for (unsigned j = 0; j < i; j++) {
+ anv_DestroyPipeline(_device, pPipelines[j]);
+ }
+
+ return result;
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+static VkResult anv_compute_pipeline_create(
+ VkDevice _device,
+ const VkComputePipelineCreateInfo* pCreateInfo,
+ VkPipeline* pPipeline)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_pipeline *pipeline;
+ VkResult result;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO);
+
+ pipeline = anv_device_alloc(device, sizeof(*pipeline), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (pipeline == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ pipeline->device = device;
+ pipeline->layout = anv_pipeline_layout_from_handle(pCreateInfo->layout);
+
+ result = anv_reloc_list_init(&pipeline->batch.relocs, device);
+ if (result != VK_SUCCESS) {
+ anv_device_free(device, pipeline);
+ return result;
+ }
+ pipeline->batch.next = pipeline->batch.start = pipeline->batch_data;
+ pipeline->batch.end = pipeline->batch.start + sizeof(pipeline->batch_data);
+
+ anv_state_stream_init(&pipeline->program_stream,
+ &device->instruction_block_pool);
+
+ memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
+
+ pipeline->shaders[VK_SHADER_STAGE_COMPUTE] =
+ anv_shader_from_handle(pCreateInfo->cs.shader);
+
+ pipeline->use_repclear = false;
+
+ anv_compiler_run(device->compiler, pipeline);
+
+ const struct brw_cs_prog_data *cs_prog_data = &pipeline->cs_prog_data;
+
+ anv_batch_emit(&pipeline->batch, GEN8_MEDIA_VFE_STATE,
+ .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
+ .PerThreadScratchSpace = ffs(cs_prog_data->base.total_scratch / 2048),
+ .ScratchSpaceBasePointerHigh = 0,
+ .StackSize = 0,
+
+ .MaximumNumberofThreads = device->info.max_cs_threads - 1,
+ .NumberofURBEntries = 2,
+ .ResetGatewayTimer = true,
+ .BypassGatewayControl = true,
+ .URBEntryAllocationSize = 2,
+ .CURBEAllocationSize = 0);
+
+ struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
+ uint32_t group_size = prog_data->local_size[0] *
+ prog_data->local_size[1] * prog_data->local_size[2];
+ pipeline->cs_thread_width_max = DIV_ROUND_UP(group_size, prog_data->simd_size);
+ uint32_t remainder = group_size & (prog_data->simd_size - 1);
+
+ if (remainder > 0)
+ pipeline->cs_right_mask = ~0u >> (32 - remainder);
+ else
+ pipeline->cs_right_mask = ~0u >> (32 - prog_data->simd_size);
+
+
+ *pPipeline = anv_pipeline_to_handle(pipeline);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_CreateComputePipelines(
+ VkDevice _device,
+ VkPipelineCache pipelineCache,
+ uint32_t count,
+ const VkComputePipelineCreateInfo* pCreateInfos,
+ VkPipeline* pPipelines)
+{
+ VkResult result = VK_SUCCESS;
+
+ unsigned i = 0;
+ for (; i < count; i++) {
+ result = anv_compute_pipeline_create(_device, &pCreateInfos[i],
+ &pPipelines[i]);
+ if (result != VK_SUCCESS) {
+ for (unsigned j = 0; j < i; j++) {
+ anv_DestroyPipeline(_device, pPipelines[j]);
+ }
+
+ return result;
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+// Pipeline layout functions
+
+VkResult anv_CreatePipelineLayout(
+ VkDevice _device,
+ const VkPipelineLayoutCreateInfo* pCreateInfo,
+ VkPipelineLayout* pPipelineLayout)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_pipeline_layout *layout;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
+
+ layout = anv_device_alloc(device, sizeof(*layout), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (layout == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ layout->num_sets = pCreateInfo->descriptorSetCount;
+
+ uint32_t surface_start[VK_SHADER_STAGE_NUM] = { 0, };
+ uint32_t sampler_start[VK_SHADER_STAGE_NUM] = { 0, };
+
+ for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
+ layout->stage[s].surface_count = 0;
+ layout->stage[s].sampler_count = 0;
+ }
+
+ for (uint32_t i = 0; i < pCreateInfo->descriptorSetCount; i++) {
+ ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout,
+ pCreateInfo->pSetLayouts[i]);
+
+ layout->set[i].layout = set_layout;
+ for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
+ layout->set[i].surface_start[s] = surface_start[s];
+ surface_start[s] += set_layout->stage[s].surface_count;
+ layout->set[i].sampler_start[s] = sampler_start[s];
+ sampler_start[s] += set_layout->stage[s].sampler_count;
+
+ layout->stage[s].surface_count += set_layout->stage[s].surface_count;
+ layout->stage[s].sampler_count += set_layout->stage[s].sampler_count;
+ }
+ }
+
+ *pPipelineLayout = anv_pipeline_layout_to_handle(layout);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_DestroyPipelineLayout(
+ VkDevice _device,
+ VkPipelineLayout _pipelineLayout)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_pipeline_layout, pipeline_layout, _pipelineLayout);
+
+ anv_device_free(device, pipeline_layout);
+
+ return VK_SUCCESS;
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <pthread.h>
+#include <assert.h>
+#include <i915_drm.h>
+
+#ifdef HAVE_VALGRIND
+#include <valgrind.h>
+#include <memcheck.h>
+#define VG(x) x
+#define __gen_validate_value(x) VALGRIND_CHECK_MEM_IS_DEFINED(&(x), sizeof(x))
+#else
+#define VG(x)
+#endif
+
+#include "brw_device_info.h"
+#include "util/macros.h"
+
+#define VK_PROTOTYPES
+#include <vulkan/vulkan.h>
+#include <vulkan/vulkan_intel.h>
+#include <vulkan/vk_wsi_lunarg.h>
+
+#include "anv_entrypoints.h"
+
+#include "brw_context.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define anv_noreturn __attribute__((__noreturn__))
+#define anv_printflike(a, b) __attribute__((__format__(__printf__, a, b)))
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+static inline uint32_t
+align_u32(uint32_t v, uint32_t a)
+{
+ return (v + a - 1) & ~(a - 1);
+}
+
+static inline int32_t
+align_i32(int32_t v, int32_t a)
+{
+ return (v + a - 1) & ~(a - 1);
+}
+
+/** Alignment must be a power of 2. */
+static inline bool
+anv_is_aligned(uintmax_t n, uintmax_t a)
+{
+ assert(a == (a & -a));
+ return (n & (a - 1)) == 0;
+}
+
+static inline uint32_t
+anv_minify(uint32_t n, uint32_t levels)
+{
+ if (unlikely(n == 0))
+ return 0;
+ else
+ return MAX(n >> levels, 1);
+}
+
+static inline bool
+anv_clear_mask(uint32_t *inout_mask, uint32_t clear_mask)
+{
+ if (*inout_mask & clear_mask) {
+ *inout_mask &= ~clear_mask;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+#define for_each_bit(b, dword) \
+ for (uint32_t __dword = (dword); \
+ (b) = __builtin_ffs(__dword) - 1, __dword; \
+ __dword &= ~(1 << (b)))
+
+/* Define no kernel as 1, since that's an illegal offset for a kernel */
+#define NO_KERNEL 1
+
+struct anv_common {
+ VkStructureType sType;
+ const void* pNext;
+};
+
+/* Whenever we generate an error, pass it through this function. Useful for
+ * debugging, where we can break on it. Only call at error site, not when
+ * propagating errors. Might be useful to plug in a stack trace here.
+ */
+
+static inline VkResult
+vk_error(VkResult error)
+{
+#ifdef DEBUG
+ fprintf(stderr, "vk_error: %x\n", error);
+#endif
+
+ return error;
+}
+
+void __anv_finishme(const char *file, int line, const char *format, ...)
+ anv_printflike(3, 4);
+void anv_loge(const char *format, ...) anv_printflike(1, 2);
+void anv_loge_v(const char *format, va_list va);
+
+/**
+ * Print a FINISHME message, including its source location.
+ */
+#define anv_finishme(format, ...) \
+ __anv_finishme(__FILE__, __LINE__, format, ##__VA_ARGS__);
+
+/* A non-fatal assert. Useful for debugging. */
+#ifdef DEBUG
+#define anv_assert(x) ({ \
+ if (unlikely(!(x))) \
+ fprintf(stderr, "%s:%d ASSERT: %s\n", __FILE__, __LINE__, #x); \
+})
+#else
+#define anv_assert(x)
+#endif
+
+void anv_abortf(const char *format, ...) anv_noreturn anv_printflike(1, 2);
+void anv_abortfv(const char *format, va_list va) anv_noreturn;
+
+#define stub_return(v) \
+ do { \
+ anv_finishme("stub %s", __func__); \
+ return (v); \
+ } while (0)
+
+#define stub() \
+ do { \
+ anv_finishme("stub %s", __func__); \
+ return; \
+ } while (0)
+
+/**
+ * A dynamically growable, circular buffer. Elements are added at head and
+ * removed from tail. head and tail are free-running uint32_t indices and we
+ * only compute the modulo with size when accessing the array. This way,
+ * number of bytes in the queue is always head - tail, even in case of
+ * wraparound.
+ */
+
+struct anv_vector {
+ uint32_t head;
+ uint32_t tail;
+ uint32_t element_size;
+ uint32_t size;
+ void *data;
+};
+
+int anv_vector_init(struct anv_vector *queue, uint32_t element_size, uint32_t size);
+void *anv_vector_add(struct anv_vector *queue);
+void *anv_vector_remove(struct anv_vector *queue);
+
+static inline int
+anv_vector_length(struct anv_vector *queue)
+{
+ return (queue->head - queue->tail) / queue->element_size;
+}
+
+static inline void
+anv_vector_finish(struct anv_vector *queue)
+{
+ free(queue->data);
+}
+
+#define anv_vector_foreach(elem, queue) \
+ static_assert(__builtin_types_compatible_p(__typeof__(queue), struct anv_vector *), ""); \
+ for (uint32_t __anv_vector_offset = (queue)->tail; \
+ elem = (queue)->data + (__anv_vector_offset & ((queue)->size - 1)), __anv_vector_offset < (queue)->head; \
+ __anv_vector_offset += (queue)->element_size)
+
+struct anv_bo {
+ int gem_handle;
+ uint32_t index;
+ uint64_t offset;
+ uint64_t size;
+
+ /* This field is here for the benefit of the aub dumper. It can (and for
+ * userptr bos it must) be set to the cpu map of the buffer. Destroying
+ * the bo won't clean up the mmap, it's still the responsibility of the bo
+ * user to do that. */
+ void *map;
+};
+
+/* Represents a lock-free linked list of "free" things. This is used by
+ * both the block pool and the state pools. Unfortunately, in order to
+ * solve the ABA problem, we can't use a single uint32_t head.
+ */
+union anv_free_list {
+ struct {
+ uint32_t offset;
+
+ /* A simple count that is incremented every time the head changes. */
+ uint32_t count;
+ };
+ uint64_t u64;
+};
+
+#define ANV_FREE_LIST_EMPTY ((union anv_free_list) { { 1, 0 } })
+
+struct anv_block_pool {
+ struct anv_device *device;
+
+ struct anv_bo bo;
+ void *map;
+ int fd;
+ uint32_t size;
+
+ /**
+ * Array of mmaps and gem handles owned by the block pool, reclaimed when
+ * the block pool is destroyed.
+ */
+ struct anv_vector mmap_cleanups;
+
+ uint32_t block_size;
+
+ uint32_t next_block;
+ union anv_free_list free_list;
+};
+
+struct anv_block_state {
+ union {
+ struct {
+ uint32_t next;
+ uint32_t end;
+ };
+ uint64_t u64;
+ };
+};
+
+struct anv_state {
+ uint32_t offset;
+ uint32_t alloc_size;
+ void *map;
+};
+
+struct anv_fixed_size_state_pool {
+ size_t state_size;
+ union anv_free_list free_list;
+ struct anv_block_state block;
+};
+
+#define ANV_MIN_STATE_SIZE_LOG2 6
+#define ANV_MAX_STATE_SIZE_LOG2 10
+
+#define ANV_STATE_BUCKETS (ANV_MAX_STATE_SIZE_LOG2 - ANV_MIN_STATE_SIZE_LOG2)
+
+struct anv_state_pool {
+ struct anv_block_pool *block_pool;
+ struct anv_fixed_size_state_pool buckets[ANV_STATE_BUCKETS];
+};
+
+struct anv_state_stream {
+ struct anv_block_pool *block_pool;
+ uint32_t next;
+ uint32_t current_block;
+ uint32_t end;
+};
+
+void anv_block_pool_init(struct anv_block_pool *pool,
+ struct anv_device *device, uint32_t block_size);
+void anv_block_pool_finish(struct anv_block_pool *pool);
+uint32_t anv_block_pool_alloc(struct anv_block_pool *pool);
+void anv_block_pool_free(struct anv_block_pool *pool, uint32_t offset);
+void anv_state_pool_init(struct anv_state_pool *pool,
+ struct anv_block_pool *block_pool);
+struct anv_state anv_state_pool_alloc(struct anv_state_pool *pool,
+ size_t state_size, size_t alignment);
+void anv_state_pool_free(struct anv_state_pool *pool, struct anv_state state);
+void anv_state_stream_init(struct anv_state_stream *stream,
+ struct anv_block_pool *block_pool);
+void anv_state_stream_finish(struct anv_state_stream *stream);
+struct anv_state anv_state_stream_alloc(struct anv_state_stream *stream,
+ uint32_t size, uint32_t alignment);
+
+/**
+ * Implements a pool of re-usable BOs. The interface is identical to that
+ * of block_pool except that each block is its own BO.
+ */
+struct anv_bo_pool {
+ struct anv_device *device;
+
+ uint32_t bo_size;
+
+ void *free_list;
+};
+
+void anv_bo_pool_init(struct anv_bo_pool *pool,
+ struct anv_device *device, uint32_t block_size);
+void anv_bo_pool_finish(struct anv_bo_pool *pool);
+VkResult anv_bo_pool_alloc(struct anv_bo_pool *pool, struct anv_bo *bo);
+void anv_bo_pool_free(struct anv_bo_pool *pool, const struct anv_bo *bo);
+
+struct anv_physical_device {
+ struct anv_instance * instance;
+ uint32_t chipset_id;
+ bool no_hw;
+ const char * path;
+ const char * name;
+ const struct brw_device_info * info;
+ int fd;
+};
+
+struct anv_instance {
+ void * pAllocUserData;
+ PFN_vkAllocFunction pfnAlloc;
+ PFN_vkFreeFunction pfnFree;
+ uint32_t apiVersion;
+ uint32_t physicalDeviceCount;
+ struct anv_physical_device physicalDevice;
+};
+
+struct anv_meta_state {
+ struct {
+ VkPipeline pipeline;
+ } clear;
+
+ struct {
+ VkPipeline pipeline;
+ VkPipelineLayout pipeline_layout;
+ VkDescriptorSetLayout ds_layout;
+ } blit;
+
+ struct {
+ VkDynamicRasterState rs_state;
+ VkDynamicColorBlendState cb_state;
+ VkDynamicDepthStencilState ds_state;
+ } shared;
+};
+
+struct anv_queue {
+ struct anv_device * device;
+
+ struct anv_state_pool * pool;
+
+ /**
+ * Serial number of the most recently completed batch executed on the
+ * engine.
+ */
+ struct anv_state completed_serial;
+
+ /**
+ * The next batch submitted to the engine will be assigned this serial
+ * number.
+ */
+ uint32_t next_serial;
+
+ uint32_t last_collected_serial;
+};
+
+struct anv_device {
+ struct anv_instance * instance;
+ uint32_t chipset_id;
+ struct brw_device_info info;
+ int context_id;
+ int fd;
+ bool no_hw;
+ bool dump_aub;
+
+ struct anv_bo_pool batch_bo_pool;
+
+ struct anv_block_pool dynamic_state_block_pool;
+ struct anv_state_pool dynamic_state_pool;
+
+ struct anv_block_pool instruction_block_pool;
+ struct anv_block_pool surface_state_block_pool;
+ struct anv_state_pool surface_state_pool;
+
+ struct anv_meta_state meta_state;
+
+ struct anv_state border_colors;
+
+ struct anv_queue queue;
+
+ struct anv_block_pool scratch_block_pool;
+
+ struct anv_compiler * compiler;
+ struct anv_aub_writer * aub_writer;
+ pthread_mutex_t mutex;
+};
+
+void *
+anv_device_alloc(struct anv_device * device,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocType allocType);
+
+void
+anv_device_free(struct anv_device * device,
+ void * mem);
+
+void* anv_gem_mmap(struct anv_device *device,
+ uint32_t gem_handle, uint64_t offset, uint64_t size);
+void anv_gem_munmap(void *p, uint64_t size);
+uint32_t anv_gem_create(struct anv_device *device, size_t size);
+void anv_gem_close(struct anv_device *device, int gem_handle);
+int anv_gem_userptr(struct anv_device *device, void *mem, size_t size);
+int anv_gem_wait(struct anv_device *device, int gem_handle, int64_t *timeout_ns);
+int anv_gem_execbuffer(struct anv_device *device,
+ struct drm_i915_gem_execbuffer2 *execbuf);
+int anv_gem_set_tiling(struct anv_device *device, int gem_handle,
+ uint32_t stride, uint32_t tiling);
+int anv_gem_create_context(struct anv_device *device);
+int anv_gem_destroy_context(struct anv_device *device, int context);
+int anv_gem_get_param(int fd, uint32_t param);
+int anv_gem_get_aperture(struct anv_physical_device *physical_dev, uint64_t *size);
+int anv_gem_handle_to_fd(struct anv_device *device, int gem_handle);
+int anv_gem_fd_to_handle(struct anv_device *device, int fd);
+int anv_gem_userptr(struct anv_device *device, void *mem, size_t size);
+
+VkResult anv_bo_init_new(struct anv_bo *bo, struct anv_device *device, uint64_t size);
+
+struct anv_reloc_list {
+ size_t num_relocs;
+ size_t array_length;
+ struct drm_i915_gem_relocation_entry * relocs;
+ struct anv_bo ** reloc_bos;
+};
+
+VkResult anv_reloc_list_init(struct anv_reloc_list *list,
+ struct anv_device *device);
+void anv_reloc_list_finish(struct anv_reloc_list *list,
+ struct anv_device *device);
+
+uint64_t anv_reloc_list_add(struct anv_reloc_list *list,
+ struct anv_device *device,
+ uint32_t offset, struct anv_bo *target_bo,
+ uint32_t delta);
+
+struct anv_batch_bo {
+ struct anv_bo bo;
+
+ /* Bytes actually consumed in this batch BO */
+ size_t length;
+
+ /* These offsets reference the per-batch reloc list */
+ size_t first_reloc;
+ size_t num_relocs;
+
+ struct anv_batch_bo * prev_batch_bo;
+};
+
+struct anv_batch {
+ struct anv_device * device;
+
+ void * start;
+ void * end;
+ void * next;
+
+ struct anv_reloc_list relocs;
+
+ /* This callback is called (with the associated user data) in the event
+ * that the batch runs out of space.
+ */
+ VkResult (*extend_cb)(struct anv_batch *, void *);
+ void * user_data;
+};
+
+void *anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords);
+void anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other);
+uint64_t anv_batch_emit_reloc(struct anv_batch *batch,
+ void *location, struct anv_bo *bo, uint32_t offset);
+
+struct anv_address {
+ struct anv_bo *bo;
+ uint32_t offset;
+};
+
+#define __gen_address_type struct anv_address
+#define __gen_user_data struct anv_batch
+
+static inline uint64_t
+__gen_combine_address(struct anv_batch *batch, void *location,
+ const struct anv_address address, uint32_t delta)
+{
+ if (address.bo == NULL) {
+ return delta;
+ } else {
+ assert(batch->start <= location && location < batch->end);
+
+ return anv_batch_emit_reloc(batch, location, address.bo, address.offset + delta);
+ }
+}
+
+#include "gen7_pack.h"
+#include "gen75_pack.h"
+#undef GEN8_3DSTATE_MULTISAMPLE
+#include "gen8_pack.h"
+
+#define anv_batch_emit(batch, cmd, ...) do { \
+ struct cmd __template = { \
+ cmd ## _header, \
+ __VA_ARGS__ \
+ }; \
+ void *__dst = anv_batch_emit_dwords(batch, cmd ## _length); \
+ cmd ## _pack(batch, __dst, &__template); \
+ } while (0)
+
+#define anv_batch_emitn(batch, n, cmd, ...) ({ \
+ struct cmd __template = { \
+ cmd ## _header, \
+ .DwordLength = n - cmd ## _length_bias, \
+ __VA_ARGS__ \
+ }; \
+ void *__dst = anv_batch_emit_dwords(batch, n); \
+ cmd ## _pack(batch, __dst, &__template); \
+ __dst; \
+ })
+
+#define anv_batch_emit_merge(batch, dwords0, dwords1) \
+ do { \
+ uint32_t *dw; \
+ \
+ assert(ARRAY_SIZE(dwords0) == ARRAY_SIZE(dwords1)); \
+ dw = anv_batch_emit_dwords((batch), ARRAY_SIZE(dwords0)); \
+ for (uint32_t i = 0; i < ARRAY_SIZE(dwords0); i++) \
+ dw[i] = (dwords0)[i] | (dwords1)[i]; \
+ VG(VALGRIND_CHECK_MEM_IS_DEFINED(dw, ARRAY_SIZE(dwords0) * 4));\
+ } while (0)
+
+#define GEN8_MOCS { \
+ .MemoryTypeLLCeLLCCacheabilityControl = WB, \
+ .TargetCache = L3DefertoPATforLLCeLLCselection, \
+ .AgeforQUADLRU = 0 \
+ }
+
+struct anv_device_memory {
+ struct anv_bo bo;
+ VkDeviceSize map_size;
+ void * map;
+};
+
+struct anv_dynamic_vp_state {
+ struct anv_state sf_clip_vp;
+ struct anv_state cc_vp;
+ struct anv_state scissor;
+};
+
+struct anv_dynamic_rs_state {
+ uint32_t state_sf[GEN8_3DSTATE_SF_length];
+ uint32_t state_raster[GEN8_3DSTATE_RASTER_length];
+};
+
+struct anv_dynamic_ds_state {
+ uint32_t state_wm_depth_stencil[GEN8_3DSTATE_WM_DEPTH_STENCIL_length];
+ uint32_t state_color_calc[GEN8_COLOR_CALC_STATE_length];
+};
+
+struct anv_dynamic_cb_state {
+ uint32_t state_color_calc[GEN8_COLOR_CALC_STATE_length];
+
+};
+
+struct anv_descriptor_slot {
+ int8_t dynamic_slot;
+ uint8_t index;
+};
+
+struct anv_descriptor_set_layout {
+ struct {
+ uint32_t surface_count;
+ struct anv_descriptor_slot *surface_start;
+ uint32_t sampler_count;
+ struct anv_descriptor_slot *sampler_start;
+ } stage[VK_SHADER_STAGE_NUM];
+
+ uint32_t count;
+ uint32_t num_dynamic_buffers;
+ uint32_t shader_stages;
+ struct anv_descriptor_slot entries[0];
+};
+
+struct anv_descriptor {
+ struct anv_sampler *sampler;
+ struct anv_surface_view *view;
+};
+
+struct anv_descriptor_set {
+ struct anv_descriptor descriptors[0];
+};
+
+VkResult
+anv_descriptor_set_create(struct anv_device *device,
+ const struct anv_descriptor_set_layout *layout,
+ struct anv_descriptor_set **out_set);
+
+void
+anv_descriptor_set_destroy(struct anv_device *device,
+ struct anv_descriptor_set *set);
+
+#define MAX_VBS 32
+#define MAX_SETS 8
+#define MAX_RTS 8
+
+struct anv_pipeline_layout {
+ struct {
+ struct anv_descriptor_set_layout *layout;
+ uint32_t surface_start[VK_SHADER_STAGE_NUM];
+ uint32_t sampler_start[VK_SHADER_STAGE_NUM];
+ } set[MAX_SETS];
+
+ uint32_t num_sets;
+
+ struct {
+ uint32_t surface_count;
+ uint32_t sampler_count;
+ } stage[VK_SHADER_STAGE_NUM];
+};
+
+struct anv_buffer {
+ struct anv_device * device;
+ VkDeviceSize size;
+
+ /* Set when bound */
+ struct anv_bo * bo;
+ VkDeviceSize offset;
+};
+
+#define ANV_CMD_BUFFER_PIPELINE_DIRTY (1 << 0)
+#define ANV_CMD_BUFFER_RS_DIRTY (1 << 2)
+#define ANV_CMD_BUFFER_DS_DIRTY (1 << 3)
+#define ANV_CMD_BUFFER_CB_DIRTY (1 << 4)
+#define ANV_CMD_BUFFER_VP_DIRTY (1 << 5)
+#define ANV_CMD_BUFFER_INDEX_BUFFER_DIRTY (1 << 6)
+
+struct anv_vertex_binding {
+ struct anv_buffer * buffer;
+ VkDeviceSize offset;
+};
+
+struct anv_descriptor_set_binding {
+ struct anv_descriptor_set * set;
+ uint32_t dynamic_offsets[128];
+};
+
+/** State required while building cmd buffer */
+struct anv_cmd_state {
+ uint32_t current_pipeline;
+ uint32_t vb_dirty;
+ uint32_t dirty;
+ uint32_t compute_dirty;
+ uint32_t descriptors_dirty;
+ uint32_t scratch_size;
+ struct anv_pipeline * pipeline;
+ struct anv_pipeline * compute_pipeline;
+ struct anv_framebuffer * framebuffer;
+ struct anv_render_pass * pass;
+ struct anv_subpass * subpass;
+ struct anv_dynamic_rs_state * rs_state;
+ struct anv_dynamic_ds_state * ds_state;
+ struct anv_dynamic_vp_state * vp_state;
+ struct anv_dynamic_cb_state * cb_state;
+ uint32_t state_vf[GEN8_3DSTATE_VF_length];
+ struct anv_vertex_binding vertex_bindings[MAX_VBS];
+ struct anv_descriptor_set_binding descriptors[MAX_SETS];
+};
+
+VkResult anv_cmd_state_init(struct anv_cmd_state *state);
+void anv_cmd_state_fini(struct anv_cmd_state *state);
+
+struct anv_cmd_buffer {
+ struct anv_device * device;
+
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 * exec2_objects;
+ uint32_t exec2_bo_count;
+ struct anv_bo ** exec2_bos;
+ uint32_t exec2_array_length;
+ bool need_reloc;
+ uint32_t serial;
+
+ struct anv_batch batch;
+ struct anv_batch_bo * last_batch_bo;
+ struct anv_batch_bo * surface_batch_bo;
+ uint32_t surface_next;
+ struct anv_reloc_list surface_relocs;
+ struct anv_state_stream surface_state_stream;
+ struct anv_state_stream dynamic_state_stream;
+
+ struct anv_cmd_state state;
+};
+
+struct anv_state
+anv_cmd_buffer_alloc_surface_state(struct anv_cmd_buffer *cmd_buffer,
+ uint32_t size, uint32_t alignment);
+struct anv_state
+anv_cmd_buffer_alloc_dynamic_state(struct anv_cmd_buffer *cmd_buffer,
+ uint32_t size, uint32_t alignment);
+
+VkResult anv_cmd_buffer_new_surface_state_bo(struct anv_cmd_buffer *cmd_buffer);
+
+void anv_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer);
+
+void anv_cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
+ struct anv_subpass *subpass);
+
+void anv_cmd_buffer_clear_attachments(struct anv_cmd_buffer *cmd_buffer,
+ struct anv_render_pass *pass,
+ const VkClearValue *clear_values);
+
+void anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer);
+void anv_aub_writer_destroy(struct anv_aub_writer *writer);
+
+struct anv_fence {
+ struct anv_bo bo;
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 exec2_objects[1];
+ bool ready;
+};
+
+struct anv_shader_module {
+ uint32_t size;
+ char data[0];
+};
+
+struct anv_shader {
+ struct anv_shader_module * module;
+ char entrypoint[0];
+};
+
+struct anv_pipeline {
+ struct anv_device * device;
+ struct anv_batch batch;
+ uint32_t batch_data[256];
+ struct anv_shader * shaders[VK_SHADER_STAGE_NUM];
+ struct anv_pipeline_layout * layout;
+ bool use_repclear;
+
+ struct brw_vs_prog_data vs_prog_data;
+ struct brw_wm_prog_data wm_prog_data;
+ struct brw_gs_prog_data gs_prog_data;
+ struct brw_cs_prog_data cs_prog_data;
+ bool writes_point_size;
+ struct brw_stage_prog_data * prog_data[VK_SHADER_STAGE_NUM];
+ uint32_t scratch_start[VK_SHADER_STAGE_NUM];
+ uint32_t total_scratch;
+ struct {
+ uint32_t vs_start;
+ uint32_t vs_size;
+ uint32_t nr_vs_entries;
+ uint32_t gs_start;
+ uint32_t gs_size;
+ uint32_t nr_gs_entries;
+ } urb;
+
+ uint32_t active_stages;
+ struct anv_state_stream program_stream;
+ struct anv_state blend_state;
+ uint32_t vs_simd8;
+ uint32_t ps_simd8;
+ uint32_t ps_simd16;
+ uint32_t gs_vec4;
+ uint32_t gs_vertex_count;
+ uint32_t cs_simd;
+
+ uint32_t vb_used;
+ uint32_t binding_stride[MAX_VBS];
+
+ uint32_t state_sf[GEN8_3DSTATE_SF_length];
+ uint32_t state_vf[GEN8_3DSTATE_VF_length];
+ uint32_t state_raster[GEN8_3DSTATE_RASTER_length];
+ uint32_t state_wm_depth_stencil[GEN8_3DSTATE_WM_DEPTH_STENCIL_length];
+
+ uint32_t cs_thread_width_max;
+ uint32_t cs_right_mask;
+};
+
+struct anv_pipeline_create_info {
+ bool use_repclear;
+ bool disable_viewport;
+ bool disable_scissor;
+ bool disable_vs;
+ bool use_rectlist;
+};
+
+VkResult
+anv_pipeline_create(VkDevice device,
+ const VkGraphicsPipelineCreateInfo *pCreateInfo,
+ const struct anv_pipeline_create_info *extra,
+ VkPipeline *pPipeline);
+
+struct anv_compiler *anv_compiler_create(struct anv_device *device);
+void anv_compiler_destroy(struct anv_compiler *compiler);
+int anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline);
+void anv_compiler_free(struct anv_pipeline *pipeline);
+
+struct anv_format {
+ const char *name;
+ uint16_t surface_format; /**< RENDER_SURFACE_STATE.SurfaceFormat */
+ uint8_t cpp; /**< Bytes-per-pixel of anv_format::surface_format. */
+ uint8_t num_channels;
+ uint16_t depth_format; /**< 3DSTATE_DEPTH_BUFFER.SurfaceFormat */
+ bool has_stencil;
+};
+
+const struct anv_format *
+anv_format_for_vk_format(VkFormat format);
+bool anv_is_vk_format_depth_or_stencil(VkFormat format);
+
+/**
+ * A proxy for the color surfaces, depth surfaces, and stencil surfaces.
+ */
+struct anv_surface {
+ /**
+ * Offset from VkImage's base address, as bound by vkBindImageMemory().
+ */
+ uint32_t offset;
+
+ uint32_t stride; /**< RENDER_SURFACE_STATE.SurfacePitch */
+ uint16_t qpitch; /**< RENDER_SURFACE_STATE.QPitch */
+
+ /**
+ * \name Alignment of miptree images, in units of pixels.
+ *
+ * These fields contain the real alignment values, not the values to be
+ * given to the GPU. For example, if h_align is 4, then program the GPU
+ * with HALIGN_4.
+ * \{
+ */
+ uint8_t h_align; /**< RENDER_SURFACE_STATE.SurfaceHorizontalAlignment */
+ uint8_t v_align; /**< RENDER_SURFACE_STATE.SurfaceVerticalAlignment */
+ /** \} */
+
+ uint8_t tile_mode; /**< RENDER_SURFACE_STATE.TileMode */
+};
+
+struct anv_image {
+ VkImageType type;
+ VkExtent3D extent;
+ VkFormat format;
+ uint32_t levels;
+ uint32_t array_size;
+
+ VkDeviceSize size;
+ uint32_t alignment;
+
+ /* Set when bound */
+ struct anv_bo *bo;
+ VkDeviceSize offset;
+
+ struct anv_swap_chain *swap_chain;
+
+ /** RENDER_SURFACE_STATE.SurfaceType */
+ uint8_t surf_type;
+
+ /** Primary surface is either color or depth. */
+ struct anv_surface primary_surface;
+
+ /** Stencil surface is optional. */
+ struct anv_surface stencil_surface;
+};
+
+struct anv_surface_view {
+ struct anv_state surface_state; /**< RENDER_SURFACE_STATE */
+ struct anv_bo *bo;
+ uint32_t offset; /**< VkBufferCreateInfo::offset */
+ uint32_t range; /**< VkBufferCreateInfo::range */
+ VkFormat format; /**< VkBufferCreateInfo::format */
+};
+
+struct anv_buffer_view {
+ struct anv_surface_view view;
+};
+
+struct anv_image_view {
+ struct anv_surface_view view;
+ VkExtent3D extent;
+};
+
+enum anv_attachment_view_type {
+ ANV_ATTACHMENT_VIEW_TYPE_COLOR,
+ ANV_ATTACHMENT_VIEW_TYPE_DEPTH_STENCIL,
+};
+
+struct anv_attachment_view {
+ enum anv_attachment_view_type attachment_type;
+ VkExtent3D extent;
+};
+
+struct anv_color_attachment_view {
+ struct anv_attachment_view base;
+ struct anv_surface_view view;
+};
+
+struct anv_depth_stencil_view {
+ struct anv_attachment_view base;
+
+ struct anv_bo *bo;
+
+ uint32_t depth_offset; /**< Offset into bo. */
+ uint32_t depth_stride; /**< 3DSTATE_DEPTH_BUFFER.SurfacePitch */
+ uint32_t depth_format; /**< 3DSTATE_DEPTH_BUFFER.SurfaceFormat */
+ uint16_t depth_qpitch; /**< 3DSTATE_DEPTH_BUFFER.SurfaceQPitch */
+
+ uint32_t stencil_offset; /**< Offset into bo. */
+ uint32_t stencil_stride; /**< 3DSTATE_STENCIL_BUFFER.SurfacePitch */
+ uint16_t stencil_qpitch; /**< 3DSTATE_STENCIL_BUFFER.SurfaceQPitch */
+};
+
+struct anv_image_create_info {
+ const VkImageCreateInfo *vk_info;
+ bool force_tile_mode;
+ uint8_t tile_mode;
+};
+
+VkResult anv_image_create(VkDevice _device,
+ const struct anv_image_create_info *info,
+ VkImage *pImage);
+
+void anv_image_view_init(struct anv_image_view *view,
+ struct anv_device *device,
+ const VkImageViewCreateInfo* pCreateInfo,
+ struct anv_cmd_buffer *cmd_buffer);
+
+void anv_color_attachment_view_init(struct anv_color_attachment_view *view,
+ struct anv_device *device,
+ const VkAttachmentViewCreateInfo* pCreateInfo,
+ struct anv_cmd_buffer *cmd_buffer);
+void anv_fill_buffer_surface_state(void *state, VkFormat format,
+ uint32_t offset, uint32_t range);
+
+void anv_surface_view_fini(struct anv_device *device,
+ struct anv_surface_view *view);
+
+struct anv_sampler {
+ uint32_t state[4];
+};
+
+struct anv_framebuffer {
+ uint32_t width;
+ uint32_t height;
+ uint32_t layers;
+
+ /* Viewport for clears */
+ VkDynamicViewportState vp_state;
+
+ uint32_t attachment_count;
+ const struct anv_attachment_view * attachments[0];
+};
+
+struct anv_subpass {
+ uint32_t input_count;
+ uint32_t * input_attachments;
+ uint32_t color_count;
+ uint32_t * color_attachments;
+ uint32_t * resolve_attachments;
+ uint32_t depth_stencil_attachment;
+};
+
+struct anv_render_pass_attachment {
+ VkFormat format;
+ uint32_t samples;
+ VkAttachmentLoadOp load_op;
+ VkAttachmentLoadOp stencil_load_op;
+};
+
+struct anv_render_pass {
+ uint32_t attachment_count;
+ uint32_t subpass_count;
+
+ struct anv_render_pass_attachment * attachments;
+ struct anv_subpass subpasses[0];
+};
+
+void anv_device_init_meta(struct anv_device *device);
+void anv_device_finish_meta(struct anv_device *device);
+
+void *anv_lookup_entrypoint(const char *name);
+
+#define ANV_DEFINE_HANDLE_CASTS(__anv_type, __VkType) \
+ \
+ static inline struct __anv_type * \
+ __anv_type ## _from_handle(__VkType _handle) \
+ { \
+ return (struct __anv_type *) _handle; \
+ } \
+ \
+ static inline __VkType \
+ __anv_type ## _to_handle(struct __anv_type *_obj) \
+ { \
+ return (__VkType) _obj; \
+ }
+
+#define ANV_DEFINE_NONDISP_HANDLE_CASTS(__anv_type, __VkType) \
+ \
+ static inline struct __anv_type * \
+ __anv_type ## _from_handle(__VkType _handle) \
+ { \
+ return (struct __anv_type *) _handle.handle; \
+ } \
+ \
+ static inline __VkType \
+ __anv_type ## _to_handle(struct __anv_type *_obj) \
+ { \
+ return (__VkType) { .handle = (uint64_t) _obj }; \
+ }
+
+#define ANV_FROM_HANDLE(__anv_type, __name, __handle) \
+ struct __anv_type *__name = __anv_type ## _from_handle(__handle)
+
+ANV_DEFINE_HANDLE_CASTS(anv_cmd_buffer, VkCmdBuffer)
+ANV_DEFINE_HANDLE_CASTS(anv_device, VkDevice)
+ANV_DEFINE_HANDLE_CASTS(anv_instance, VkInstance)
+ANV_DEFINE_HANDLE_CASTS(anv_physical_device, VkPhysicalDevice)
+ANV_DEFINE_HANDLE_CASTS(anv_queue, VkQueue)
+ANV_DEFINE_HANDLE_CASTS(anv_swap_chain, VkSwapChainWSI);
+
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_attachment_view, VkAttachmentView)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_buffer, VkBuffer)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_buffer_view, VkBufferView);
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_descriptor_set, VkDescriptorSet)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_descriptor_set_layout, VkDescriptorSetLayout)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_device_memory, VkDeviceMemory)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_dynamic_cb_state, VkDynamicColorBlendState)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_dynamic_ds_state, VkDynamicDepthStencilState)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_dynamic_rs_state, VkDynamicRasterState)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_dynamic_vp_state, VkDynamicViewportState)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_fence, VkFence)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_framebuffer, VkFramebuffer)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_image, VkImage)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_image_view, VkImageView);
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_pipeline, VkPipeline)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_pipeline_layout, VkPipelineLayout)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_query_pool, VkQueryPool)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_render_pass, VkRenderPass)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_sampler, VkSampler)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_shader, VkShader)
+ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_shader_module, VkShaderModule)
+
+#define ANV_DEFINE_STRUCT_CASTS(__anv_type, __VkType) \
+ \
+ static inline const __VkType * \
+ __anv_type ## _to_ ## __VkType(const struct __anv_type *__anv_obj) \
+ { \
+ return (const __VkType *) __anv_obj; \
+ }
+
+#define ANV_COMMON_TO_STRUCT(__VkType, __vk_name, __common_name) \
+ const __VkType *__vk_name = anv_common_to_ ## __VkType(__common_name)
+
+ANV_DEFINE_STRUCT_CASTS(anv_common, VkMemoryBarrier)
+ANV_DEFINE_STRUCT_CASTS(anv_common, VkBufferMemoryBarrier)
+ANV_DEFINE_STRUCT_CASTS(anv_common, VkImageMemoryBarrier)
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*
+ * 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 <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "anv_private.h"
+
+struct anv_query_pool_slot {
+ uint64_t begin;
+ uint64_t end;
+ uint64_t available;
+};
+
+struct anv_query_pool {
+ VkQueryType type;
+ uint32_t slots;
+ struct anv_bo bo;
+};
+
+VkResult anv_CreateQueryPool(
+ VkDevice _device,
+ const VkQueryPoolCreateInfo* pCreateInfo,
+ VkQueryPool* pQueryPool)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_query_pool *pool;
+ VkResult result;
+ size_t size;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO);
+
+ switch (pCreateInfo->queryType) {
+ case VK_QUERY_TYPE_OCCLUSION:
+ break;
+ case VK_QUERY_TYPE_PIPELINE_STATISTICS:
+ return VK_UNSUPPORTED;
+ default:
+ unreachable("");
+ }
+
+ pool = anv_device_alloc(device, sizeof(*pool), 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (pool == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ size = pCreateInfo->slots * sizeof(struct anv_query_pool_slot);
+ result = anv_bo_init_new(&pool->bo, device, size);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ pool->bo.map = anv_gem_mmap(device, pool->bo.gem_handle, 0, size);
+
+ *pQueryPool = anv_query_pool_to_handle(pool);
+
+ return VK_SUCCESS;
+
+ fail:
+ anv_device_free(device, pool);
+
+ return result;
+}
+
+VkResult anv_DestroyQueryPool(
+ VkDevice _device,
+ VkQueryPool _pool)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_query_pool, pool, _pool);
+
+ anv_gem_munmap(pool->bo.map, pool->bo.size);
+ anv_gem_close(device, pool->bo.gem_handle);
+ anv_device_free(device, pool);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetQueryPoolResults(
+ VkDevice _device,
+ VkQueryPool queryPool,
+ uint32_t startQuery,
+ uint32_t queryCount,
+ size_t* pDataSize,
+ void* pData,
+ VkQueryResultFlags flags)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
+ struct anv_query_pool_slot *slot = pool->bo.map;
+ int64_t timeout = INT64_MAX;
+ uint32_t *dst32 = pData;
+ uint64_t *dst64 = pData;
+ uint64_t result;
+ int ret;
+
+ if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
+ /* Where is the availabilty info supposed to go? */
+ anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
+ return VK_UNSUPPORTED;
+ }
+
+ assert(pool->type == VK_QUERY_TYPE_OCCLUSION);
+
+ if (flags & VK_QUERY_RESULT_64_BIT)
+ *pDataSize = queryCount * sizeof(uint64_t);
+ else
+ *pDataSize = queryCount * sizeof(uint32_t);
+
+ if (pData == NULL)
+ return VK_SUCCESS;
+
+ if (flags & VK_QUERY_RESULT_WAIT_BIT) {
+ ret = anv_gem_wait(device, pool->bo.gem_handle, &timeout);
+ if (ret == -1)
+ return vk_error(VK_ERROR_UNKNOWN);
+ }
+
+ for (uint32_t i = 0; i < queryCount; i++) {
+ result = slot[startQuery + i].end - slot[startQuery + i].begin;
+ if (flags & VK_QUERY_RESULT_64_BIT) {
+ *dst64++ = result;
+ } else {
+ if (result > UINT32_MAX)
+ result = UINT32_MAX;
+ *dst32++ = result;
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+static void
+anv_batch_emit_ps_depth_count(struct anv_batch *batch,
+ struct anv_bo *bo, uint32_t offset)
+{
+ anv_batch_emit(batch, GEN8_PIPE_CONTROL,
+ .DestinationAddressType = DAT_PPGTT,
+ .PostSyncOperation = WritePSDepthCount,
+ .Address = { bo, offset }); /* FIXME: This is only lower 32 bits */
+}
+
+void anv_CmdBeginQuery(
+ VkCmdBuffer cmdBuffer,
+ VkQueryPool queryPool,
+ uint32_t slot,
+ VkQueryControlFlags flags)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
+
+ switch (pool->type) {
+ case VK_QUERY_TYPE_OCCLUSION:
+ anv_batch_emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
+ slot * sizeof(struct anv_query_pool_slot));
+ break;
+
+ case VK_QUERY_TYPE_PIPELINE_STATISTICS:
+ default:
+ unreachable("");
+ }
+}
+
+void anv_CmdEndQuery(
+ VkCmdBuffer cmdBuffer,
+ VkQueryPool queryPool,
+ uint32_t slot)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
+
+ switch (pool->type) {
+ case VK_QUERY_TYPE_OCCLUSION:
+ anv_batch_emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
+ slot * sizeof(struct anv_query_pool_slot) + 8);
+ break;
+
+ case VK_QUERY_TYPE_PIPELINE_STATISTICS:
+ default:
+ unreachable("");
+ }
+}
+
+void anv_CmdResetQueryPool(
+ VkCmdBuffer cmdBuffer,
+ VkQueryPool queryPool,
+ uint32_t startQuery,
+ uint32_t queryCount)
+{
+ stub();
+}
+
+#define TIMESTAMP 0x2358
+
+void anv_CmdWriteTimestamp(
+ VkCmdBuffer cmdBuffer,
+ VkTimestampType timestampType,
+ VkBuffer destBuffer,
+ VkDeviceSize destOffset)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_buffer, buffer, destBuffer);
+ struct anv_bo *bo = buffer->bo;
+
+ switch (timestampType) {
+ case VK_TIMESTAMP_TYPE_TOP:
+ anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
+ .RegisterAddress = TIMESTAMP,
+ .MemoryAddress = { bo, buffer->offset + destOffset });
+ anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
+ .RegisterAddress = TIMESTAMP + 4,
+ .MemoryAddress = { bo, buffer->offset + destOffset + 4 });
+ break;
+
+ case VK_TIMESTAMP_TYPE_BOTTOM:
+ anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
+ .DestinationAddressType = DAT_PPGTT,
+ .PostSyncOperation = WriteTimestamp,
+ .Address = /* FIXME: This is only lower 32 bits */
+ { bo, buffer->offset + destOffset });
+ break;
+
+ default:
+ break;
+ }
+}
+
+#define alu_opcode(v) __gen_field((v), 20, 31)
+#define alu_operand1(v) __gen_field((v), 10, 19)
+#define alu_operand2(v) __gen_field((v), 0, 9)
+#define alu(opcode, operand1, operand2) \
+ alu_opcode(opcode) | alu_operand1(operand1) | alu_operand2(operand2)
+
+#define OPCODE_NOOP 0x000
+#define OPCODE_LOAD 0x080
+#define OPCODE_LOADINV 0x480
+#define OPCODE_LOAD0 0x081
+#define OPCODE_LOAD1 0x481
+#define OPCODE_ADD 0x100
+#define OPCODE_SUB 0x101
+#define OPCODE_AND 0x102
+#define OPCODE_OR 0x103
+#define OPCODE_XOR 0x104
+#define OPCODE_STORE 0x180
+#define OPCODE_STOREINV 0x580
+
+#define OPERAND_R0 0x00
+#define OPERAND_R1 0x01
+#define OPERAND_R2 0x02
+#define OPERAND_R3 0x03
+#define OPERAND_R4 0x04
+#define OPERAND_SRCA 0x20
+#define OPERAND_SRCB 0x21
+#define OPERAND_ACCU 0x31
+#define OPERAND_ZF 0x32
+#define OPERAND_CF 0x33
+
+#define CS_GPR(n) (0x2600 + (n) * 8)
+
+static void
+emit_load_alu_reg_u64(struct anv_batch *batch, uint32_t reg,
+ struct anv_bo *bo, uint32_t offset)
+{
+ anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
+ .RegisterAddress = reg,
+ .MemoryAddress = { bo, offset });
+ anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
+ .RegisterAddress = reg + 4,
+ .MemoryAddress = { bo, offset + 4 });
+}
+
+void anv_CmdCopyQueryPoolResults(
+ VkCmdBuffer cmdBuffer,
+ VkQueryPool queryPool,
+ uint32_t startQuery,
+ uint32_t queryCount,
+ VkBuffer destBuffer,
+ VkDeviceSize destOffset,
+ VkDeviceSize destStride,
+ VkQueryResultFlags flags)
+{
+ ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
+ ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
+ ANV_FROM_HANDLE(anv_buffer, buffer, destBuffer);
+ uint32_t slot_offset, dst_offset;
+
+ if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
+ /* Where is the availabilty info supposed to go? */
+ anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
+ return;
+ }
+
+ assert(pool->type == VK_QUERY_TYPE_OCCLUSION);
+
+ /* FIXME: If we're not waiting, should we just do this on the CPU? */
+ if (flags & VK_QUERY_RESULT_WAIT_BIT)
+ anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
+ .CommandStreamerStallEnable = true,
+ .StallAtPixelScoreboard = true);
+
+ dst_offset = buffer->offset + destOffset;
+ for (uint32_t i = 0; i < queryCount; i++) {
+
+ slot_offset = (startQuery + i) * sizeof(struct anv_query_pool_slot);
+
+ emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(0), &pool->bo, slot_offset);
+ emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(1), &pool->bo, slot_offset + 8);
+
+ /* FIXME: We need to clamp the result for 32 bit. */
+
+ uint32_t *dw = anv_batch_emitn(&cmd_buffer->batch, 5, GEN8_MI_MATH);
+ dw[1] = alu(OPCODE_LOAD, OPERAND_SRCA, OPERAND_R1);
+ dw[2] = alu(OPCODE_LOAD, OPERAND_SRCB, OPERAND_R0);
+ dw[3] = alu(OPCODE_SUB, 0, 0);
+ dw[4] = alu(OPCODE_STORE, OPERAND_R2, OPERAND_ACCU);
+
+ anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
+ .RegisterAddress = CS_GPR(2),
+ /* FIXME: This is only lower 32 bits */
+ .MemoryAddress = { buffer->bo, dst_offset });
+
+ if (flags & VK_QUERY_RESULT_64_BIT)
+ anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
+ .RegisterAddress = CS_GPR(2) + 4,
+ /* FIXME: This is only lower 32 bits */
+ .MemoryAddress = { buffer->bo, dst_offset + 4 });
+
+ dst_offset += destStride;
+ }
+}
--- /dev/null
+/*
+ * 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 <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "anv_private.h"
+
+/** Log an error message. */
+void anv_printflike(1, 2)
+anv_loge(const char *format, ...)
+{
+ va_list va;
+
+ va_start(va, format);
+ anv_loge_v(format, va);
+ va_end(va);
+}
+
+/** \see anv_loge() */
+void
+anv_loge_v(const char *format, va_list va)
+{
+ fprintf(stderr, "vk: error: ");
+ vfprintf(stderr, format, va);
+ fprintf(stderr, "\n");
+}
+
+void anv_printflike(3, 4)
+__anv_finishme(const char *file, int line, const char *format, ...)
+{
+ va_list ap;
+ char buffer[256];
+
+ va_start(ap, format);
+ vsnprintf(buffer, sizeof(buffer), format, ap);
+ va_end(ap);
+
+ fprintf(stderr, "%s:%d: FINISHME: %s\n", file, line, buffer);
+}
+
+void anv_noreturn anv_printflike(1, 2)
+anv_abortf(const char *format, ...)
+{
+ va_list va;
+
+ va_start(va, format);
+ anv_abortfv(format, va);
+ va_end(va);
+}
+
+void anv_noreturn
+anv_abortfv(const char *format, va_list va)
+{
+ fprintf(stderr, "vk: error: ");
+ vfprintf(stderr, format, va);
+ fprintf(stderr, "\n");
+ abort();
+}
+
+int
+anv_vector_init(struct anv_vector *vector, uint32_t element_size, uint32_t size)
+{
+ assert(is_power_of_two(size));
+ assert(element_size < size && is_power_of_two(element_size));
+
+ vector->head = 0;
+ vector->tail = 0;
+ vector->element_size = element_size;
+ vector->size = size;
+ vector->data = malloc(size);
+
+ return vector->data != NULL;
+}
+
+void *
+anv_vector_add(struct anv_vector *vector)
+{
+ uint32_t offset, size, split, tail;
+ void *data;
+
+ if (vector->head - vector->tail == vector->size) {
+ size = vector->size * 2;
+ data = malloc(size);
+ if (data == NULL)
+ return NULL;
+ split = align_u32(vector->tail, vector->size);
+ tail = vector->tail & (vector->size - 1);
+ if (vector->head - split < vector->size) {
+ memcpy(data + tail,
+ vector->data + tail,
+ split - vector->tail);
+ memcpy(data + vector->size,
+ vector->data, vector->head - split);
+ } else {
+ memcpy(data + tail,
+ vector->data + tail,
+ vector->head - vector->tail);
+ }
+ free(vector->data);
+ vector->data = data;
+ vector->size = size;
+ }
+
+ assert(vector->head - vector->tail < vector->size);
+
+ offset = vector->head & (vector->size - 1);
+ vector->head += vector->element_size;
+
+ return vector->data + offset;
+}
+
+void *
+anv_vector_remove(struct anv_vector *vector)
+{
+ uint32_t offset;
+
+ if (vector->head == vector->tail)
+ return NULL;
+
+ assert(vector->head - vector->tail <= vector->size);
+
+ offset = vector->tail & (vector->size - 1);
+ vector->tail += vector->element_size;
+
+ return vector->data + offset;
+}
--- /dev/null
+/*
+ * 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 "anv_private.h"
+
+#include <xcb/xcb.h>
+#include <xcb/dri3.h>
+#include <xcb/present.h>
+
+static const VkFormat formats[] = {
+ VK_FORMAT_B5G6R5_UNORM,
+ VK_FORMAT_B8G8R8A8_UNORM,
+ VK_FORMAT_B8G8R8A8_SRGB,
+};
+
+VkResult anv_GetDisplayInfoWSI(
+ VkDisplayWSI display,
+ VkDisplayInfoTypeWSI infoType,
+ size_t* pDataSize,
+ void* pData)
+{
+ VkDisplayFormatPropertiesWSI *properties = pData;
+ size_t size;
+
+ if (pDataSize == NULL)
+ return VK_ERROR_INVALID_POINTER;
+
+ switch (infoType) {
+ case VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI:
+ size = sizeof(properties[0]) * ARRAY_SIZE(formats);
+
+ if (pData == NULL) {
+ *pDataSize = size;
+ return VK_SUCCESS;
+ }
+
+ if (*pDataSize < size)
+ return vk_error(VK_ERROR_INVALID_VALUE);
+
+ *pDataSize = size;
+
+ for (uint32_t i = 0; i < ARRAY_SIZE(formats); i++)
+ properties[i].swapChainFormat = formats[i];
+
+ return VK_SUCCESS;
+
+ default:
+ return VK_UNSUPPORTED;
+ }
+}
+
+struct anv_swap_chain {
+ struct anv_device * device;
+ xcb_connection_t * conn;
+ xcb_window_t window;
+ xcb_gc_t gc;
+ VkExtent2D extent;
+ uint32_t count;
+ struct {
+ struct anv_image * image;
+ struct anv_device_memory * memory;
+ xcb_pixmap_t pixmap;
+ } images[0];
+};
+
+VkResult anv_CreateSwapChainWSI(
+ VkDevice _device,
+ const VkSwapChainCreateInfoWSI* pCreateInfo,
+ VkSwapChainWSI* pSwapChain)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+
+ struct anv_swap_chain *chain;
+ xcb_void_cookie_t cookie;
+ VkResult result;
+ size_t size;
+ int ret;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI);
+
+ size = sizeof(*chain) + pCreateInfo->imageCount * sizeof(chain->images[0]);
+ chain = anv_device_alloc(device, size, 8,
+ VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (chain == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ chain->device = device;
+ chain->conn = (xcb_connection_t *) pCreateInfo->pNativeWindowSystemHandle;
+ chain->window = (xcb_window_t) (uintptr_t) pCreateInfo->pNativeWindowHandle;
+ chain->count = pCreateInfo->imageCount;
+ chain->extent = pCreateInfo->imageExtent;
+
+ for (uint32_t i = 0; i < chain->count; i++) {
+ VkDeviceMemory memory_h;
+ VkImage image_h;
+ struct anv_image *image;
+ struct anv_surface *surface;
+ struct anv_device_memory *memory;
+
+ anv_image_create(_device,
+ &(struct anv_image_create_info) {
+ .force_tile_mode = true,
+ .tile_mode = XMAJOR,
+ .vk_info =
+ &(VkImageCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .imageType = VK_IMAGE_TYPE_2D,
+ .format = pCreateInfo->imageFormat,
+ .extent = {
+ .width = pCreateInfo->imageExtent.width,
+ .height = pCreateInfo->imageExtent.height,
+ .depth = 1
+ },
+ .mipLevels = 1,
+ .arraySize = 1,
+ .samples = 1,
+ /* FIXME: Need a way to use X tiling to allow scanout */
+ .tiling = VK_IMAGE_TILING_OPTIMAL,
+ .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ .flags = 0,
+ }},
+ &image_h);
+
+ image = anv_image_from_handle(image_h);
+ surface = &image->primary_surface;
+
+ anv_AllocMemory(_device,
+ &(VkMemoryAllocInfo) {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
+ .allocationSize = image->size,
+ .memoryTypeIndex = 0,
+ },
+ &memory_h);
+
+ memory = anv_device_memory_from_handle(memory_h);
+
+ anv_BindImageMemory(VK_NULL_HANDLE, anv_image_to_handle(image),
+ memory_h, 0);
+
+ ret = anv_gem_set_tiling(device, memory->bo.gem_handle,
+ surface->stride, I915_TILING_X);
+ if (ret) {
+ result = vk_error(VK_ERROR_UNKNOWN);
+ goto fail;
+ }
+
+ int fd = anv_gem_handle_to_fd(device, memory->bo.gem_handle);
+ if (fd == -1) {
+ result = vk_error(VK_ERROR_UNKNOWN);
+ goto fail;
+ }
+
+ uint32_t bpp = 32;
+ uint32_t depth = 24;
+ xcb_pixmap_t pixmap = xcb_generate_id(chain->conn);
+
+ cookie =
+ xcb_dri3_pixmap_from_buffer_checked(chain->conn,
+ pixmap,
+ chain->window,
+ image->size,
+ pCreateInfo->imageExtent.width,
+ pCreateInfo->imageExtent.height,
+ surface->stride,
+ depth, bpp, fd);
+
+ chain->images[i].image = image;
+ chain->images[i].memory = memory;
+ chain->images[i].pixmap = pixmap;
+ image->swap_chain = chain;
+
+ xcb_discard_reply(chain->conn, cookie.sequence);
+ }
+
+ chain->gc = xcb_generate_id(chain->conn);
+ if (!chain->gc) {
+ result = vk_error(VK_ERROR_UNKNOWN);
+ goto fail;
+ }
+
+ cookie = xcb_create_gc(chain->conn,
+ chain->gc,
+ chain->window,
+ XCB_GC_GRAPHICS_EXPOSURES,
+ (uint32_t []) { 0 });
+ xcb_discard_reply(chain->conn, cookie.sequence);
+
+ *pSwapChain = anv_swap_chain_to_handle(chain);
+
+ return VK_SUCCESS;
+
+ fail:
+ return result;
+}
+
+VkResult anv_DestroySwapChainWSI(
+ VkSwapChainWSI _chain)
+{
+ ANV_FROM_HANDLE(anv_swap_chain, chain, _chain);
+
+ anv_device_free(chain->device, chain);
+
+ return VK_SUCCESS;
+}
+
+VkResult anv_GetSwapChainInfoWSI(
+ VkSwapChainWSI _chain,
+ VkSwapChainInfoTypeWSI infoType,
+ size_t* pDataSize,
+ void* pData)
+{
+ ANV_FROM_HANDLE(anv_swap_chain, chain, _chain);
+
+ VkSwapChainImageInfoWSI *images;
+ size_t size;
+
+ switch (infoType) {
+ case VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI:
+ size = sizeof(*images) * chain->count;
+ if (pData && *pDataSize < size)
+ return VK_ERROR_INVALID_VALUE;
+
+ *pDataSize = size;
+ if (!pData)
+ return VK_SUCCESS;
+
+ images = pData;
+ for (uint32_t i = 0; i < chain->count; i++) {
+ images[i].image = anv_image_to_handle(chain->images[i].image);
+ images[i].memory = anv_device_memory_to_handle(chain->images[i].memory);
+ }
+
+ return VK_SUCCESS;
+
+ default:
+ return VK_UNSUPPORTED;
+ }
+}
+
+VkResult anv_QueuePresentWSI(
+ VkQueue queue_,
+ const VkPresentInfoWSI* pPresentInfo)
+{
+ ANV_FROM_HANDLE(anv_image, image, pPresentInfo->image);
+
+ struct anv_swap_chain *chain = image->swap_chain;
+ xcb_void_cookie_t cookie;
+ xcb_pixmap_t pixmap;
+
+ assert(pPresentInfo->sType == VK_STRUCTURE_TYPE_PRESENT_INFO_WSI);
+
+ if (chain == NULL)
+ return vk_error(VK_ERROR_INVALID_VALUE);
+
+ pixmap = XCB_NONE;
+ for (uint32_t i = 0; i < chain->count; i++) {
+ if (image == chain->images[i].image) {
+ pixmap = chain->images[i].pixmap;
+ break;
+ }
+ }
+
+ if (pixmap == XCB_NONE)
+ return vk_error(VK_ERROR_INVALID_VALUE);
+
+ cookie = xcb_copy_area(chain->conn,
+ pixmap,
+ chain->window,
+ chain->gc,
+ 0, 0,
+ 0, 0,
+ chain->extent.width,
+ chain->extent.height);
+ xcb_discard_reply(chain->conn, cookie.sequence);
+
+ xcb_flush(chain->conn);
+
+ return VK_SUCCESS;
+}
+++ /dev/null
-/*
- * 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 <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-
-#include <drm.h>
-#include <i915_drm.h>
-
-#include "private.h"
-#include "aub.h"
-
-struct anv_aub_writer {
- FILE *file;
- uint32_t offset;
- int gen;
-};
-
-static void
-aub_out(struct anv_aub_writer *writer, uint32_t data)
-{
- fwrite(&data, 1, 4, writer->file);
-}
-
-static void
-aub_out_data(struct anv_aub_writer *writer, const void *data, size_t size)
-{
- fwrite(data, 1, size, writer->file);
-}
-
-static struct anv_aub_writer *
-get_anv_aub_writer(struct anv_device *device)
-{
- struct anv_aub_writer *writer = device->aub_writer;
- int entry = 0x200003;
- int i;
- int gtt_size = 0x10000;
- const char *filename;
-
- if (geteuid() != getuid())
- return NULL;
-
- if (writer)
- return writer;
-
- writer = malloc(sizeof(*writer));
- if (writer == NULL)
- return NULL;
-
- filename = "intel.aub";
- writer->gen = device->info.gen;
- writer->file = fopen(filename, "w+");
- if (!writer->file) {
- free(writer);
- return NULL;
- }
-
- /* Start allocating objects from just after the GTT. */
- writer->offset = gtt_size;
-
- /* Start with a (required) version packet. */
- aub_out(writer, CMD_AUB_HEADER | (13 - 2));
- aub_out(writer,
- (4 << AUB_HEADER_MAJOR_SHIFT) |
- (0 << AUB_HEADER_MINOR_SHIFT));
- for (i = 0; i < 8; i++) {
- aub_out(writer, 0); /* app name */
- }
- aub_out(writer, 0); /* timestamp */
- aub_out(writer, 0); /* timestamp */
- aub_out(writer, 0); /* comment len */
-
- /* Set up the GTT. The max we can handle is 256M */
- aub_out(writer, CMD_AUB_TRACE_HEADER_BLOCK | ((writer->gen >= 8 ? 6 : 5) - 2));
- aub_out(writer,
- AUB_TRACE_MEMTYPE_GTT_ENTRY |
- AUB_TRACE_TYPE_NOTYPE | AUB_TRACE_OP_DATA_WRITE);
- aub_out(writer, 0); /* subtype */
- aub_out(writer, 0); /* offset */
- aub_out(writer, gtt_size); /* size */
- if (writer->gen >= 8)
- aub_out(writer, 0);
- for (i = 0x000; i < gtt_size; i += 4, entry += 0x1000) {
- aub_out(writer, entry);
- }
-
- return device->aub_writer = writer;
-}
-
-void
-anv_aub_writer_destroy(struct anv_aub_writer *writer)
-{
- fclose(writer->file);
- free(writer);
-}
-
-
-/**
- * Break up large objects into multiple writes. Otherwise a 128kb VBO
- * would overflow the 16 bits of size field in the packet header and
- * everything goes badly after that.
- */
-static void
-aub_write_trace_block(struct anv_aub_writer *writer, uint32_t type,
- void *virtual, uint32_t size, uint32_t gtt_offset)
-{
- uint32_t block_size;
- uint32_t offset;
- uint32_t subtype = 0;
- static const char null_block[8 * 4096];
-
- for (offset = 0; offset < size; offset += block_size) {
- block_size = size - offset;
-
- if (block_size > 8 * 4096)
- block_size = 8 * 4096;
-
- aub_out(writer,
- CMD_AUB_TRACE_HEADER_BLOCK |
- ((writer->gen >= 8 ? 6 : 5) - 2));
- aub_out(writer,
- AUB_TRACE_MEMTYPE_GTT |
- type | AUB_TRACE_OP_DATA_WRITE);
- aub_out(writer, subtype);
- aub_out(writer, gtt_offset + offset);
- aub_out(writer, align_u32(block_size, 4));
- if (writer->gen >= 8)
- aub_out(writer, 0);
-
- if (virtual)
- aub_out_data(writer, (char *) virtual + offset, block_size);
- else
- aub_out_data(writer, null_block, block_size);
-
- /* Pad to a multiple of 4 bytes. */
- aub_out_data(writer, null_block, -block_size & 3);
- }
-}
-
-/*
- * Make a ringbuffer on fly and dump it
- */
-static void
-aub_build_dump_ringbuffer(struct anv_aub_writer *writer,
- uint32_t batch_offset, uint32_t offset,
- int ring_flag)
-{
- uint32_t ringbuffer[4096];
- int ring = AUB_TRACE_TYPE_RING_PRB0; /* The default ring */
- int ring_count = 0;
-
- if (ring_flag == I915_EXEC_BSD)
- ring = AUB_TRACE_TYPE_RING_PRB1;
- else if (ring_flag == I915_EXEC_BLT)
- ring = AUB_TRACE_TYPE_RING_PRB2;
-
- /* Make a ring buffer to execute our batchbuffer. */
- memset(ringbuffer, 0, sizeof(ringbuffer));
- if (writer->gen >= 8) {
- ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START | (3 - 2);
- ringbuffer[ring_count++] = batch_offset;
- ringbuffer[ring_count++] = 0;
- } else {
- ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START;
- ringbuffer[ring_count++] = batch_offset;
- }
-
- /* Write out the ring. This appears to trigger execution of
- * the ring in the simulator.
- */
- aub_out(writer,
- CMD_AUB_TRACE_HEADER_BLOCK |
- ((writer->gen >= 8 ? 6 : 5) - 2));
- aub_out(writer,
- AUB_TRACE_MEMTYPE_GTT | ring | AUB_TRACE_OP_COMMAND_WRITE);
- aub_out(writer, 0); /* general/surface subtype */
- aub_out(writer, offset);
- aub_out(writer, ring_count * 4);
- if (writer->gen >= 8)
- aub_out(writer, 0);
-
- /* FIXME: Need some flush operations here? */
- aub_out_data(writer, ringbuffer, ring_count * 4);
-}
-
-struct aub_bo {
- uint32_t offset;
- void *map;
- void *relocated;
-};
-
-static void
-relocate_bo(struct anv_bo *bo, struct drm_i915_gem_relocation_entry *relocs,
- size_t num_relocs, struct aub_bo *bos)
-{
- struct aub_bo *aub_bo = &bos[bo->index];
- struct drm_i915_gem_relocation_entry *reloc;
- uint32_t *dw;
-
- aub_bo->relocated = malloc(bo->size);
- memcpy(aub_bo->relocated, aub_bo->map, bo->size);
- for (size_t i = 0; i < num_relocs; i++) {
- reloc = &relocs[i];
- assert(reloc->offset < bo->size);
- dw = aub_bo->relocated + reloc->offset;
- *dw = bos[reloc->target_handle].offset + reloc->delta;
- }
-}
-
-void
-anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer)
-{
- struct anv_device *device = cmd_buffer->device;
- struct anv_batch *batch = &cmd_buffer->batch;
- struct anv_aub_writer *writer;
- struct anv_bo *bo;
- uint32_t ring_flag = 0;
- uint32_t offset;
- struct aub_bo *aub_bos;
-
- writer = get_anv_aub_writer(device);
- if (writer == NULL)
- return;
-
- aub_bos = malloc(cmd_buffer->exec2_bo_count * sizeof(aub_bos[0]));
- offset = writer->offset;
- for (uint32_t i = 0; i < cmd_buffer->exec2_bo_count; i++) {
- bo = cmd_buffer->exec2_bos[i];
- if (bo->map)
- aub_bos[i].map = bo->map;
- else
- aub_bos[i].map = anv_gem_mmap(device, bo->gem_handle, 0, bo->size);
- aub_bos[i].relocated = aub_bos[i].map;
- aub_bos[i].offset = offset;
- offset = align_u32(offset + bo->size + 4095, 4096);
- }
-
- struct anv_batch_bo *first_bbo;
- for (struct anv_batch_bo *bbo = cmd_buffer->last_batch_bo;
- bbo != NULL; bbo = bbo->prev_batch_bo) {
- /* Keep stashing the current BO until we get to the beginning */
- first_bbo = bbo;
-
- /* Handle relocations for this batch BO */
- relocate_bo(&bbo->bo, &batch->relocs.relocs[bbo->first_reloc],
- bbo->num_relocs, aub_bos);
- }
- assert(first_bbo->prev_batch_bo == NULL);
-
- for (struct anv_batch_bo *bbo = cmd_buffer->surface_batch_bo;
- bbo != NULL; bbo = bbo->prev_batch_bo) {
-
- /* Handle relocations for this surface state BO */
- relocate_bo(&bbo->bo,
- &cmd_buffer->surface_relocs.relocs[bbo->first_reloc],
- bbo->num_relocs, aub_bos);
- }
-
- for (uint32_t i = 0; i < cmd_buffer->exec2_bo_count; i++) {
- bo = cmd_buffer->exec2_bos[i];
- if (i == cmd_buffer->exec2_bo_count - 1) {
- assert(bo == &first_bbo->bo);
- aub_write_trace_block(writer, AUB_TRACE_TYPE_BATCH,
- aub_bos[i].relocated,
- first_bbo->length, aub_bos[i].offset);
- } else {
- aub_write_trace_block(writer, AUB_TRACE_TYPE_NOTYPE,
- aub_bos[i].relocated,
- bo->size, aub_bos[i].offset);
- }
- if (aub_bos[i].relocated != aub_bos[i].map)
- free(aub_bos[i].relocated);
- if (aub_bos[i].map != bo->map)
- anv_gem_munmap(aub_bos[i].map, bo->size);
- }
-
- /* Dump ring buffer */
- aub_build_dump_ringbuffer(writer, aub_bos[first_bbo->bo.index].offset,
- offset, ring_flag);
-
- free(aub_bos);
-
- fflush(writer->file);
-}
+++ /dev/null
-/*
- * 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.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- *
- */
-
-/** @file intel_aub.h
- *
- * The AUB file is a file format used by Intel's internal simulation
- * and other validation tools. It can be used at various levels by a
- * driver to input state to the simulated hardware or a replaying
- * debugger.
- *
- * We choose to dump AUB files using the trace block format for ease
- * of implementation -- dump out the blocks of memory as plain blobs
- * and insert ring commands to execute the batchbuffer blob.
- */
-
-#ifndef _INTEL_AUB_H
-#define _INTEL_AUB_H
-
-#define AUB_MI_NOOP (0)
-#define AUB_MI_BATCH_BUFFER_START (0x31 << 23)
-#define AUB_PIPE_CONTROL (0x7a000002)
-
-/* DW0: instruction type. */
-
-#define CMD_AUB (7 << 29)
-
-#define CMD_AUB_HEADER (CMD_AUB | (1 << 23) | (0x05 << 16))
-/* DW1 */
-# define AUB_HEADER_MAJOR_SHIFT 24
-# define AUB_HEADER_MINOR_SHIFT 16
-
-#define CMD_AUB_TRACE_HEADER_BLOCK (CMD_AUB | (1 << 23) | (0x41 << 16))
-#define CMD_AUB_DUMP_BMP (CMD_AUB | (1 << 23) | (0x9e << 16))
-
-/* DW1 */
-#define AUB_TRACE_OPERATION_MASK 0x000000ff
-#define AUB_TRACE_OP_COMMENT 0x00000000
-#define AUB_TRACE_OP_DATA_WRITE 0x00000001
-#define AUB_TRACE_OP_COMMAND_WRITE 0x00000002
-#define AUB_TRACE_OP_MMIO_WRITE 0x00000003
-// operation = TRACE_DATA_WRITE, Type
-#define AUB_TRACE_TYPE_MASK 0x0000ff00
-#define AUB_TRACE_TYPE_NOTYPE (0 << 8)
-#define AUB_TRACE_TYPE_BATCH (1 << 8)
-#define AUB_TRACE_TYPE_VERTEX_BUFFER (5 << 8)
-#define AUB_TRACE_TYPE_2D_MAP (6 << 8)
-#define AUB_TRACE_TYPE_CUBE_MAP (7 << 8)
-#define AUB_TRACE_TYPE_VOLUME_MAP (9 << 8)
-#define AUB_TRACE_TYPE_1D_MAP (10 << 8)
-#define AUB_TRACE_TYPE_CONSTANT_BUFFER (11 << 8)
-#define AUB_TRACE_TYPE_CONSTANT_URB (12 << 8)
-#define AUB_TRACE_TYPE_INDEX_BUFFER (13 << 8)
-#define AUB_TRACE_TYPE_GENERAL (14 << 8)
-#define AUB_TRACE_TYPE_SURFACE (15 << 8)
-
-
-// operation = TRACE_COMMAND_WRITE, Type =
-#define AUB_TRACE_TYPE_RING_HWB (1 << 8)
-#define AUB_TRACE_TYPE_RING_PRB0 (2 << 8)
-#define AUB_TRACE_TYPE_RING_PRB1 (3 << 8)
-#define AUB_TRACE_TYPE_RING_PRB2 (4 << 8)
-
-// Address space
-#define AUB_TRACE_ADDRESS_SPACE_MASK 0x00ff0000
-#define AUB_TRACE_MEMTYPE_GTT (0 << 16)
-#define AUB_TRACE_MEMTYPE_LOCAL (1 << 16)
-#define AUB_TRACE_MEMTYPE_NONLOCAL (2 << 16)
-#define AUB_TRACE_MEMTYPE_PCI (3 << 16)
-#define AUB_TRACE_MEMTYPE_GTT_ENTRY (4 << 16)
-
-/* DW2 */
-
-/**
- * aub_state_struct_type enum values are encoded with the top 16 bits
- * representing the type to be delivered to the .aub file, and the bottom 16
- * bits representing the subtype. This macro performs the encoding.
- */
-#define ENCODE_SS_TYPE(type, subtype) (((type) << 16) | (subtype))
-
-enum aub_state_struct_type {
- AUB_TRACE_VS_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 1),
- AUB_TRACE_GS_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 2),
- AUB_TRACE_CLIP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 3),
- AUB_TRACE_SF_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 4),
- AUB_TRACE_WM_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 5),
- AUB_TRACE_CC_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 6),
- AUB_TRACE_CLIP_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 7),
- AUB_TRACE_SF_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 8),
- AUB_TRACE_CC_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x9),
- AUB_TRACE_SAMPLER_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xa),
- AUB_TRACE_KERNEL_INSTRUCTIONS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xb),
- AUB_TRACE_SCRATCH_SPACE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xc),
- AUB_TRACE_SAMPLER_DEFAULT_COLOR = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xd),
-
- AUB_TRACE_SCISSOR_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x15),
- AUB_TRACE_BLEND_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x16),
- AUB_TRACE_DEPTH_STENCIL_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x17),
-
- AUB_TRACE_VERTEX_BUFFER = ENCODE_SS_TYPE(AUB_TRACE_TYPE_VERTEX_BUFFER, 0),
- AUB_TRACE_BINDING_TABLE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_SURFACE, 0x100),
- AUB_TRACE_SURFACE_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_SURFACE, 0x200),
- AUB_TRACE_VS_CONSTANTS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_CONSTANT_BUFFER, 0),
- AUB_TRACE_WM_CONSTANTS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_CONSTANT_BUFFER, 1),
-};
-
-#undef ENCODE_SS_TYPE
-
-/**
- * Decode a aub_state_struct_type value to determine the type that should be
- * stored in the .aub file.
- */
-static inline uint32_t AUB_TRACE_TYPE(enum aub_state_struct_type ss_type)
-{
- return (ss_type & 0xFFFF0000) >> 16;
-}
-
-/**
- * Decode a state_struct_type value to determine the subtype that should be
- * stored in the .aub file.
- */
-static inline uint32_t AUB_TRACE_SUBTYPE(enum aub_state_struct_type ss_type)
-{
- return ss_type & 0xFFFF;
-}
-
-/* DW3: address */
-/* DW4: len */
-
-#endif /* _INTEL_AUB_H */
+++ /dev/null
-/*
- * 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 <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "private.h"
-
-#include <brw_context.h>
-#include <brw_wm.h> /* brw_new_shader_program is here */
-#include <brw_nir.h>
-
-#include <brw_vs.h>
-#include <brw_gs.h>
-#include <brw_cs.h>
-
-#include <mesa/main/shaderobj.h>
-#include <mesa/main/fbobject.h>
-#include <mesa/main/context.h>
-#include <mesa/program/program.h>
-#include <glsl/program.h>
-
-/* XXX: We need this to keep symbols in nir.h from conflicting with the
- * generated GEN command packing headers. We need to fix *both* to not
- * define something as generic as LOAD.
- */
-#undef LOAD
-
-#include <glsl/nir/nir_spirv.h>
-
-#define SPIR_V_MAGIC_NUMBER 0x07230203
-
-static void
-fail_if(int cond, const char *format, ...)
-{
- va_list args;
-
- if (!cond)
- return;
-
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
-
- exit(1);
-}
-
-static VkResult
-set_binding_table_layout(struct brw_stage_prog_data *prog_data,
- struct anv_pipeline *pipeline, uint32_t stage)
-{
- uint32_t bias, count, k, *map;
- struct anv_pipeline_layout *layout = pipeline->layout;
-
- /* No layout is valid for shaders that don't bind any resources. */
- if (pipeline->layout == NULL)
- return VK_SUCCESS;
-
- if (stage == VK_SHADER_STAGE_FRAGMENT)
- bias = MAX_RTS;
- else
- bias = 0;
-
- count = layout->stage[stage].surface_count;
- prog_data->map_entries =
- (uint32_t *) malloc(count * sizeof(prog_data->map_entries[0]));
- if (prog_data->map_entries == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- k = bias;
- map = prog_data->map_entries;
- for (uint32_t i = 0; i < layout->num_sets; i++) {
- prog_data->bind_map[i].index = map;
- for (uint32_t j = 0; j < layout->set[i].layout->stage[stage].surface_count; j++)
- *map++ = k++;
-
- prog_data->bind_map[i].index_count =
- layout->set[i].layout->stage[stage].surface_count;
- }
-
- return VK_SUCCESS;
-}
-
-static void
-brw_vs_populate_key(struct brw_context *brw,
- struct brw_vertex_program *vp,
- struct brw_vs_prog_key *key)
-{
- struct gl_context *ctx = &brw->ctx;
- /* BRW_NEW_VERTEX_PROGRAM */
- struct gl_program *prog = (struct gl_program *) vp;
-
- memset(key, 0, sizeof(*key));
-
- /* Just upload the program verbatim for now. Always send it all
- * the inputs it asks for, whether they are varying or not.
- */
- key->base.program_string_id = vp->id;
- brw_setup_vue_key_clip_info(brw, &key->base,
- vp->program.Base.UsesClipDistanceOut);
-
- /* _NEW_POLYGON */
- if (brw->gen < 6) {
- key->copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL ||
- ctx->Polygon.BackMode != GL_FILL);
- }
-
- if (prog->OutputsWritten & (VARYING_BIT_COL0 | VARYING_BIT_COL1 |
- VARYING_BIT_BFC0 | VARYING_BIT_BFC1)) {
- /* _NEW_LIGHT | _NEW_BUFFERS */
- key->clamp_vertex_color = ctx->Light._ClampVertexColor;
- }
-
- /* _NEW_POINT */
- if (brw->gen < 6 && ctx->Point.PointSprite) {
- for (int i = 0; i < 8; i++) {
- if (ctx->Point.CoordReplace[i])
- key->point_coord_replace |= (1 << i);
- }
- }
-
- /* _NEW_TEXTURE */
- brw_populate_sampler_prog_key_data(ctx, prog, brw->vs.base.sampler_count,
- &key->base.tex);
-}
-
-static bool
-really_do_vs_prog(struct brw_context *brw,
- struct gl_shader_program *prog,
- struct brw_vertex_program *vp,
- struct brw_vs_prog_key *key, struct anv_pipeline *pipeline)
-{
- GLuint program_size;
- const GLuint *program;
- struct brw_vs_compile c;
- struct brw_vs_prog_data *prog_data = &pipeline->vs_prog_data;
- struct brw_stage_prog_data *stage_prog_data = &prog_data->base.base;
- void *mem_ctx;
- struct gl_shader *vs = NULL;
-
- if (prog)
- vs = prog->_LinkedShaders[MESA_SHADER_VERTEX];
-
- memset(&c, 0, sizeof(c));
- memcpy(&c.key, key, sizeof(*key));
- memset(prog_data, 0, sizeof(*prog_data));
-
- mem_ctx = ralloc_context(NULL);
-
- c.vp = vp;
-
- /* Allocate the references to the uniforms that will end up in the
- * prog_data associated with the compiled program, and which will be freed
- * by the state cache.
- */
- int param_count;
- if (vs) {
- /* We add padding around uniform values below vec4 size, with the worst
- * case being a float value that gets blown up to a vec4, so be
- * conservative here.
- */
- param_count = vs->num_uniform_components * 4;
-
- } else {
- param_count = vp->program.Base.Parameters->NumParameters * 4;
- }
- /* vec4_visitor::setup_uniform_clipplane_values() also uploads user clip
- * planes as uniforms.
- */
- param_count += c.key.base.nr_userclip_plane_consts * 4;
-
- /* Setting nr_params here NOT to the size of the param and pull_param
- * arrays, but to the number of uniform components vec4_visitor
- * needs. vec4_visitor::setup_uniforms() will set it back to a proper value.
- */
- stage_prog_data->nr_params = ALIGN(param_count, 4) / 4;
- if (vs) {
- stage_prog_data->nr_params += vs->num_samplers;
- }
-
- GLbitfield64 outputs_written = vp->program.Base.OutputsWritten;
- prog_data->inputs_read = vp->program.Base.InputsRead;
-
- if (c.key.copy_edgeflag) {
- outputs_written |= BITFIELD64_BIT(VARYING_SLOT_EDGE);
- prog_data->inputs_read |= VERT_BIT_EDGEFLAG;
- }
-
- if (brw->gen < 6) {
- /* Put dummy slots into the VUE for the SF to put the replaced
- * point sprite coords in. We shouldn't need these dummy slots,
- * which take up precious URB space, but it would mean that the SF
- * doesn't get nice aligned pairs of input coords into output
- * coords, which would be a pain to handle.
- */
- for (int i = 0; i < 8; i++) {
- if (c.key.point_coord_replace & (1 << i))
- outputs_written |= BITFIELD64_BIT(VARYING_SLOT_TEX0 + i);
- }
-
- /* if back colors are written, allocate slots for front colors too */
- if (outputs_written & BITFIELD64_BIT(VARYING_SLOT_BFC0))
- outputs_written |= BITFIELD64_BIT(VARYING_SLOT_COL0);
- if (outputs_written & BITFIELD64_BIT(VARYING_SLOT_BFC1))
- outputs_written |= BITFIELD64_BIT(VARYING_SLOT_COL1);
- }
-
- /* In order for legacy clipping to work, we need to populate the clip
- * distance varying slots whenever clipping is enabled, even if the vertex
- * shader doesn't write to gl_ClipDistance.
- */
- if (c.key.base.userclip_active) {
- outputs_written |= BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST0);
- outputs_written |= BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST1);
- }
-
- brw_compute_vue_map(brw->intelScreen->devinfo,
- &prog_data->base.vue_map, outputs_written);
-\
- set_binding_table_layout(&prog_data->base.base, pipeline,
- VK_SHADER_STAGE_VERTEX);
-
- /* Emit GEN4 code.
- */
- program = brw_vs_emit(brw, prog, &c, prog_data, mem_ctx, &program_size);
- if (program == NULL) {
- ralloc_free(mem_ctx);
- return false;
- }
-
- struct anv_state vs_state = anv_state_stream_alloc(&pipeline->program_stream,
- program_size, 64);
- memcpy(vs_state.map, program, program_size);
-
- pipeline->vs_simd8 = vs_state.offset;
-
- ralloc_free(mem_ctx);
-
- return true;
-}
-
-void brw_wm_populate_key(struct brw_context *brw,
- struct brw_fragment_program *fp,
- struct brw_wm_prog_key *key)
-{
- struct gl_context *ctx = &brw->ctx;
- struct gl_program *prog = (struct gl_program *) brw->fragment_program;
- GLuint lookup = 0;
- GLuint line_aa;
- bool program_uses_dfdy = fp->program.UsesDFdy;
- struct gl_framebuffer draw_buffer;
- bool multisample_fbo;
-
- memset(key, 0, sizeof(*key));
-
- for (int i = 0; i < MAX_SAMPLERS; i++) {
- /* Assume color sampler, no swizzling. */
- key->tex.swizzles[i] = SWIZZLE_XYZW;
- }
-
- /* A non-zero framebuffer name indicates that the framebuffer was created by
- * the user rather than the window system. */
- draw_buffer.Name = 1;
- draw_buffer.Visual.samples = 1;
- draw_buffer._NumColorDrawBuffers = 1;
- draw_buffer._NumColorDrawBuffers = 1;
- draw_buffer.Width = 400;
- draw_buffer.Height = 400;
- ctx->DrawBuffer = &draw_buffer;
-
- multisample_fbo = ctx->DrawBuffer->Visual.samples > 1;
-
- /* Build the index for table lookup
- */
- if (brw->gen < 6) {
- /* _NEW_COLOR */
- if (fp->program.UsesKill || ctx->Color.AlphaEnabled)
- lookup |= IZ_PS_KILL_ALPHATEST_BIT;
-
- if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH))
- lookup |= IZ_PS_COMPUTES_DEPTH_BIT;
-
- /* _NEW_DEPTH */
- if (ctx->Depth.Test)
- lookup |= IZ_DEPTH_TEST_ENABLE_BIT;
-
- if (ctx->Depth.Test && ctx->Depth.Mask) /* ?? */
- lookup |= IZ_DEPTH_WRITE_ENABLE_BIT;
-
- /* _NEW_STENCIL | _NEW_BUFFERS */
- if (ctx->Stencil._Enabled) {
- lookup |= IZ_STENCIL_TEST_ENABLE_BIT;
-
- if (ctx->Stencil.WriteMask[0] ||
- ctx->Stencil.WriteMask[ctx->Stencil._BackFace])
- lookup |= IZ_STENCIL_WRITE_ENABLE_BIT;
- }
- key->iz_lookup = lookup;
- }
-
- line_aa = AA_NEVER;
-
- /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */
- if (ctx->Line.SmoothFlag) {
- if (brw->reduced_primitive == GL_LINES) {
- line_aa = AA_ALWAYS;
- }
- else if (brw->reduced_primitive == GL_TRIANGLES) {
- if (ctx->Polygon.FrontMode == GL_LINE) {
- line_aa = AA_SOMETIMES;
-
- if (ctx->Polygon.BackMode == GL_LINE ||
- (ctx->Polygon.CullFlag &&
- ctx->Polygon.CullFaceMode == GL_BACK))
- line_aa = AA_ALWAYS;
- }
- else if (ctx->Polygon.BackMode == GL_LINE) {
- line_aa = AA_SOMETIMES;
-
- if ((ctx->Polygon.CullFlag &&
- ctx->Polygon.CullFaceMode == GL_FRONT))
- line_aa = AA_ALWAYS;
- }
- }
- }
-
- key->line_aa = line_aa;
-
- /* _NEW_HINT */
- key->high_quality_derivatives =
- ctx->Hint.FragmentShaderDerivative == GL_NICEST;
-
- if (brw->gen < 6)
- key->stats_wm = brw->stats_wm;
-
- /* _NEW_LIGHT */
- key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT);
-
- /* _NEW_FRAG_CLAMP | _NEW_BUFFERS */
- key->clamp_fragment_color = ctx->Color._ClampFragmentColor;
-
- /* _NEW_TEXTURE */
- brw_populate_sampler_prog_key_data(ctx, prog, brw->wm.base.sampler_count,
- &key->tex);
-
- /* _NEW_BUFFERS */
- /*
- * Include the draw buffer origin and height so that we can calculate
- * fragment position values relative to the bottom left of the drawable,
- * from the incoming screen origin relative position we get as part of our
- * payload.
- *
- * This is only needed for the WM_WPOSXY opcode when the fragment program
- * uses the gl_FragCoord input.
- *
- * We could avoid recompiling by including this as a constant referenced by
- * our program, but if we were to do that it would also be nice to handle
- * getting that constant updated at batchbuffer submit time (when we
- * hold the lock and know where the buffer really is) rather than at emit
- * time when we don't hold the lock and are just guessing. We could also
- * just avoid using this as key data if the program doesn't use
- * fragment.position.
- *
- * For DRI2 the origin_x/y will always be (0,0) but we still need the
- * drawable height in order to invert the Y axis.
- */
- if (fp->program.Base.InputsRead & VARYING_BIT_POS) {
- key->drawable_height = ctx->DrawBuffer->Height;
- }
-
- if ((fp->program.Base.InputsRead & VARYING_BIT_POS) || program_uses_dfdy) {
- key->render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer);
- }
-
- /* _NEW_BUFFERS */
- key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers;
-
- /* _NEW_MULTISAMPLE, _NEW_COLOR, _NEW_BUFFERS */
- key->replicate_alpha = ctx->DrawBuffer->_NumColorDrawBuffers > 1 &&
- (ctx->Multisample.SampleAlphaToCoverage || ctx->Color.AlphaEnabled);
-
- /* _NEW_BUFFERS _NEW_MULTISAMPLE */
- /* Ignore sample qualifier while computing this flag. */
- key->persample_shading =
- _mesa_get_min_invocations_per_fragment(ctx, &fp->program, true) > 1;
- if (key->persample_shading)
- key->persample_2x = ctx->DrawBuffer->Visual.samples == 2;
-
- key->compute_pos_offset =
- _mesa_get_min_invocations_per_fragment(ctx, &fp->program, false) > 1 &&
- fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_POS;
-
- key->compute_sample_id =
- multisample_fbo &&
- ctx->Multisample.Enabled &&
- (fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_ID);
-
- /* BRW_NEW_VUE_MAP_GEOM_OUT */
- if (brw->gen < 6 || _mesa_bitcount_64(fp->program.Base.InputsRead &
- BRW_FS_VARYING_INPUT_MASK) > 16)
- key->input_slots_valid = brw->vue_map_geom_out.slots_valid;
-
-
- /* _NEW_COLOR | _NEW_BUFFERS */
- /* Pre-gen6, the hardware alpha test always used each render
- * target's alpha to do alpha test, as opposed to render target 0's alpha
- * like GL requires. Fix that by building the alpha test into the
- * shader, and we'll skip enabling the fixed function alpha test.
- */
- if (brw->gen < 6 && ctx->DrawBuffer->_NumColorDrawBuffers > 1 && ctx->Color.AlphaEnabled) {
- key->alpha_test_func = ctx->Color.AlphaFunc;
- key->alpha_test_ref = ctx->Color.AlphaRef;
- }
-
- /* The unique fragment program ID */
- key->program_string_id = fp->id;
-
- ctx->DrawBuffer = NULL;
-}
-
-static uint8_t
-computed_depth_mode(struct gl_fragment_program *fp)
-{
- if (fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
- switch (fp->FragDepthLayout) {
- case FRAG_DEPTH_LAYOUT_NONE:
- case FRAG_DEPTH_LAYOUT_ANY:
- return BRW_PSCDEPTH_ON;
- case FRAG_DEPTH_LAYOUT_GREATER:
- return BRW_PSCDEPTH_ON_GE;
- case FRAG_DEPTH_LAYOUT_LESS:
- return BRW_PSCDEPTH_ON_LE;
- case FRAG_DEPTH_LAYOUT_UNCHANGED:
- return BRW_PSCDEPTH_OFF;
- }
- }
- return BRW_PSCDEPTH_OFF;
-}
-
-static bool
-really_do_wm_prog(struct brw_context *brw,
- struct gl_shader_program *prog,
- struct brw_fragment_program *fp,
- struct brw_wm_prog_key *key, struct anv_pipeline *pipeline)
-{
- struct gl_context *ctx = &brw->ctx;
- void *mem_ctx = ralloc_context(NULL);
- struct brw_wm_prog_data *prog_data = &pipeline->wm_prog_data;
- struct gl_shader *fs = NULL;
- unsigned int program_size;
- const uint32_t *program;
-
- if (prog)
- fs = prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
-
- memset(prog_data, 0, sizeof(*prog_data));
-
- /* key->alpha_test_func means simulating alpha testing via discards,
- * so the shader definitely kills pixels.
- */
- prog_data->uses_kill = fp->program.UsesKill || key->alpha_test_func;
-
- prog_data->computed_depth_mode = computed_depth_mode(&fp->program);
-
- /* Allocate the references to the uniforms that will end up in the
- * prog_data associated with the compiled program, and which will be freed
- * by the state cache.
- */
- int param_count;
- if (fs) {
- param_count = fs->num_uniform_components;
- } else {
- param_count = fp->program.Base.Parameters->NumParameters * 4;
- }
- /* The backend also sometimes adds params for texture size. */
- param_count += 2 * ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits;
- prog_data->base.param =
- rzalloc_array(NULL, const gl_constant_value *, param_count);
- prog_data->base.pull_param =
- rzalloc_array(NULL, const gl_constant_value *, param_count);
- prog_data->base.nr_params = param_count;
-
- prog_data->barycentric_interp_modes =
- brw_compute_barycentric_interp_modes(brw, key->flat_shade,
- key->persample_shading,
- &fp->program);
-
- set_binding_table_layout(&prog_data->base, pipeline,
- VK_SHADER_STAGE_FRAGMENT);
- /* This needs to come after shader time and pull constant entries, but we
- * don't have those set up now, so just put it after the layout entries.
- */
- prog_data->binding_table.render_target_start = 0;
-
- program = brw_wm_fs_emit(brw, mem_ctx, key, prog_data,
- &fp->program, prog, &program_size);
- if (program == NULL) {
- ralloc_free(mem_ctx);
- return false;
- }
-
- struct anv_state ps_state = anv_state_stream_alloc(&pipeline->program_stream,
- program_size, 64);
- memcpy(ps_state.map, program, program_size);
-
- if (prog_data->no_8)
- pipeline->ps_simd8 = NO_KERNEL;
- else
- pipeline->ps_simd8 = ps_state.offset;
-
- if (prog_data->no_8 || prog_data->prog_offset_16) {
- pipeline->ps_simd16 = ps_state.offset + prog_data->prog_offset_16;
- } else {
- pipeline->ps_simd16 = NO_KERNEL;
- }
-
- ralloc_free(mem_ctx);
-
- return true;
-}
-
-static void
-brw_gs_populate_key(struct brw_context *brw,
- struct anv_pipeline *pipeline,
- struct brw_geometry_program *gp,
- struct brw_gs_prog_key *key)
-{
- struct gl_context *ctx = &brw->ctx;
- struct brw_stage_state *stage_state = &brw->gs.base;
- struct gl_program *prog = &gp->program.Base;
-
- memset(key, 0, sizeof(*key));
-
- key->base.program_string_id = gp->id;
- brw_setup_vue_key_clip_info(brw, &key->base,
- gp->program.Base.UsesClipDistanceOut);
-
- /* _NEW_TEXTURE */
- brw_populate_sampler_prog_key_data(ctx, prog, stage_state->sampler_count,
- &key->base.tex);
-
- struct brw_vs_prog_data *prog_data = &pipeline->vs_prog_data;
-
- /* BRW_NEW_VUE_MAP_VS */
- key->input_varyings = prog_data->base.vue_map.slots_valid;
-}
-
-static bool
-really_do_gs_prog(struct brw_context *brw,
- struct gl_shader_program *prog,
- struct brw_geometry_program *gp,
- struct brw_gs_prog_key *key, struct anv_pipeline *pipeline)
-{
- struct brw_gs_compile_output output;
-
- /* FIXME: We pass the bind map to the compile in the output struct. Need
- * something better. */
- set_binding_table_layout(&output.prog_data.base.base,
- pipeline, VK_SHADER_STAGE_GEOMETRY);
-
- brw_compile_gs_prog(brw, prog, gp, key, &output);
-
- struct anv_state gs_state = anv_state_stream_alloc(&pipeline->program_stream,
- output.program_size, 64);
- memcpy(gs_state.map, output.program, output.program_size);
-
- pipeline->gs_vec4 = gs_state.offset;
- pipeline->gs_vertex_count = gp->program.VerticesIn;
-
- ralloc_free(output.mem_ctx);
-
- return true;
-}
-
-static bool
-brw_codegen_cs_prog(struct brw_context *brw,
- struct gl_shader_program *prog,
- struct brw_compute_program *cp,
- struct brw_cs_prog_key *key, struct anv_pipeline *pipeline)
-{
- struct gl_context *ctx = &brw->ctx;
- const GLuint *program;
- void *mem_ctx = ralloc_context(NULL);
- GLuint program_size;
- struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
-
- struct gl_shader *cs = prog->_LinkedShaders[MESA_SHADER_COMPUTE];
- assert (cs);
-
- memset(prog_data, 0, sizeof(*prog_data));
-
- set_binding_table_layout(&prog_data->base, pipeline, VK_SHADER_STAGE_COMPUTE);
-
- /* Allocate the references to the uniforms that will end up in the
- * prog_data associated with the compiled program, and which will be freed
- * by the state cache.
- */
- int param_count = cs->num_uniform_components;
-
- /* The backend also sometimes adds params for texture size. */
- param_count += 2 * ctx->Const.Program[MESA_SHADER_COMPUTE].MaxTextureImageUnits;
- prog_data->base.param =
- rzalloc_array(NULL, const gl_constant_value *, param_count);
- prog_data->base.pull_param =
- rzalloc_array(NULL, const gl_constant_value *, param_count);
- prog_data->base.nr_params = param_count;
-
- program = brw_cs_emit(brw, mem_ctx, key, prog_data,
- &cp->program, prog, &program_size);
- if (program == NULL) {
- ralloc_free(mem_ctx);
- return false;
- }
-
- if (unlikely(INTEL_DEBUG & DEBUG_CS))
- fprintf(stderr, "\n");
-
- struct anv_state cs_state = anv_state_stream_alloc(&pipeline->program_stream,
- program_size, 64);
- memcpy(cs_state.map, program, program_size);
-
- pipeline->cs_simd = cs_state.offset;
-
- ralloc_free(mem_ctx);
-
- return true;
-}
-
-static void
-brw_cs_populate_key(struct brw_context *brw,
- struct brw_compute_program *bcp, struct brw_cs_prog_key *key)
-{
- memset(key, 0, sizeof(*key));
-
- /* The unique compute program ID */
- key->program_string_id = bcp->id;
-}
-
-static void
-fail_on_compile_error(int status, const char *msg)
-{
- int source, line, column;
- char error[256];
-
- if (status)
- return;
-
- if (sscanf(msg, "%d:%d(%d): error: %255[^\n]", &source, &line, &column, error) == 4)
- fail_if(!status, "%d:%s\n", line, error);
- else
- fail_if(!status, "%s\n", msg);
-}
-
-struct anv_compiler {
- struct anv_device *device;
- struct intel_screen *screen;
- struct brw_context *brw;
- struct gl_pipeline_object pipeline;
-};
-
-extern "C" {
-
-struct anv_compiler *
-anv_compiler_create(struct anv_device *device)
-{
- const struct brw_device_info *devinfo = &device->info;
- struct anv_compiler *compiler;
- struct gl_context *ctx;
-
- compiler = rzalloc(NULL, struct anv_compiler);
- if (compiler == NULL)
- return NULL;
-
- compiler->screen = rzalloc(compiler, struct intel_screen);
- if (compiler->screen == NULL)
- goto fail;
-
- compiler->brw = rzalloc(compiler, struct brw_context);
- if (compiler->brw == NULL)
- goto fail;
-
- compiler->device = device;
-
- compiler->brw->optionCache.info = NULL;
- compiler->brw->bufmgr = NULL;
- compiler->brw->gen = devinfo->gen;
- compiler->brw->is_g4x = devinfo->is_g4x;
- compiler->brw->is_baytrail = devinfo->is_baytrail;
- compiler->brw->is_haswell = devinfo->is_haswell;
- compiler->brw->is_cherryview = devinfo->is_cherryview;
-
- /* We need this at least for CS, which will check brw->max_cs_threads
- * against the work group size. */
- compiler->brw->max_vs_threads = devinfo->max_vs_threads;
- compiler->brw->max_hs_threads = devinfo->max_hs_threads;
- compiler->brw->max_ds_threads = devinfo->max_ds_threads;
- compiler->brw->max_gs_threads = devinfo->max_gs_threads;
- compiler->brw->max_wm_threads = devinfo->max_wm_threads;
- compiler->brw->max_cs_threads = devinfo->max_cs_threads;
- compiler->brw->urb.size = devinfo->urb.size;
- compiler->brw->urb.min_vs_entries = devinfo->urb.min_vs_entries;
- compiler->brw->urb.max_vs_entries = devinfo->urb.max_vs_entries;
- compiler->brw->urb.max_hs_entries = devinfo->urb.max_hs_entries;
- compiler->brw->urb.max_ds_entries = devinfo->urb.max_ds_entries;
- compiler->brw->urb.max_gs_entries = devinfo->urb.max_gs_entries;
-
- compiler->brw->intelScreen = compiler->screen;
- compiler->screen->devinfo = &device->info;
-
- brw_process_intel_debug_variable(compiler->screen);
-
- compiler->screen->compiler = brw_compiler_create(compiler, &device->info);
-
- ctx = &compiler->brw->ctx;
- _mesa_init_shader_object_functions(&ctx->Driver);
-
- _mesa_init_constants(&ctx->Const, API_OPENGL_CORE);
-
- brw_initialize_context_constants(compiler->brw);
-
- intelInitExtensions(ctx);
-
- /* Set dd::NewShader */
- brwInitFragProgFuncs(&ctx->Driver);
-
- ctx->_Shader = &compiler->pipeline;
-
- compiler->brw->precompile = false;
-
- return compiler;
-
- fail:
- ralloc_free(compiler);
- return NULL;
-}
-
-void
-anv_compiler_destroy(struct anv_compiler *compiler)
-{
- _mesa_free_errors_data(&compiler->brw->ctx);
- ralloc_free(compiler);
-}
-
-/* From gen7_urb.c */
-
-/* FIXME: Add to struct intel_device_info */
-
-static const int gen8_push_size = 32 * 1024;
-
-static void
-gen7_compute_urb_partition(struct anv_pipeline *pipeline)
-{
- const struct brw_device_info *devinfo = &pipeline->device->info;
- bool vs_present = pipeline->vs_simd8 != NO_KERNEL;
- unsigned vs_size = vs_present ? pipeline->vs_prog_data.base.urb_entry_size : 1;
- unsigned vs_entry_size_bytes = vs_size * 64;
- bool gs_present = pipeline->gs_vec4 != NO_KERNEL;
- unsigned gs_size = gs_present ? pipeline->gs_prog_data.base.urb_entry_size : 1;
- unsigned gs_entry_size_bytes = gs_size * 64;
-
- /* From p35 of the Ivy Bridge PRM (section 1.7.1: 3DSTATE_URB_GS):
- *
- * VS Number of URB Entries must be divisible by 8 if the VS URB Entry
- * Allocation Size is less than 9 512-bit URB entries.
- *
- * Similar text exists for GS.
- */
- unsigned vs_granularity = (vs_size < 9) ? 8 : 1;
- unsigned gs_granularity = (gs_size < 9) ? 8 : 1;
-
- /* URB allocations must be done in 8k chunks. */
- unsigned chunk_size_bytes = 8192;
-
- /* Determine the size of the URB in chunks. */
- unsigned urb_chunks = devinfo->urb.size * 1024 / chunk_size_bytes;
-
- /* Reserve space for push constants */
- unsigned push_constant_bytes = gen8_push_size;
- unsigned push_constant_chunks =
- push_constant_bytes / chunk_size_bytes;
-
- /* Initially, assign each stage the minimum amount of URB space it needs,
- * and make a note of how much additional space it "wants" (the amount of
- * additional space it could actually make use of).
- */
-
- /* VS has a lower limit on the number of URB entries */
- unsigned vs_chunks =
- ALIGN(devinfo->urb.min_vs_entries * vs_entry_size_bytes,
- chunk_size_bytes) / chunk_size_bytes;
- unsigned vs_wants =
- ALIGN(devinfo->urb.max_vs_entries * vs_entry_size_bytes,
- chunk_size_bytes) / chunk_size_bytes - vs_chunks;
-
- unsigned gs_chunks = 0;
- unsigned gs_wants = 0;
- if (gs_present) {
- /* There are two constraints on the minimum amount of URB space we can
- * allocate:
- *
- * (1) We need room for at least 2 URB entries, since we always operate
- * the GS in DUAL_OBJECT mode.
- *
- * (2) We can't allocate less than nr_gs_entries_granularity.
- */
- gs_chunks = ALIGN(MAX2(gs_granularity, 2) * gs_entry_size_bytes,
- chunk_size_bytes) / chunk_size_bytes;
- gs_wants =
- ALIGN(devinfo->urb.max_gs_entries * gs_entry_size_bytes,
- chunk_size_bytes) / chunk_size_bytes - gs_chunks;
- }
-
- /* There should always be enough URB space to satisfy the minimum
- * requirements of each stage.
- */
- unsigned total_needs = push_constant_chunks + vs_chunks + gs_chunks;
- assert(total_needs <= urb_chunks);
-
- /* Mete out remaining space (if any) in proportion to "wants". */
- unsigned total_wants = vs_wants + gs_wants;
- unsigned remaining_space = urb_chunks - total_needs;
- if (remaining_space > total_wants)
- remaining_space = total_wants;
- if (remaining_space > 0) {
- unsigned vs_additional = (unsigned)
- round(vs_wants * (((double) remaining_space) / total_wants));
- vs_chunks += vs_additional;
- remaining_space -= vs_additional;
- gs_chunks += remaining_space;
- }
-
- /* Sanity check that we haven't over-allocated. */
- assert(push_constant_chunks + vs_chunks + gs_chunks <= urb_chunks);
-
- /* Finally, compute the number of entries that can fit in the space
- * allocated to each stage.
- */
- unsigned nr_vs_entries = vs_chunks * chunk_size_bytes / vs_entry_size_bytes;
- unsigned nr_gs_entries = gs_chunks * chunk_size_bytes / gs_entry_size_bytes;
-
- /* Since we rounded up when computing *_wants, this may be slightly more
- * than the maximum allowed amount, so correct for that.
- */
- nr_vs_entries = MIN2(nr_vs_entries, devinfo->urb.max_vs_entries);
- nr_gs_entries = MIN2(nr_gs_entries, devinfo->urb.max_gs_entries);
-
- /* Ensure that we program a multiple of the granularity. */
- nr_vs_entries = ROUND_DOWN_TO(nr_vs_entries, vs_granularity);
- nr_gs_entries = ROUND_DOWN_TO(nr_gs_entries, gs_granularity);
-
- /* Finally, sanity check to make sure we have at least the minimum number
- * of entries needed for each stage.
- */
- assert(nr_vs_entries >= devinfo->urb.min_vs_entries);
- if (gs_present)
- assert(nr_gs_entries >= 2);
-
- /* Lay out the URB in the following order:
- * - push constants
- * - VS
- * - GS
- */
- pipeline->urb.vs_start = push_constant_chunks;
- pipeline->urb.vs_size = vs_size;
- pipeline->urb.nr_vs_entries = nr_vs_entries;
-
- pipeline->urb.gs_start = push_constant_chunks + vs_chunks;
- pipeline->urb.gs_size = gs_size;
- pipeline->urb.nr_gs_entries = nr_gs_entries;
-}
-
-static const struct {
- uint32_t token;
- gl_shader_stage stage;
- const char *name;
-} stage_info[] = {
- { GL_VERTEX_SHADER, MESA_SHADER_VERTEX, "vertex" },
- { GL_TESS_CONTROL_SHADER, (gl_shader_stage)-1,"tess control" },
- { GL_TESS_EVALUATION_SHADER, (gl_shader_stage)-1, "tess evaluation" },
- { GL_GEOMETRY_SHADER, MESA_SHADER_GEOMETRY, "geometry" },
- { GL_FRAGMENT_SHADER, MESA_SHADER_FRAGMENT, "fragment" },
- { GL_COMPUTE_SHADER, MESA_SHADER_COMPUTE, "compute" },
-};
-
-struct spirv_header{
- uint32_t magic;
- uint32_t version;
- uint32_t gen_magic;
-};
-
-static const char *
-src_as_glsl(const char *data)
-{
- const struct spirv_header *as_spirv = (const struct spirv_header *)data;
-
- /* Check alignment */
- if ((intptr_t)data & 0x3) {
- return data;
- }
-
- if (as_spirv->magic == SPIR_V_MAGIC_NUMBER) {
- /* LunarG back-door */
- if (as_spirv->version == 0)
- return data + 12;
- else
- return NULL;
- } else {
- return data;
- }
-}
-
-static void
-anv_compile_shader_glsl(struct anv_compiler *compiler,
- struct gl_shader_program *program,
- struct anv_pipeline *pipeline, uint32_t stage)
-{
- struct brw_context *brw = compiler->brw;
- struct gl_shader *shader;
- int name = 0;
-
- shader = brw_new_shader(&brw->ctx, name, stage_info[stage].token);
- fail_if(shader == NULL, "failed to create %s shader\n", stage_info[stage].name);
-
- shader->Source = strdup(src_as_glsl(pipeline->shaders[stage]->module->data));
- _mesa_glsl_compile_shader(&brw->ctx, shader, false, false);
- fail_on_compile_error(shader->CompileStatus, shader->InfoLog);
-
- program->Shaders[program->NumShaders] = shader;
- program->NumShaders++;
-}
-
-static void
-setup_nir_io(struct gl_program *prog,
- nir_shader *shader)
-{
- foreach_list_typed(nir_variable, var, node, &shader->inputs) {
- prog->InputsRead |= BITFIELD64_BIT(var->data.location);
- }
-
- foreach_list_typed(nir_variable, var, node, &shader->outputs) {
- prog->OutputsWritten |= BITFIELD64_BIT(var->data.location);
- }
-}
-
-static void
-anv_compile_shader_spirv(struct anv_compiler *compiler,
- struct gl_shader_program *program,
- struct anv_pipeline *pipeline, uint32_t stage)
-{
- struct brw_context *brw = compiler->brw;
- struct anv_shader *shader = pipeline->shaders[stage];
- struct gl_shader *mesa_shader;
- int name = 0;
-
- mesa_shader = brw_new_shader(&brw->ctx, name, stage_info[stage].token);
- fail_if(mesa_shader == NULL,
- "failed to create %s shader\n", stage_info[stage].name);
-
- switch (stage) {
- case VK_SHADER_STAGE_VERTEX:
- mesa_shader->Program = &rzalloc(mesa_shader, struct brw_vertex_program)->program.Base;
- break;
- case VK_SHADER_STAGE_GEOMETRY:
- mesa_shader->Program = &rzalloc(mesa_shader, struct brw_geometry_program)->program.Base;
- break;
- case VK_SHADER_STAGE_FRAGMENT:
- mesa_shader->Program = &rzalloc(mesa_shader, struct brw_fragment_program)->program.Base;
- break;
- case VK_SHADER_STAGE_COMPUTE:
- mesa_shader->Program = &rzalloc(mesa_shader, struct brw_compute_program)->program.Base;
- break;
- }
-
- mesa_shader->Program->Parameters =
- rzalloc(mesa_shader, struct gl_program_parameter_list);
-
- mesa_shader->Type = stage_info[stage].token;
- mesa_shader->Stage = stage_info[stage].stage;
-
- assert(shader->module->size % 4 == 0);
-
- struct gl_shader_compiler_options *glsl_options =
- &compiler->screen->compiler->glsl_compiler_options[stage_info[stage].stage];
-
- mesa_shader->Program->nir =
- spirv_to_nir((uint32_t *)shader->module->data, shader->module->size / 4,
- glsl_options->NirOptions);
- nir_validate_shader(mesa_shader->Program->nir);
-
- brw_process_nir(mesa_shader->Program->nir,
- compiler->screen->devinfo,
- NULL, mesa_shader->Stage);
-
- setup_nir_io(mesa_shader->Program, mesa_shader->Program->nir);
-
- fail_if(mesa_shader->Program->nir == NULL,
- "failed to translate SPIR-V to NIR\n");
-
- program->Shaders[program->NumShaders] = mesa_shader;
- program->NumShaders++;
-}
-
-static void
-add_compiled_stage(struct anv_pipeline *pipeline, uint32_t stage,
- struct brw_stage_prog_data *prog_data)
-{
- struct brw_device_info *devinfo = &pipeline->device->info;
- uint32_t max_threads[] = {
- [VK_SHADER_STAGE_VERTEX] = devinfo->max_vs_threads,
- [VK_SHADER_STAGE_TESS_CONTROL] = 0,
- [VK_SHADER_STAGE_TESS_EVALUATION] = 0,
- [VK_SHADER_STAGE_GEOMETRY] = devinfo->max_gs_threads,
- [VK_SHADER_STAGE_FRAGMENT] = devinfo->max_wm_threads,
- [VK_SHADER_STAGE_COMPUTE] = devinfo->max_cs_threads,
- };
-
- pipeline->prog_data[stage] = prog_data;
- pipeline->active_stages |= 1 << stage;
- pipeline->scratch_start[stage] = pipeline->total_scratch;
- pipeline->total_scratch =
- align_u32(pipeline->total_scratch, 1024) +
- prog_data->total_scratch * max_threads[stage];
-}
-
-int
-anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline)
-{
- struct gl_shader_program *program;
- int name = 0;
- struct brw_context *brw = compiler->brw;
-
- pipeline->writes_point_size = false;
-
- /* When we free the pipeline, we detect stages based on the NULL status
- * of various prog_data pointers. Make them NULL by default.
- */
- memset(pipeline->prog_data, 0, sizeof(pipeline->prog_data));
- memset(pipeline->scratch_start, 0, sizeof(pipeline->scratch_start));
-
- brw->use_rep_send = pipeline->use_repclear;
- brw->no_simd8 = pipeline->use_repclear;
-
- program = brw->ctx.Driver.NewShaderProgram(name);
- program->Shaders = (struct gl_shader **)
- calloc(VK_SHADER_STAGE_NUM, sizeof(struct gl_shader *));
- fail_if(program == NULL || program->Shaders == NULL,
- "failed to create program\n");
-
- bool all_spirv = true;
- for (unsigned i = 0; i < VK_SHADER_STAGE_NUM; i++) {
- if (pipeline->shaders[i] == NULL)
- continue;
-
- /* You need at least this much for "void main() { }" anyway */
- assert(pipeline->shaders[i]->module->size >= 12);
-
- if (src_as_glsl(pipeline->shaders[i]->module->data)) {
- all_spirv = false;
- break;
- }
-
- assert(pipeline->shaders[i]->module->size % 4 == 0);
- }
-
- if (all_spirv) {
- for (unsigned i = 0; i < VK_SHADER_STAGE_NUM; i++) {
- if (pipeline->shaders[i])
- anv_compile_shader_spirv(compiler, program, pipeline, i);
- }
-
- for (unsigned i = 0; i < program->NumShaders; i++) {
- struct gl_shader *shader = program->Shaders[i];
- program->_LinkedShaders[shader->Stage] = shader;
- }
- } else {
- for (unsigned i = 0; i < VK_SHADER_STAGE_NUM; i++) {
- if (pipeline->shaders[i])
- anv_compile_shader_glsl(compiler, program, pipeline, i);
- }
-
- _mesa_glsl_link_shader(&brw->ctx, program);
- fail_on_compile_error(program->LinkStatus,
- program->InfoLog);
- }
-
- bool success;
- pipeline->active_stages = 0;
- pipeline->total_scratch = 0;
-
- if (pipeline->shaders[VK_SHADER_STAGE_VERTEX]) {
- struct brw_vs_prog_key vs_key;
- struct gl_vertex_program *vp = (struct gl_vertex_program *)
- program->_LinkedShaders[MESA_SHADER_VERTEX]->Program;
- struct brw_vertex_program *bvp = brw_vertex_program(vp);
-
- brw_vs_populate_key(brw, bvp, &vs_key);
-
- success = really_do_vs_prog(brw, program, bvp, &vs_key, pipeline);
- fail_if(!success, "do_wm_prog failed\n");
- add_compiled_stage(pipeline, VK_SHADER_STAGE_VERTEX,
- &pipeline->vs_prog_data.base.base);
-
- if (vp->Base.OutputsWritten & VARYING_SLOT_PSIZ)
- pipeline->writes_point_size = true;
- } else {
- memset(&pipeline->vs_prog_data, 0, sizeof(pipeline->vs_prog_data));
- pipeline->vs_simd8 = NO_KERNEL;
- }
-
-
- if (pipeline->shaders[VK_SHADER_STAGE_GEOMETRY]) {
- struct brw_gs_prog_key gs_key;
- struct gl_geometry_program *gp = (struct gl_geometry_program *)
- program->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program;
- struct brw_geometry_program *bgp = brw_geometry_program(gp);
-
- brw_gs_populate_key(brw, pipeline, bgp, &gs_key);
-
- success = really_do_gs_prog(brw, program, bgp, &gs_key, pipeline);
- fail_if(!success, "do_gs_prog failed\n");
- add_compiled_stage(pipeline, VK_SHADER_STAGE_GEOMETRY,
- &pipeline->gs_prog_data.base.base);
-
- if (gp->Base.OutputsWritten & VARYING_SLOT_PSIZ)
- pipeline->writes_point_size = true;
- } else {
- pipeline->gs_vec4 = NO_KERNEL;
- }
-
- if (pipeline->shaders[VK_SHADER_STAGE_FRAGMENT]) {
- struct brw_wm_prog_key wm_key;
- struct gl_fragment_program *fp = (struct gl_fragment_program *)
- program->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program;
- struct brw_fragment_program *bfp = brw_fragment_program(fp);
-
- brw_wm_populate_key(brw, bfp, &wm_key);
-
- success = really_do_wm_prog(brw, program, bfp, &wm_key, pipeline);
- fail_if(!success, "do_wm_prog failed\n");
- add_compiled_stage(pipeline, VK_SHADER_STAGE_FRAGMENT,
- &pipeline->wm_prog_data.base);
- }
-
- if (pipeline->shaders[VK_SHADER_STAGE_COMPUTE]) {
- struct brw_cs_prog_key cs_key;
- struct gl_compute_program *cp = (struct gl_compute_program *)
- program->_LinkedShaders[MESA_SHADER_COMPUTE]->Program;
- struct brw_compute_program *bcp = brw_compute_program(cp);
-
- brw_cs_populate_key(brw, bcp, &cs_key);
-
- success = brw_codegen_cs_prog(brw, program, bcp, &cs_key, pipeline);
- fail_if(!success, "brw_codegen_cs_prog failed\n");
- add_compiled_stage(pipeline, VK_SHADER_STAGE_COMPUTE,
- &pipeline->cs_prog_data.base);
- }
-
- /* XXX: Deleting the shader is broken with our current SPIR-V hacks. We
- * need to fix this ASAP.
- */
- if (!all_spirv)
- brw->ctx.Driver.DeleteShaderProgram(&brw->ctx, program);
-
- struct anv_device *device = compiler->device;
- while (device->scratch_block_pool.bo.size < pipeline->total_scratch)
- anv_block_pool_alloc(&device->scratch_block_pool);
-
- gen7_compute_urb_partition(pipeline);
-
- return 0;
-}
-
-/* This badly named function frees the struct anv_pipeline data that the compiler
- * allocates. Currently just the prog_data structs.
- */
-void
-anv_compiler_free(struct anv_pipeline *pipeline)
-{
- for (uint32_t stage = 0; stage < VK_SHADER_STAGE_NUM; stage++) {
- if (pipeline->prog_data[stage]) {
- free(pipeline->prog_data[stage]->map_entries);
- ralloc_free(pipeline->prog_data[stage]->param);
- ralloc_free(pipeline->prog_data[stage]->pull_param);
- }
- }
-}
-
-}
+++ /dev/null
-/*
- * 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 <assert.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "private.h"
-#include "mesa/main/git_sha1.h"
-
-static int
-anv_env_get_int(const char *name)
-{
- const char *val = getenv(name);
-
- if (!val)
- return 0;
-
- return strtol(val, NULL, 0);
-}
-
-static void
-anv_physical_device_finish(struct anv_physical_device *device)
-{
- if (device->fd >= 0)
- close(device->fd);
-}
-
-static VkResult
-anv_physical_device_init(struct anv_physical_device *device,
- struct anv_instance *instance,
- const char *path)
-{
- device->fd = open(path, O_RDWR | O_CLOEXEC);
- if (device->fd < 0)
- return vk_error(VK_ERROR_UNAVAILABLE);
-
- device->instance = instance;
- device->path = path;
-
- device->chipset_id = anv_env_get_int("INTEL_DEVID_OVERRIDE");
- device->no_hw = false;
- if (device->chipset_id) {
- /* INTEL_DEVID_OVERRIDE implies INTEL_NO_HW. */
- device->no_hw = true;
- } else {
- device->chipset_id = anv_gem_get_param(device->fd, I915_PARAM_CHIPSET_ID);
- }
- if (!device->chipset_id)
- goto fail;
-
- device->name = brw_get_device_name(device->chipset_id);
- device->info = brw_get_device_info(device->chipset_id, -1);
- if (!device->info)
- goto fail;
-
- if (!anv_gem_get_param(device->fd, I915_PARAM_HAS_WAIT_TIMEOUT))
- goto fail;
-
- if (!anv_gem_get_param(device->fd, I915_PARAM_HAS_EXECBUF2))
- goto fail;
-
- if (!anv_gem_get_param(device->fd, I915_PARAM_HAS_LLC))
- goto fail;
-
- if (!anv_gem_get_param(device->fd, I915_PARAM_HAS_EXEC_CONSTANTS))
- goto fail;
-
- return VK_SUCCESS;
-
-fail:
- anv_physical_device_finish(device);
- return vk_error(VK_ERROR_UNAVAILABLE);
-}
-
-static void *default_alloc(
- void* pUserData,
- size_t size,
- size_t alignment,
- VkSystemAllocType allocType)
-{
- return malloc(size);
-}
-
-static void default_free(
- void* pUserData,
- void* pMem)
-{
- free(pMem);
-}
-
-static const VkAllocCallbacks default_alloc_callbacks = {
- .pUserData = NULL,
- .pfnAlloc = default_alloc,
- .pfnFree = default_free
-};
-
-VkResult anv_CreateInstance(
- const VkInstanceCreateInfo* pCreateInfo,
- VkInstance* pInstance)
-{
- struct anv_instance *instance;
- const VkAllocCallbacks *alloc_callbacks = &default_alloc_callbacks;
- void *user_data = NULL;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
-
- if (pCreateInfo->pAllocCb) {
- alloc_callbacks = pCreateInfo->pAllocCb;
- user_data = pCreateInfo->pAllocCb->pUserData;
- }
- instance = alloc_callbacks->pfnAlloc(user_data, sizeof(*instance), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (!instance)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- instance->pAllocUserData = alloc_callbacks->pUserData;
- instance->pfnAlloc = alloc_callbacks->pfnAlloc;
- instance->pfnFree = alloc_callbacks->pfnFree;
- instance->apiVersion = pCreateInfo->pAppInfo->apiVersion;
- instance->physicalDeviceCount = 0;
-
- *pInstance = anv_instance_to_handle(instance);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyInstance(
- VkInstance _instance)
-{
- ANV_FROM_HANDLE(anv_instance, instance, _instance);
-
- if (instance->physicalDeviceCount > 0) {
- anv_physical_device_finish(&instance->physicalDevice);
- }
-
- instance->pfnFree(instance->pAllocUserData, instance);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_EnumeratePhysicalDevices(
- VkInstance _instance,
- uint32_t* pPhysicalDeviceCount,
- VkPhysicalDevice* pPhysicalDevices)
-{
- ANV_FROM_HANDLE(anv_instance, instance, _instance);
- VkResult result;
-
- if (instance->physicalDeviceCount == 0) {
- result = anv_physical_device_init(&instance->physicalDevice,
- instance, "/dev/dri/renderD128");
- if (result != VK_SUCCESS)
- return result;
-
- instance->physicalDeviceCount = 1;
- }
-
- /* pPhysicalDeviceCount is an out parameter if pPhysicalDevices is NULL;
- * otherwise it's an inout parameter.
- *
- * The Vulkan spec (git aaed022) says:
- *
- * pPhysicalDeviceCount is a pointer to an unsigned integer variable
- * that is initialized with the number of devices the application is
- * prepared to receive handles to. pname:pPhysicalDevices is pointer to
- * an array of at least this many VkPhysicalDevice handles [...].
- *
- * Upon success, if pPhysicalDevices is NULL, vkEnumeratePhysicalDevices
- * overwrites the contents of the variable pointed to by
- * pPhysicalDeviceCount with the number of physical devices in in the
- * instance; otherwise, vkEnumeratePhysicalDevices overwrites
- * pPhysicalDeviceCount with the number of physical handles written to
- * pPhysicalDevices.
- */
- if (!pPhysicalDevices) {
- *pPhysicalDeviceCount = instance->physicalDeviceCount;
- } else if (*pPhysicalDeviceCount >= 1) {
- pPhysicalDevices[0] = anv_physical_device_to_handle(&instance->physicalDevice);
- *pPhysicalDeviceCount = 1;
- } else {
- *pPhysicalDeviceCount = 0;
- }
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetPhysicalDeviceFeatures(
- VkPhysicalDevice physicalDevice,
- VkPhysicalDeviceFeatures* pFeatures)
-{
- anv_finishme("Get correct values for PhysicalDeviceFeatures");
-
- *pFeatures = (VkPhysicalDeviceFeatures) {
- .robustBufferAccess = false,
- .fullDrawIndexUint32 = false,
- .imageCubeArray = false,
- .independentBlend = false,
- .geometryShader = true,
- .tessellationShader = false,
- .sampleRateShading = false,
- .dualSourceBlend = true,
- .logicOp = true,
- .instancedDrawIndirect = true,
- .depthClip = false,
- .depthBiasClamp = false,
- .fillModeNonSolid = true,
- .depthBounds = false,
- .wideLines = true,
- .largePoints = true,
- .textureCompressionETC2 = true,
- .textureCompressionASTC_LDR = true,
- .textureCompressionBC = true,
- .pipelineStatisticsQuery = true,
- .vertexSideEffects = false,
- .tessellationSideEffects = false,
- .geometrySideEffects = false,
- .fragmentSideEffects = false,
- .shaderTessellationPointSize = false,
- .shaderGeometryPointSize = true,
- .shaderTextureGatherExtended = true,
- .shaderStorageImageExtendedFormats = false,
- .shaderStorageImageMultisample = false,
- .shaderStorageBufferArrayConstantIndexing = false,
- .shaderStorageImageArrayConstantIndexing = false,
- .shaderUniformBufferArrayDynamicIndexing = true,
- .shaderSampledImageArrayDynamicIndexing = false,
- .shaderStorageBufferArrayDynamicIndexing = false,
- .shaderStorageImageArrayDynamicIndexing = false,
- .shaderClipDistance = false,
- .shaderCullDistance = false,
- .shaderFloat64 = false,
- .shaderInt64 = false,
- .shaderFloat16 = false,
- .shaderInt16 = false,
- };
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetPhysicalDeviceLimits(
- VkPhysicalDevice physicalDevice,
- VkPhysicalDeviceLimits* pLimits)
-{
- ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
- const struct brw_device_info *devinfo = physical_device->info;
-
- anv_finishme("Get correct values for PhysicalDeviceLimits");
-
- *pLimits = (VkPhysicalDeviceLimits) {
- .maxImageDimension1D = (1 << 14),
- .maxImageDimension2D = (1 << 14),
- .maxImageDimension3D = (1 << 10),
- .maxImageDimensionCube = (1 << 14),
- .maxImageArrayLayers = (1 << 10),
- .maxTexelBufferSize = (1 << 14),
- .maxUniformBufferSize = UINT32_MAX,
- .maxStorageBufferSize = UINT32_MAX,
- .maxPushConstantsSize = 128,
- .maxMemoryAllocationCount = UINT32_MAX,
- .bufferImageGranularity = 64, /* A cache line */
- .maxBoundDescriptorSets = MAX_SETS,
- .maxDescriptorSets = UINT32_MAX,
- .maxPerStageDescriptorSamplers = 64,
- .maxPerStageDescriptorUniformBuffers = 64,
- .maxPerStageDescriptorStorageBuffers = 64,
- .maxPerStageDescriptorSampledImages = 64,
- .maxPerStageDescriptorStorageImages = 64,
- .maxDescriptorSetSamplers = 256,
- .maxDescriptorSetUniformBuffers = 256,
- .maxDescriptorSetStorageBuffers = 256,
- .maxDescriptorSetSampledImages = 256,
- .maxDescriptorSetStorageImages = 256,
- .maxVertexInputAttributes = 32,
- .maxVertexInputAttributeOffset = 256,
- .maxVertexInputBindingStride = 256,
- .maxVertexOutputComponents = 32,
- .maxTessGenLevel = 0,
- .maxTessPatchSize = 0,
- .maxTessControlPerVertexInputComponents = 0,
- .maxTessControlPerVertexOutputComponents = 0,
- .maxTessControlPerPatchOutputComponents = 0,
- .maxTessControlTotalOutputComponents = 0,
- .maxTessEvaluationInputComponents = 0,
- .maxTessEvaluationOutputComponents = 0,
- .maxGeometryShaderInvocations = 6,
- .maxGeometryInputComponents = 16,
- .maxGeometryOutputComponents = 16,
- .maxGeometryOutputVertices = 16,
- .maxGeometryTotalOutputComponents = 16,
- .maxFragmentInputComponents = 16,
- .maxFragmentOutputBuffers = 8,
- .maxFragmentDualSourceBuffers = 2,
- .maxFragmentCombinedOutputResources = 8,
- .maxComputeSharedMemorySize = 1024,
- .maxComputeWorkGroupCount = {
- 16 * devinfo->max_cs_threads,
- 16 * devinfo->max_cs_threads,
- 16 * devinfo->max_cs_threads,
- },
- .maxComputeWorkGroupInvocations = 16 * devinfo->max_cs_threads,
- .maxComputeWorkGroupSize = {
- 16 * devinfo->max_cs_threads,
- 16 * devinfo->max_cs_threads,
- 16 * devinfo->max_cs_threads,
- },
- .subPixelPrecisionBits = 4 /* FIXME */,
- .subTexelPrecisionBits = 4 /* FIXME */,
- .mipmapPrecisionBits = 4 /* FIXME */,
- .maxDrawIndexedIndexValue = UINT32_MAX,
- .maxDrawIndirectInstanceCount = UINT32_MAX,
- .primitiveRestartForPatches = UINT32_MAX,
- .maxSamplerLodBias = 16,
- .maxSamplerAnisotropy = 16,
- .maxViewports = 16,
- .maxDynamicViewportStates = UINT32_MAX,
- .maxViewportDimensions = { (1 << 14), (1 << 14) },
- .viewportBoundsRange = { -1.0, 1.0 }, /* FIXME */
- .viewportSubPixelBits = 13, /* We take a float? */
- .minMemoryMapAlignment = 64, /* A cache line */
- .minTexelBufferOffsetAlignment = 1,
- .minUniformBufferOffsetAlignment = 1,
- .minStorageBufferOffsetAlignment = 1,
- .minTexelOffset = 0, /* FIXME */
- .maxTexelOffset = 0, /* FIXME */
- .minTexelGatherOffset = 0, /* FIXME */
- .maxTexelGatherOffset = 0, /* FIXME */
- .minInterpolationOffset = 0, /* FIXME */
- .maxInterpolationOffset = 0, /* FIXME */
- .subPixelInterpolationOffsetBits = 0, /* FIXME */
- .maxFramebufferWidth = (1 << 14),
- .maxFramebufferHeight = (1 << 14),
- .maxFramebufferLayers = (1 << 10),
- .maxFramebufferColorSamples = 8,
- .maxFramebufferDepthSamples = 8,
- .maxFramebufferStencilSamples = 8,
- .maxColorAttachments = MAX_RTS,
- .maxSampledImageColorSamples = 8,
- .maxSampledImageDepthSamples = 8,
- .maxSampledImageIntegerSamples = 1,
- .maxStorageImageSamples = 1,
- .maxSampleMaskWords = 1,
- .timestampFrequency = 1000 * 1000 * 1000 / 80,
- .maxClipDistances = 0 /* FIXME */,
- .maxCullDistances = 0 /* FIXME */,
- .maxCombinedClipAndCullDistances = 0 /* FIXME */,
- .pointSizeRange = { 0.125, 255.875 },
- .lineWidthRange = { 0.0, 7.9921875 },
- .pointSizeGranularity = (1.0 / 8.0),
- .lineWidthGranularity = (1.0 / 128.0),
- };
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetPhysicalDeviceProperties(
- VkPhysicalDevice physicalDevice,
- VkPhysicalDeviceProperties* pProperties)
-{
- ANV_FROM_HANDLE(anv_physical_device, pdevice, physicalDevice);
-
- *pProperties = (VkPhysicalDeviceProperties) {
- .apiVersion = 1,
- .driverVersion = 1,
- .vendorId = 0x8086,
- .deviceId = pdevice->chipset_id,
- .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
- };
-
- strcpy(pProperties->deviceName, pdevice->name);
- snprintf((char *)pProperties->pipelineCacheUUID, VK_UUID_LENGTH,
- "anv-%s", MESA_GIT_SHA1 + 4);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetPhysicalDeviceQueueCount(
- VkPhysicalDevice physicalDevice,
- uint32_t* pCount)
-{
- *pCount = 1;
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetPhysicalDeviceQueueProperties(
- VkPhysicalDevice physicalDevice,
- uint32_t count,
- VkPhysicalDeviceQueueProperties* pQueueProperties)
-{
- assert(count == 1);
-
- *pQueueProperties = (VkPhysicalDeviceQueueProperties) {
- .queueFlags = VK_QUEUE_GRAPHICS_BIT |
- VK_QUEUE_COMPUTE_BIT |
- VK_QUEUE_DMA_BIT,
- .queueCount = 1,
- .supportsTimestamps = true,
- };
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetPhysicalDeviceMemoryProperties(
- VkPhysicalDevice physicalDevice,
- VkPhysicalDeviceMemoryProperties* pMemoryProperties)
-{
- ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
-
- size_t aperture_size;
- size_t heap_size;
-
- if (anv_gem_get_aperture(physical_device, &aperture_size) == -1)
- return vk_error(VK_ERROR_UNAVAILABLE);
-
- /* Reserve some wiggle room for the driver by exposing only 75% of the
- * aperture to the heap.
- */
- heap_size = 3 * aperture_size / 4;
-
- /* The property flags below are valid only for llc platforms. */
- pMemoryProperties->memoryTypeCount = 1;
- pMemoryProperties->memoryTypes[0] = (VkMemoryType) {
- .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
- .heapIndex = 1,
- };
-
- pMemoryProperties->memoryHeapCount = 1;
- pMemoryProperties->memoryHeaps[0] = (VkMemoryHeap) {
- .size = heap_size,
- .flags = VK_MEMORY_HEAP_HOST_LOCAL,
- };
-
- return VK_SUCCESS;
-}
-
-PFN_vkVoidFunction anv_GetInstanceProcAddr(
- VkInstance instance,
- const char* pName)
-{
- return anv_lookup_entrypoint(pName);
-}
-
-PFN_vkVoidFunction anv_GetDeviceProcAddr(
- VkDevice device,
- const char* pName)
-{
- return anv_lookup_entrypoint(pName);
-}
-
-static void
-parse_debug_flags(struct anv_device *device)
-{
- const char *debug, *p, *end;
-
- debug = getenv("INTEL_DEBUG");
- device->dump_aub = false;
- if (debug) {
- for (p = debug; *p; p = end + 1) {
- end = strchrnul(p, ',');
- if (end - p == 3 && memcmp(p, "aub", 3) == 0)
- device->dump_aub = true;
- if (end - p == 5 && memcmp(p, "no_hw", 5) == 0)
- device->no_hw = true;
- if (*end == '\0')
- break;
- }
- }
-}
-
-static VkResult
-anv_queue_init(struct anv_device *device, struct anv_queue *queue)
-{
- queue->device = device;
- queue->pool = &device->surface_state_pool;
-
- queue->completed_serial = anv_state_pool_alloc(queue->pool, 4, 4);
- if (queue->completed_serial.map == NULL)
- return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
-
- *(uint32_t *)queue->completed_serial.map = 0;
- queue->next_serial = 1;
-
- return VK_SUCCESS;
-}
-
-static void
-anv_queue_finish(struct anv_queue *queue)
-{
-#ifdef HAVE_VALGRIND
- /* This gets torn down with the device so we only need to do this if
- * valgrind is present.
- */
- anv_state_pool_free(queue->pool, queue->completed_serial);
-#endif
-}
-
-static void
-anv_device_init_border_colors(struct anv_device *device)
-{
- static const VkClearColorValue border_colors[] = {
- [VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK] = { .f32 = { 0.0, 0.0, 0.0, 0.0 } },
- [VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK] = { .f32 = { 0.0, 0.0, 0.0, 1.0 } },
- [VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE] = { .f32 = { 1.0, 1.0, 1.0, 1.0 } },
- [VK_BORDER_COLOR_INT_TRANSPARENT_BLACK] = { .u32 = { 0, 0, 0, 0 } },
- [VK_BORDER_COLOR_INT_OPAQUE_BLACK] = { .u32 = { 0, 0, 0, 1 } },
- [VK_BORDER_COLOR_INT_OPAQUE_WHITE] = { .u32 = { 1, 1, 1, 1 } },
- };
-
- device->border_colors =
- anv_state_pool_alloc(&device->dynamic_state_pool,
- sizeof(border_colors), 32);
- memcpy(device->border_colors.map, border_colors, sizeof(border_colors));
-}
-
-static const uint32_t BATCH_SIZE = 8192;
-
-VkResult anv_CreateDevice(
- VkPhysicalDevice physicalDevice,
- const VkDeviceCreateInfo* pCreateInfo,
- VkDevice* pDevice)
-{
- ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
- struct anv_instance *instance = physical_device->instance;
- struct anv_device *device;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
-
- device = instance->pfnAlloc(instance->pAllocUserData,
- sizeof(*device), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (!device)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- device->no_hw = physical_device->no_hw;
- parse_debug_flags(device);
-
- device->instance = physical_device->instance;
-
- /* XXX(chadv): Can we dup() physicalDevice->fd here? */
- device->fd = open(physical_device->path, O_RDWR | O_CLOEXEC);
- if (device->fd == -1)
- goto fail_device;
-
- device->context_id = anv_gem_create_context(device);
- if (device->context_id == -1)
- goto fail_fd;
-
- anv_bo_pool_init(&device->batch_bo_pool, device, BATCH_SIZE);
-
- anv_block_pool_init(&device->dynamic_state_block_pool, device, 2048);
-
- anv_state_pool_init(&device->dynamic_state_pool,
- &device->dynamic_state_block_pool);
-
- anv_block_pool_init(&device->instruction_block_pool, device, 2048);
- anv_block_pool_init(&device->surface_state_block_pool, device, 2048);
-
- anv_state_pool_init(&device->surface_state_pool,
- &device->surface_state_block_pool);
-
- anv_block_pool_init(&device->scratch_block_pool, device, 0x10000);
-
- device->info = *physical_device->info;
-
- device->compiler = anv_compiler_create(device);
- device->aub_writer = NULL;
-
- pthread_mutex_init(&device->mutex, NULL);
-
- anv_queue_init(device, &device->queue);
-
- anv_device_init_meta(device);
-
- anv_device_init_border_colors(device);
-
- *pDevice = anv_device_to_handle(device);
-
- return VK_SUCCESS;
-
- fail_fd:
- close(device->fd);
- fail_device:
- anv_device_free(device, device);
-
- return vk_error(VK_ERROR_UNAVAILABLE);
-}
-
-VkResult anv_DestroyDevice(
- VkDevice _device)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
-
- anv_compiler_destroy(device->compiler);
-
- anv_queue_finish(&device->queue);
-
- anv_device_finish_meta(device);
-
-#ifdef HAVE_VALGRIND
- /* We only need to free these to prevent valgrind errors. The backing
- * BO will go away in a couple of lines so we don't actually leak.
- */
- anv_state_pool_free(&device->dynamic_state_pool, device->border_colors);
-#endif
-
- anv_bo_pool_finish(&device->batch_bo_pool);
- anv_block_pool_finish(&device->dynamic_state_block_pool);
- anv_block_pool_finish(&device->instruction_block_pool);
- anv_block_pool_finish(&device->surface_state_block_pool);
-
- close(device->fd);
-
- if (device->aub_writer)
- anv_aub_writer_destroy(device->aub_writer);
-
- anv_device_free(device, device);
-
- return VK_SUCCESS;
-}
-
-static const VkExtensionProperties global_extensions[] = {
- {
- .extName = "VK_WSI_LunarG",
- .specVersion = 3
- }
-};
-
-VkResult anv_GetGlobalExtensionProperties(
- const char* pLayerName,
- uint32_t* pCount,
- VkExtensionProperties* pProperties)
-{
- if (pProperties == NULL) {
- *pCount = ARRAY_SIZE(global_extensions);
- return VK_SUCCESS;
- }
-
- assert(*pCount < ARRAY_SIZE(global_extensions));
-
- *pCount = ARRAY_SIZE(global_extensions);
- memcpy(pProperties, global_extensions, sizeof(global_extensions));
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetPhysicalDeviceExtensionProperties(
- VkPhysicalDevice physicalDevice,
- const char* pLayerName,
- uint32_t* pCount,
- VkExtensionProperties* pProperties)
-{
- if (pProperties == NULL) {
- *pCount = 0;
- return VK_SUCCESS;
- }
-
- /* None supported at this time */
- return vk_error(VK_ERROR_INVALID_EXTENSION);
-}
-
-VkResult anv_GetGlobalLayerProperties(
- uint32_t* pCount,
- VkLayerProperties* pProperties)
-{
- if (pProperties == NULL) {
- *pCount = 0;
- return VK_SUCCESS;
- }
-
- /* None supported at this time */
- return vk_error(VK_ERROR_INVALID_LAYER);
-}
-
-VkResult anv_GetPhysicalDeviceLayerProperties(
- VkPhysicalDevice physicalDevice,
- uint32_t* pCount,
- VkLayerProperties* pProperties)
-{
- if (pProperties == NULL) {
- *pCount = 0;
- return VK_SUCCESS;
- }
-
- /* None supported at this time */
- return vk_error(VK_ERROR_INVALID_LAYER);
-}
-
-VkResult anv_GetDeviceQueue(
- VkDevice _device,
- uint32_t queueNodeIndex,
- uint32_t queueIndex,
- VkQueue* pQueue)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
-
- assert(queueIndex == 0);
-
- *pQueue = anv_queue_to_handle(&device->queue);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_QueueSubmit(
- VkQueue _queue,
- uint32_t cmdBufferCount,
- const VkCmdBuffer* pCmdBuffers,
- VkFence _fence)
-{
- ANV_FROM_HANDLE(anv_queue, queue, _queue);
- ANV_FROM_HANDLE(anv_fence, fence, _fence);
- struct anv_device *device = queue->device;
- int ret;
-
- for (uint32_t i = 0; i < cmdBufferCount; i++) {
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, pCmdBuffers[i]);
-
- if (device->dump_aub)
- anv_cmd_buffer_dump(cmd_buffer);
-
- if (!device->no_hw) {
- ret = anv_gem_execbuffer(device, &cmd_buffer->execbuf);
- if (ret != 0)
- return vk_error(VK_ERROR_UNKNOWN);
-
- if (fence) {
- ret = anv_gem_execbuffer(device, &fence->execbuf);
- if (ret != 0)
- return vk_error(VK_ERROR_UNKNOWN);
- }
-
- for (uint32_t i = 0; i < cmd_buffer->exec2_bo_count; i++)
- cmd_buffer->exec2_bos[i]->offset = cmd_buffer->exec2_objects[i].offset;
- } else {
- *(uint32_t *)queue->completed_serial.map = cmd_buffer->serial;
- }
- }
-
- return VK_SUCCESS;
-}
-
-VkResult anv_QueueWaitIdle(
- VkQueue _queue)
-{
- ANV_FROM_HANDLE(anv_queue, queue, _queue);
-
- return vkDeviceWaitIdle(anv_device_to_handle(queue->device));
-}
-
-VkResult anv_DeviceWaitIdle(
- VkDevice _device)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_state state;
- struct anv_batch batch;
- struct drm_i915_gem_execbuffer2 execbuf;
- struct drm_i915_gem_exec_object2 exec2_objects[1];
- struct anv_bo *bo = NULL;
- VkResult result;
- int64_t timeout;
- int ret;
-
- state = anv_state_pool_alloc(&device->dynamic_state_pool, 32, 32);
- bo = &device->dynamic_state_pool.block_pool->bo;
- batch.start = batch.next = state.map;
- batch.end = state.map + 32;
- anv_batch_emit(&batch, GEN8_MI_BATCH_BUFFER_END);
- anv_batch_emit(&batch, GEN8_MI_NOOP);
-
- exec2_objects[0].handle = bo->gem_handle;
- exec2_objects[0].relocation_count = 0;
- exec2_objects[0].relocs_ptr = 0;
- exec2_objects[0].alignment = 0;
- exec2_objects[0].offset = bo->offset;
- exec2_objects[0].flags = 0;
- exec2_objects[0].rsvd1 = 0;
- exec2_objects[0].rsvd2 = 0;
-
- execbuf.buffers_ptr = (uintptr_t) exec2_objects;
- execbuf.buffer_count = 1;
- execbuf.batch_start_offset = state.offset;
- execbuf.batch_len = batch.next - state.map;
- execbuf.cliprects_ptr = 0;
- execbuf.num_cliprects = 0;
- execbuf.DR1 = 0;
- execbuf.DR4 = 0;
-
- execbuf.flags =
- I915_EXEC_HANDLE_LUT | I915_EXEC_NO_RELOC | I915_EXEC_RENDER;
- execbuf.rsvd1 = device->context_id;
- execbuf.rsvd2 = 0;
-
- if (!device->no_hw) {
- ret = anv_gem_execbuffer(device, &execbuf);
- if (ret != 0) {
- result = vk_error(VK_ERROR_UNKNOWN);
- goto fail;
- }
-
- timeout = INT64_MAX;
- ret = anv_gem_wait(device, bo->gem_handle, &timeout);
- if (ret != 0) {
- result = vk_error(VK_ERROR_UNKNOWN);
- goto fail;
- }
- }
-
- anv_state_pool_free(&device->dynamic_state_pool, state);
-
- return VK_SUCCESS;
-
- fail:
- anv_state_pool_free(&device->dynamic_state_pool, state);
-
- return result;
-}
-
-void *
-anv_device_alloc(struct anv_device * device,
- size_t size,
- size_t alignment,
- VkSystemAllocType allocType)
-{
- return device->instance->pfnAlloc(device->instance->pAllocUserData,
- size,
- alignment,
- allocType);
-}
-
-void
-anv_device_free(struct anv_device * device,
- void * mem)
-{
- if (mem == NULL)
- return;
-
- return device->instance->pfnFree(device->instance->pAllocUserData,
- mem);
-}
-
-VkResult
-anv_bo_init_new(struct anv_bo *bo, struct anv_device *device, uint64_t size)
-{
- bo->gem_handle = anv_gem_create(device, size);
- if (!bo->gem_handle)
- return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
-
- bo->map = NULL;
- bo->index = 0;
- bo->offset = 0;
- bo->size = size;
-
- return VK_SUCCESS;
-}
-
-VkResult anv_AllocMemory(
- VkDevice _device,
- const VkMemoryAllocInfo* pAllocInfo,
- VkDeviceMemory* pMem)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_device_memory *mem;
- VkResult result;
-
- assert(pAllocInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO);
-
- if (pAllocInfo->memoryTypeIndex != 0) {
- /* We support exactly one memory heap. */
- return vk_error(VK_ERROR_INVALID_VALUE);
- }
-
- /* FINISHME: Fail if allocation request exceeds heap size. */
-
- mem = anv_device_alloc(device, sizeof(*mem), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (mem == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- result = anv_bo_init_new(&mem->bo, device, pAllocInfo->allocationSize);
- if (result != VK_SUCCESS)
- goto fail;
-
- *pMem = anv_device_memory_to_handle(mem);
-
- return VK_SUCCESS;
-
- fail:
- anv_device_free(device, mem);
-
- return result;
-}
-
-VkResult anv_FreeMemory(
- VkDevice _device,
- VkDeviceMemory _mem)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_device_memory, mem, _mem);
-
- if (mem->bo.map)
- anv_gem_munmap(mem->bo.map, mem->bo.size);
-
- if (mem->bo.gem_handle != 0)
- anv_gem_close(device, mem->bo.gem_handle);
-
- anv_device_free(device, mem);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_MapMemory(
- VkDevice _device,
- VkDeviceMemory _mem,
- VkDeviceSize offset,
- VkDeviceSize size,
- VkMemoryMapFlags flags,
- void** ppData)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_device_memory, mem, _mem);
-
- /* FIXME: Is this supposed to be thread safe? Since vkUnmapMemory() only
- * takes a VkDeviceMemory pointer, it seems like only one map of the memory
- * at a time is valid. We could just mmap up front and return an offset
- * pointer here, but that may exhaust virtual memory on 32 bit
- * userspace. */
-
- mem->map = anv_gem_mmap(device, mem->bo.gem_handle, offset, size);
- mem->map_size = size;
-
- *ppData = mem->map;
-
- return VK_SUCCESS;
-}
-
-VkResult anv_UnmapMemory(
- VkDevice _device,
- VkDeviceMemory _mem)
-{
- ANV_FROM_HANDLE(anv_device_memory, mem, _mem);
-
- anv_gem_munmap(mem->map, mem->map_size);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_FlushMappedMemoryRanges(
- VkDevice device,
- uint32_t memRangeCount,
- const VkMappedMemoryRange* pMemRanges)
-{
- /* clflush here for !llc platforms */
-
- return VK_SUCCESS;
-}
-
-VkResult anv_InvalidateMappedMemoryRanges(
- VkDevice device,
- uint32_t memRangeCount,
- const VkMappedMemoryRange* pMemRanges)
-{
- return anv_FlushMappedMemoryRanges(device, memRangeCount, pMemRanges);
-}
-
-VkResult anv_GetBufferMemoryRequirements(
- VkDevice device,
- VkBuffer _buffer,
- VkMemoryRequirements* pMemoryRequirements)
-{
- ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
-
- /* The Vulkan spec (git aaed022) says:
- *
- * memoryTypeBits is a bitfield and contains one bit set for every
- * supported memory type for the resource. The bit `1<<i` is set if and
- * only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
- * structure for the physical device is supported.
- *
- * We support exactly one memory type.
- */
- pMemoryRequirements->memoryTypeBits = 1;
-
- pMemoryRequirements->size = buffer->size;
- pMemoryRequirements->alignment = 16;
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetImageMemoryRequirements(
- VkDevice device,
- VkImage _image,
- VkMemoryRequirements* pMemoryRequirements)
-{
- ANV_FROM_HANDLE(anv_image, image, _image);
-
- /* The Vulkan spec (git aaed022) says:
- *
- * memoryTypeBits is a bitfield and contains one bit set for every
- * supported memory type for the resource. The bit `1<<i` is set if and
- * only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
- * structure for the physical device is supported.
- *
- * We support exactly one memory type.
- */
- pMemoryRequirements->memoryTypeBits = 1;
-
- pMemoryRequirements->size = image->size;
- pMemoryRequirements->alignment = image->alignment;
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetImageSparseMemoryRequirements(
- VkDevice device,
- VkImage image,
- uint32_t* pNumRequirements,
- VkSparseImageMemoryRequirements* pSparseMemoryRequirements)
-{
- return vk_error(VK_UNSUPPORTED);
-}
-
-VkResult anv_GetDeviceMemoryCommitment(
- VkDevice device,
- VkDeviceMemory memory,
- VkDeviceSize* pCommittedMemoryInBytes)
-{
- *pCommittedMemoryInBytes = 0;
- stub_return(VK_SUCCESS);
-}
-
-VkResult anv_BindBufferMemory(
- VkDevice device,
- VkBuffer _buffer,
- VkDeviceMemory _mem,
- VkDeviceSize memOffset)
-{
- ANV_FROM_HANDLE(anv_device_memory, mem, _mem);
- ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
-
- buffer->bo = &mem->bo;
- buffer->offset = memOffset;
-
- return VK_SUCCESS;
-}
-
-VkResult anv_BindImageMemory(
- VkDevice device,
- VkImage _image,
- VkDeviceMemory _mem,
- VkDeviceSize memOffset)
-{
- ANV_FROM_HANDLE(anv_device_memory, mem, _mem);
- ANV_FROM_HANDLE(anv_image, image, _image);
-
- image->bo = &mem->bo;
- image->offset = memOffset;
-
- return VK_SUCCESS;
-}
-
-VkResult anv_QueueBindSparseBufferMemory(
- VkQueue queue,
- VkBuffer buffer,
- uint32_t numBindings,
- const VkSparseMemoryBindInfo* pBindInfo)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_QueueBindSparseImageOpaqueMemory(
- VkQueue queue,
- VkImage image,
- uint32_t numBindings,
- const VkSparseMemoryBindInfo* pBindInfo)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_QueueBindSparseImageMemory(
- VkQueue queue,
- VkImage image,
- uint32_t numBindings,
- const VkSparseImageMemoryBindInfo* pBindInfo)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_CreateFence(
- VkDevice _device,
- const VkFenceCreateInfo* pCreateInfo,
- VkFence* pFence)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_fence *fence;
- struct anv_batch batch;
- VkResult result;
-
- const uint32_t fence_size = 128;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO);
-
- fence = anv_device_alloc(device, sizeof(*fence), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (fence == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- result = anv_bo_init_new(&fence->bo, device, fence_size);
- if (result != VK_SUCCESS)
- goto fail;
-
- fence->bo.map =
- anv_gem_mmap(device, fence->bo.gem_handle, 0, fence->bo.size);
- batch.next = batch.start = fence->bo.map;
- batch.end = fence->bo.map + fence->bo.size;
- anv_batch_emit(&batch, GEN8_MI_BATCH_BUFFER_END);
- anv_batch_emit(&batch, GEN8_MI_NOOP);
-
- fence->exec2_objects[0].handle = fence->bo.gem_handle;
- fence->exec2_objects[0].relocation_count = 0;
- fence->exec2_objects[0].relocs_ptr = 0;
- fence->exec2_objects[0].alignment = 0;
- fence->exec2_objects[0].offset = fence->bo.offset;
- fence->exec2_objects[0].flags = 0;
- fence->exec2_objects[0].rsvd1 = 0;
- fence->exec2_objects[0].rsvd2 = 0;
-
- fence->execbuf.buffers_ptr = (uintptr_t) fence->exec2_objects;
- fence->execbuf.buffer_count = 1;
- fence->execbuf.batch_start_offset = 0;
- fence->execbuf.batch_len = batch.next - fence->bo.map;
- fence->execbuf.cliprects_ptr = 0;
- fence->execbuf.num_cliprects = 0;
- fence->execbuf.DR1 = 0;
- fence->execbuf.DR4 = 0;
-
- fence->execbuf.flags =
- I915_EXEC_HANDLE_LUT | I915_EXEC_NO_RELOC | I915_EXEC_RENDER;
- fence->execbuf.rsvd1 = device->context_id;
- fence->execbuf.rsvd2 = 0;
-
- *pFence = anv_fence_to_handle(fence);
-
- return VK_SUCCESS;
-
- fail:
- anv_device_free(device, fence);
-
- return result;
-}
-
-VkResult anv_DestroyFence(
- VkDevice _device,
- VkFence _fence)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_fence, fence, _fence);
-
- anv_gem_munmap(fence->bo.map, fence->bo.size);
- anv_gem_close(device, fence->bo.gem_handle);
- anv_device_free(device, fence);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_ResetFences(
- VkDevice _device,
- uint32_t fenceCount,
- const VkFence* pFences)
-{
- for (uint32_t i = 0; i < fenceCount; i++) {
- ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
- fence->ready = false;
- }
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetFenceStatus(
- VkDevice _device,
- VkFence _fence)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_fence, fence, _fence);
- int64_t t = 0;
- int ret;
-
- if (fence->ready)
- return VK_SUCCESS;
-
- ret = anv_gem_wait(device, fence->bo.gem_handle, &t);
- if (ret == 0) {
- fence->ready = true;
- return VK_SUCCESS;
- }
-
- return VK_NOT_READY;
-}
-
-VkResult anv_WaitForFences(
- VkDevice _device,
- uint32_t fenceCount,
- const VkFence* pFences,
- VkBool32 waitAll,
- uint64_t timeout)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- int64_t t = timeout;
- int ret;
-
- /* FIXME: handle !waitAll */
-
- for (uint32_t i = 0; i < fenceCount; i++) {
- ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
- ret = anv_gem_wait(device, fence->bo.gem_handle, &t);
- if (ret == -1 && errno == ETIME)
- return VK_TIMEOUT;
- else if (ret == -1)
- return vk_error(VK_ERROR_UNKNOWN);
- }
-
- return VK_SUCCESS;
-}
-
-// Queue semaphore functions
-
-VkResult anv_CreateSemaphore(
- VkDevice device,
- const VkSemaphoreCreateInfo* pCreateInfo,
- VkSemaphore* pSemaphore)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_DestroySemaphore(
- VkDevice device,
- VkSemaphore semaphore)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_QueueSignalSemaphore(
- VkQueue queue,
- VkSemaphore semaphore)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_QueueWaitSemaphore(
- VkQueue queue,
- VkSemaphore semaphore)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-// Event functions
-
-VkResult anv_CreateEvent(
- VkDevice device,
- const VkEventCreateInfo* pCreateInfo,
- VkEvent* pEvent)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_DestroyEvent(
- VkDevice device,
- VkEvent event)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_GetEventStatus(
- VkDevice device,
- VkEvent event)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_SetEvent(
- VkDevice device,
- VkEvent event)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_ResetEvent(
- VkDevice device,
- VkEvent event)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-// Buffer functions
-
-VkResult anv_CreateBuffer(
- VkDevice _device,
- const VkBufferCreateInfo* pCreateInfo,
- VkBuffer* pBuffer)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_buffer *buffer;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
-
- buffer = anv_device_alloc(device, sizeof(*buffer), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (buffer == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- buffer->size = pCreateInfo->size;
- buffer->bo = NULL;
- buffer->offset = 0;
-
- *pBuffer = anv_buffer_to_handle(buffer);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyBuffer(
- VkDevice _device,
- VkBuffer _buffer)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
-
- anv_device_free(device, buffer);
-
- return VK_SUCCESS;
-}
-
-// Buffer view functions
-
-void
-anv_fill_buffer_surface_state(void *state, VkFormat format,
- uint32_t offset, uint32_t range)
-{
- const struct anv_format *info;
-
- info = anv_format_for_vk_format(format);
- /* This assumes RGBA float format. */
- uint32_t stride = 4;
- uint32_t num_elements = range / stride;
-
- struct GEN8_RENDER_SURFACE_STATE surface_state = {
- .SurfaceType = SURFTYPE_BUFFER,
- .SurfaceArray = false,
- .SurfaceFormat = info->surface_format,
- .SurfaceVerticalAlignment = VALIGN4,
- .SurfaceHorizontalAlignment = HALIGN4,
- .TileMode = LINEAR,
- .VerticalLineStride = 0,
- .VerticalLineStrideOffset = 0,
- .SamplerL2BypassModeDisable = true,
- .RenderCacheReadWriteMode = WriteOnlyCache,
- .MemoryObjectControlState = GEN8_MOCS,
- .BaseMipLevel = 0.0,
- .SurfaceQPitch = 0,
- .Height = (num_elements >> 7) & 0x3fff,
- .Width = num_elements & 0x7f,
- .Depth = (num_elements >> 21) & 0x3f,
- .SurfacePitch = stride - 1,
- .MinimumArrayElement = 0,
- .NumberofMultisamples = MULTISAMPLECOUNT_1,
- .XOffset = 0,
- .YOffset = 0,
- .SurfaceMinLOD = 0,
- .MIPCountLOD = 0,
- .AuxiliarySurfaceMode = AUX_NONE,
- .RedClearColor = 0,
- .GreenClearColor = 0,
- .BlueClearColor = 0,
- .AlphaClearColor = 0,
- .ShaderChannelSelectRed = SCS_RED,
- .ShaderChannelSelectGreen = SCS_GREEN,
- .ShaderChannelSelectBlue = SCS_BLUE,
- .ShaderChannelSelectAlpha = SCS_ALPHA,
- .ResourceMinLOD = 0.0,
- /* FIXME: We assume that the image must be bound at this time. */
- .SurfaceBaseAddress = { NULL, offset },
- };
-
- GEN8_RENDER_SURFACE_STATE_pack(NULL, state, &surface_state);
-}
-
-VkResult anv_CreateBufferView(
- VkDevice _device,
- const VkBufferViewCreateInfo* pCreateInfo,
- VkBufferView* pView)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_buffer, buffer, pCreateInfo->buffer);
- struct anv_buffer_view *bview;
- struct anv_surface_view *view;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO);
-
- bview = anv_device_alloc(device, sizeof(*view), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (bview == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- view = &bview->view;
- view->bo = buffer->bo;
- view->offset = buffer->offset + pCreateInfo->offset;
- view->surface_state =
- anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
- view->format = pCreateInfo->format;
- view->range = pCreateInfo->range;
-
- anv_fill_buffer_surface_state(view->surface_state.map,
- pCreateInfo->format,
- view->offset, pCreateInfo->range);
-
- *pView = anv_buffer_view_to_handle(bview);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyBufferView(
- VkDevice _device,
- VkBufferView _bview)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_buffer_view, bview, _bview);
-
- anv_surface_view_fini(device, &bview->view);
- anv_device_free(device, bview);
-
- return VK_SUCCESS;
-}
-
-// Sampler functions
-
-VkResult anv_CreateSampler(
- VkDevice _device,
- const VkSamplerCreateInfo* pCreateInfo,
- VkSampler* pSampler)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_sampler *sampler;
- uint32_t mag_filter, min_filter, max_anisotropy;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
-
- sampler = anv_device_alloc(device, sizeof(*sampler), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (!sampler)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- static const uint32_t vk_to_gen_tex_filter[] = {
- [VK_TEX_FILTER_NEAREST] = MAPFILTER_NEAREST,
- [VK_TEX_FILTER_LINEAR] = MAPFILTER_LINEAR
- };
-
- static const uint32_t vk_to_gen_mipmap_mode[] = {
- [VK_TEX_MIPMAP_MODE_BASE] = MIPFILTER_NONE,
- [VK_TEX_MIPMAP_MODE_NEAREST] = MIPFILTER_NEAREST,
- [VK_TEX_MIPMAP_MODE_LINEAR] = MIPFILTER_LINEAR
- };
-
- static const uint32_t vk_to_gen_tex_address[] = {
- [VK_TEX_ADDRESS_WRAP] = TCM_WRAP,
- [VK_TEX_ADDRESS_MIRROR] = TCM_MIRROR,
- [VK_TEX_ADDRESS_CLAMP] = TCM_CLAMP,
- [VK_TEX_ADDRESS_MIRROR_ONCE] = TCM_MIRROR_ONCE,
- [VK_TEX_ADDRESS_CLAMP_BORDER] = TCM_CLAMP_BORDER,
- };
-
- static const uint32_t vk_to_gen_compare_op[] = {
- [VK_COMPARE_OP_NEVER] = PREFILTEROPNEVER,
- [VK_COMPARE_OP_LESS] = PREFILTEROPLESS,
- [VK_COMPARE_OP_EQUAL] = PREFILTEROPEQUAL,
- [VK_COMPARE_OP_LESS_EQUAL] = PREFILTEROPLEQUAL,
- [VK_COMPARE_OP_GREATER] = PREFILTEROPGREATER,
- [VK_COMPARE_OP_NOT_EQUAL] = PREFILTEROPNOTEQUAL,
- [VK_COMPARE_OP_GREATER_EQUAL] = PREFILTEROPGEQUAL,
- [VK_COMPARE_OP_ALWAYS] = PREFILTEROPALWAYS,
- };
-
- if (pCreateInfo->maxAnisotropy > 1) {
- mag_filter = MAPFILTER_ANISOTROPIC;
- min_filter = MAPFILTER_ANISOTROPIC;
- max_anisotropy = (pCreateInfo->maxAnisotropy - 2) / 2;
- } else {
- mag_filter = vk_to_gen_tex_filter[pCreateInfo->magFilter];
- min_filter = vk_to_gen_tex_filter[pCreateInfo->minFilter];
- max_anisotropy = RATIO21;
- }
-
- struct GEN8_SAMPLER_STATE sampler_state = {
- .SamplerDisable = false,
- .TextureBorderColorMode = DX10OGL,
- .LODPreClampMode = 0,
- .BaseMipLevel = 0.0,
- .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipMode],
- .MagModeFilter = mag_filter,
- .MinModeFilter = min_filter,
- .TextureLODBias = pCreateInfo->mipLodBias * 256,
- .AnisotropicAlgorithm = EWAApproximation,
- .MinLOD = pCreateInfo->minLod,
- .MaxLOD = pCreateInfo->maxLod,
- .ChromaKeyEnable = 0,
- .ChromaKeyIndex = 0,
- .ChromaKeyMode = 0,
- .ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
- .CubeSurfaceControlMode = 0,
-
- .IndirectStatePointer =
- device->border_colors.offset +
- pCreateInfo->borderColor * sizeof(float) * 4,
-
- .LODClampMagnificationMode = MIPNONE,
- .MaximumAnisotropy = max_anisotropy,
- .RAddressMinFilterRoundingEnable = 0,
- .RAddressMagFilterRoundingEnable = 0,
- .VAddressMinFilterRoundingEnable = 0,
- .VAddressMagFilterRoundingEnable = 0,
- .UAddressMinFilterRoundingEnable = 0,
- .UAddressMagFilterRoundingEnable = 0,
- .TrilinearFilterQuality = 0,
- .NonnormalizedCoordinateEnable = 0,
- .TCXAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressU],
- .TCYAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressV],
- .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressW],
- };
-
- GEN8_SAMPLER_STATE_pack(NULL, sampler->state, &sampler_state);
-
- *pSampler = anv_sampler_to_handle(sampler);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroySampler(
- VkDevice _device,
- VkSampler _sampler)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_sampler, sampler, _sampler);
-
- anv_device_free(device, sampler);
-
- return VK_SUCCESS;
-}
-
-// Descriptor set functions
-
-VkResult anv_CreateDescriptorSetLayout(
- VkDevice _device,
- const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
- VkDescriptorSetLayout* pSetLayout)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_descriptor_set_layout *set_layout;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
-
- uint32_t sampler_count[VK_SHADER_STAGE_NUM] = { 0, };
- uint32_t surface_count[VK_SHADER_STAGE_NUM] = { 0, };
- uint32_t num_dynamic_buffers = 0;
- uint32_t count = 0;
- uint32_t stages = 0;
- uint32_t s;
-
- for (uint32_t i = 0; i < pCreateInfo->count; i++) {
- switch (pCreateInfo->pBinding[i].descriptorType) {
- case VK_DESCRIPTOR_TYPE_SAMPLER:
- case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
- for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
- sampler_count[s] += pCreateInfo->pBinding[i].arraySize;
- break;
- default:
- break;
- }
-
- switch (pCreateInfo->pBinding[i].descriptorType) {
- case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
- case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
- case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
- case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
- case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
- case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
- case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
- case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
- case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
- case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
- for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
- surface_count[s] += pCreateInfo->pBinding[i].arraySize;
- break;
- default:
- break;
- }
-
- switch (pCreateInfo->pBinding[i].descriptorType) {
- case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
- case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
- num_dynamic_buffers += pCreateInfo->pBinding[i].arraySize;
- break;
- default:
- break;
- }
-
- stages |= pCreateInfo->pBinding[i].stageFlags;
- count += pCreateInfo->pBinding[i].arraySize;
- }
-
- uint32_t sampler_total = 0;
- uint32_t surface_total = 0;
- for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
- sampler_total += sampler_count[s];
- surface_total += surface_count[s];
- }
-
- size_t size = sizeof(*set_layout) +
- (sampler_total + surface_total) * sizeof(set_layout->entries[0]);
- set_layout = anv_device_alloc(device, size, 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (!set_layout)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- set_layout->num_dynamic_buffers = num_dynamic_buffers;
- set_layout->count = count;
- set_layout->shader_stages = stages;
-
- struct anv_descriptor_slot *p = set_layout->entries;
- struct anv_descriptor_slot *sampler[VK_SHADER_STAGE_NUM];
- struct anv_descriptor_slot *surface[VK_SHADER_STAGE_NUM];
- for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
- set_layout->stage[s].surface_count = surface_count[s];
- set_layout->stage[s].surface_start = surface[s] = p;
- p += surface_count[s];
- set_layout->stage[s].sampler_count = sampler_count[s];
- set_layout->stage[s].sampler_start = sampler[s] = p;
- p += sampler_count[s];
- }
-
- uint32_t descriptor = 0;
- int8_t dynamic_slot = 0;
- bool is_dynamic;
- for (uint32_t i = 0; i < pCreateInfo->count; i++) {
- switch (pCreateInfo->pBinding[i].descriptorType) {
- case VK_DESCRIPTOR_TYPE_SAMPLER:
- case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
- for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
- for (uint32_t j = 0; j < pCreateInfo->pBinding[i].arraySize; j++) {
- sampler[s]->index = descriptor + j;
- sampler[s]->dynamic_slot = -1;
- sampler[s]++;
- }
- break;
- default:
- break;
- }
-
- switch (pCreateInfo->pBinding[i].descriptorType) {
- case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
- case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
- is_dynamic = true;
- break;
- default:
- is_dynamic = false;
- break;
- }
-
- switch (pCreateInfo->pBinding[i].descriptorType) {
- case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
- case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
- case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
- case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
- case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
- case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
- case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
- case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
- case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
- case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
- for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
- for (uint32_t j = 0; j < pCreateInfo->pBinding[i].arraySize; j++) {
- surface[s]->index = descriptor + j;
- if (is_dynamic)
- surface[s]->dynamic_slot = dynamic_slot + j;
- else
- surface[s]->dynamic_slot = -1;
- surface[s]++;
- }
- break;
- default:
- break;
- }
-
- if (is_dynamic)
- dynamic_slot += pCreateInfo->pBinding[i].arraySize;
-
- descriptor += pCreateInfo->pBinding[i].arraySize;
- }
-
- *pSetLayout = anv_descriptor_set_layout_to_handle(set_layout);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyDescriptorSetLayout(
- VkDevice _device,
- VkDescriptorSetLayout _set_layout)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout, _set_layout);
-
- anv_device_free(device, set_layout);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_CreateDescriptorPool(
- VkDevice device,
- VkDescriptorPoolUsage poolUsage,
- uint32_t maxSets,
- const VkDescriptorPoolCreateInfo* pCreateInfo,
- VkDescriptorPool* pDescriptorPool)
-{
- anv_finishme("VkDescriptorPool is a stub");
- pDescriptorPool->handle = 1;
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyDescriptorPool(
- VkDevice _device,
- VkDescriptorPool _pool)
-{
- anv_finishme("VkDescriptorPool is a stub: free the pool's descriptor sets");
- return VK_SUCCESS;
-}
-
-VkResult anv_ResetDescriptorPool(
- VkDevice device,
- VkDescriptorPool descriptorPool)
-{
- anv_finishme("VkDescriptorPool is a stub: free the pool's descriptor sets");
- return VK_SUCCESS;
-}
-
-VkResult
-anv_descriptor_set_create(struct anv_device *device,
- const struct anv_descriptor_set_layout *layout,
- struct anv_descriptor_set **out_set)
-{
- struct anv_descriptor_set *set;
- size_t size = sizeof(*set) + layout->count * sizeof(set->descriptors[0]);
-
- set = anv_device_alloc(device, size, 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (!set)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- /* A descriptor set may not be 100% filled. Clear the set so we can can
- * later detect holes in it.
- */
- memset(set, 0, size);
-
- *out_set = set;
-
- return VK_SUCCESS;
-}
-
-void
-anv_descriptor_set_destroy(struct anv_device *device,
- struct anv_descriptor_set *set)
-{
- anv_device_free(device, set);
-}
-
-VkResult anv_AllocDescriptorSets(
- VkDevice _device,
- VkDescriptorPool descriptorPool,
- VkDescriptorSetUsage setUsage,
- uint32_t count,
- const VkDescriptorSetLayout* pSetLayouts,
- VkDescriptorSet* pDescriptorSets,
- uint32_t* pCount)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
-
- VkResult result;
- struct anv_descriptor_set *set;
-
- for (uint32_t i = 0; i < count; i++) {
- ANV_FROM_HANDLE(anv_descriptor_set_layout, layout, pSetLayouts[i]);
-
- result = anv_descriptor_set_create(device, layout, &set);
- if (result != VK_SUCCESS) {
- *pCount = i;
- return result;
- }
-
- pDescriptorSets[i] = anv_descriptor_set_to_handle(set);
- }
-
- *pCount = count;
-
- return VK_SUCCESS;
-}
-
-VkResult anv_UpdateDescriptorSets(
- VkDevice device,
- uint32_t writeCount,
- const VkWriteDescriptorSet* pDescriptorWrites,
- uint32_t copyCount,
- const VkCopyDescriptorSet* pDescriptorCopies)
-{
- for (uint32_t i = 0; i < writeCount; i++) {
- const VkWriteDescriptorSet *write = &pDescriptorWrites[i];
- ANV_FROM_HANDLE(anv_descriptor_set, set, write->destSet);
-
- switch (write->descriptorType) {
- case VK_DESCRIPTOR_TYPE_SAMPLER:
- case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
- for (uint32_t j = 0; j < write->count; j++) {
- set->descriptors[write->destBinding + j].sampler =
- anv_sampler_from_handle(write->pDescriptors[j].sampler);
- }
-
- if (write->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
- break;
-
- /* fallthrough */
-
- case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
- case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
- for (uint32_t j = 0; j < write->count; j++) {
- ANV_FROM_HANDLE(anv_image_view, iview,
- write->pDescriptors[j].imageView);
- set->descriptors[write->destBinding + j].view = &iview->view;
- }
- break;
-
- case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
- case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
- anv_finishme("texel buffers not implemented");
- break;
-
- case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
- anv_finishme("input attachments not implemented");
- break;
-
- case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
- case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
- case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
- case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
- for (uint32_t j = 0; j < write->count; j++) {
- ANV_FROM_HANDLE(anv_buffer_view, bview,
- write->pDescriptors[j].bufferView);
- set->descriptors[write->destBinding + j].view = &bview->view;
- }
-
- default:
- break;
- }
- }
-
- for (uint32_t i = 0; i < copyCount; i++) {
- const VkCopyDescriptorSet *copy = &pDescriptorCopies[i];
- ANV_FROM_HANDLE(anv_descriptor_set, src, copy->destSet);
- ANV_FROM_HANDLE(anv_descriptor_set, dest, copy->destSet);
- for (uint32_t j = 0; j < copy->count; j++) {
- dest->descriptors[copy->destBinding + j] =
- src->descriptors[copy->srcBinding + j];
- }
- }
-
- return VK_SUCCESS;
-}
-
-// State object functions
-
-static inline int64_t
-clamp_int64(int64_t x, int64_t min, int64_t max)
-{
- if (x < min)
- return min;
- else if (x < max)
- return x;
- else
- return max;
-}
-
-VkResult anv_CreateDynamicViewportState(
- VkDevice _device,
- const VkDynamicViewportStateCreateInfo* pCreateInfo,
- VkDynamicViewportState* pState)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_dynamic_vp_state *state;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_VIEWPORT_STATE_CREATE_INFO);
-
- state = anv_device_alloc(device, sizeof(*state), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (state == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- unsigned count = pCreateInfo->viewportAndScissorCount;
- state->sf_clip_vp = anv_state_pool_alloc(&device->dynamic_state_pool,
- count * 64, 64);
- state->cc_vp = anv_state_pool_alloc(&device->dynamic_state_pool,
- count * 8, 32);
- state->scissor = anv_state_pool_alloc(&device->dynamic_state_pool,
- count * 32, 32);
-
- for (uint32_t i = 0; i < pCreateInfo->viewportAndScissorCount; i++) {
- const VkViewport *vp = &pCreateInfo->pViewports[i];
- const VkRect2D *s = &pCreateInfo->pScissors[i];
-
- struct GEN8_SF_CLIP_VIEWPORT sf_clip_viewport = {
- .ViewportMatrixElementm00 = vp->width / 2,
- .ViewportMatrixElementm11 = vp->height / 2,
- .ViewportMatrixElementm22 = (vp->maxDepth - vp->minDepth) / 2,
- .ViewportMatrixElementm30 = vp->originX + vp->width / 2,
- .ViewportMatrixElementm31 = vp->originY + vp->height / 2,
- .ViewportMatrixElementm32 = (vp->maxDepth + vp->minDepth) / 2,
- .XMinClipGuardband = -1.0f,
- .XMaxClipGuardband = 1.0f,
- .YMinClipGuardband = -1.0f,
- .YMaxClipGuardband = 1.0f,
- .XMinViewPort = vp->originX,
- .XMaxViewPort = vp->originX + vp->width - 1,
- .YMinViewPort = vp->originY,
- .YMaxViewPort = vp->originY + vp->height - 1,
- };
-
- struct GEN8_CC_VIEWPORT cc_viewport = {
- .MinimumDepth = vp->minDepth,
- .MaximumDepth = vp->maxDepth
- };
-
- /* Since xmax and ymax are inclusive, we have to have xmax < xmin or
- * ymax < ymin for empty clips. In case clip x, y, width height are all
- * 0, the clamps below produce 0 for xmin, ymin, xmax, ymax, which isn't
- * what we want. Just special case empty clips and produce a canonical
- * empty clip. */
- static const struct GEN8_SCISSOR_RECT empty_scissor = {
- .ScissorRectangleYMin = 1,
- .ScissorRectangleXMin = 1,
- .ScissorRectangleYMax = 0,
- .ScissorRectangleXMax = 0
- };
-
- const int max = 0xffff;
- struct GEN8_SCISSOR_RECT scissor = {
- /* Do this math using int64_t so overflow gets clamped correctly. */
- .ScissorRectangleYMin = clamp_int64(s->offset.y, 0, max),
- .ScissorRectangleXMin = clamp_int64(s->offset.x, 0, max),
- .ScissorRectangleYMax = clamp_int64((uint64_t) s->offset.y + s->extent.height - 1, 0, max),
- .ScissorRectangleXMax = clamp_int64((uint64_t) s->offset.x + s->extent.width - 1, 0, max)
- };
-
- GEN8_SF_CLIP_VIEWPORT_pack(NULL, state->sf_clip_vp.map + i * 64, &sf_clip_viewport);
- GEN8_CC_VIEWPORT_pack(NULL, state->cc_vp.map + i * 32, &cc_viewport);
-
- if (s->extent.width <= 0 || s->extent.height <= 0) {
- GEN8_SCISSOR_RECT_pack(NULL, state->scissor.map + i * 32, &empty_scissor);
- } else {
- GEN8_SCISSOR_RECT_pack(NULL, state->scissor.map + i * 32, &scissor);
- }
- }
-
- *pState = anv_dynamic_vp_state_to_handle(state);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyDynamicViewportState(
- VkDevice _device,
- VkDynamicViewportState _vp_state)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_dynamic_vp_state, vp_state, _vp_state);
-
- anv_state_pool_free(&device->dynamic_state_pool, vp_state->sf_clip_vp);
- anv_state_pool_free(&device->dynamic_state_pool, vp_state->cc_vp);
- anv_state_pool_free(&device->dynamic_state_pool, vp_state->scissor);
-
- anv_device_free(device, vp_state);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_CreateDynamicRasterState(
- VkDevice _device,
- const VkDynamicRasterStateCreateInfo* pCreateInfo,
- VkDynamicRasterState* pState)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_dynamic_rs_state *state;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_RASTER_STATE_CREATE_INFO);
-
- state = anv_device_alloc(device, sizeof(*state), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (state == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- struct GEN8_3DSTATE_SF sf = {
- GEN8_3DSTATE_SF_header,
- .LineWidth = pCreateInfo->lineWidth,
- };
-
- GEN8_3DSTATE_SF_pack(NULL, state->state_sf, &sf);
-
- bool enable_bias = pCreateInfo->depthBias != 0.0f ||
- pCreateInfo->slopeScaledDepthBias != 0.0f;
- struct GEN8_3DSTATE_RASTER raster = {
- .GlobalDepthOffsetEnableSolid = enable_bias,
- .GlobalDepthOffsetEnableWireframe = enable_bias,
- .GlobalDepthOffsetEnablePoint = enable_bias,
- .GlobalDepthOffsetConstant = pCreateInfo->depthBias,
- .GlobalDepthOffsetScale = pCreateInfo->slopeScaledDepthBias,
- .GlobalDepthOffsetClamp = pCreateInfo->depthBiasClamp
- };
-
- GEN8_3DSTATE_RASTER_pack(NULL, state->state_raster, &raster);
-
- *pState = anv_dynamic_rs_state_to_handle(state);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyDynamicRasterState(
- VkDevice _device,
- VkDynamicRasterState _rs_state)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_dynamic_rs_state, rs_state, _rs_state);
-
- anv_device_free(device, rs_state);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_CreateDynamicColorBlendState(
- VkDevice _device,
- const VkDynamicColorBlendStateCreateInfo* pCreateInfo,
- VkDynamicColorBlendState* pState)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_dynamic_cb_state *state;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_COLOR_BLEND_STATE_CREATE_INFO);
-
- state = anv_device_alloc(device, sizeof(*state), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (state == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- struct GEN8_COLOR_CALC_STATE color_calc_state = {
- .BlendConstantColorRed = pCreateInfo->blendConst[0],
- .BlendConstantColorGreen = pCreateInfo->blendConst[1],
- .BlendConstantColorBlue = pCreateInfo->blendConst[2],
- .BlendConstantColorAlpha = pCreateInfo->blendConst[3]
- };
-
- GEN8_COLOR_CALC_STATE_pack(NULL, state->state_color_calc, &color_calc_state);
-
- *pState = anv_dynamic_cb_state_to_handle(state);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyDynamicColorBlendState(
- VkDevice _device,
- VkDynamicColorBlendState _cb_state)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_dynamic_cb_state, cb_state, _cb_state);
-
- anv_device_free(device, cb_state);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_CreateDynamicDepthStencilState(
- VkDevice _device,
- const VkDynamicDepthStencilStateCreateInfo* pCreateInfo,
- VkDynamicDepthStencilState* pState)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_dynamic_ds_state *state;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_DEPTH_STENCIL_STATE_CREATE_INFO);
-
- state = anv_device_alloc(device, sizeof(*state), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (state == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- struct GEN8_3DSTATE_WM_DEPTH_STENCIL wm_depth_stencil = {
- GEN8_3DSTATE_WM_DEPTH_STENCIL_header,
-
- /* Is this what we need to do? */
- .StencilBufferWriteEnable = pCreateInfo->stencilWriteMask != 0,
-
- .StencilTestMask = pCreateInfo->stencilReadMask & 0xff,
- .StencilWriteMask = pCreateInfo->stencilWriteMask & 0xff,
-
- .BackfaceStencilTestMask = pCreateInfo->stencilReadMask & 0xff,
- .BackfaceStencilWriteMask = pCreateInfo->stencilWriteMask & 0xff,
- };
-
- GEN8_3DSTATE_WM_DEPTH_STENCIL_pack(NULL, state->state_wm_depth_stencil,
- &wm_depth_stencil);
-
- struct GEN8_COLOR_CALC_STATE color_calc_state = {
- .StencilReferenceValue = pCreateInfo->stencilFrontRef,
- .BackFaceStencilReferenceValue = pCreateInfo->stencilBackRef
- };
-
- GEN8_COLOR_CALC_STATE_pack(NULL, state->state_color_calc, &color_calc_state);
-
- *pState = anv_dynamic_ds_state_to_handle(state);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyDynamicDepthStencilState(
- VkDevice _device,
- VkDynamicDepthStencilState _ds_state)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_dynamic_ds_state, ds_state, _ds_state);
-
- anv_device_free(device, ds_state);
-
- return VK_SUCCESS;
-}
-
-// Command buffer functions
-
-VkResult anv_CreateCommandPool(
- VkDevice device,
- const VkCmdPoolCreateInfo* pCreateInfo,
- VkCmdPool* pCmdPool)
-{
- pCmdPool->handle = 7;
-
- stub_return(VK_SUCCESS);
-}
-
-VkResult anv_DestroyCommandPool(
- VkDevice device,
- VkCmdPool cmdPool)
-{
- stub_return(VK_SUCCESS);
-}
-
-VkResult anv_ResetCommandPool(
- VkDevice device,
- VkCmdPool cmdPool,
- VkCmdPoolResetFlags flags)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_CreateFramebuffer(
- VkDevice _device,
- const VkFramebufferCreateInfo* pCreateInfo,
- VkFramebuffer* pFramebuffer)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_framebuffer *framebuffer;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
-
- size_t size = sizeof(*framebuffer) +
- sizeof(struct anv_attachment_view *) * pCreateInfo->attachmentCount;
- framebuffer = anv_device_alloc(device, size, 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (framebuffer == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- framebuffer->attachment_count = pCreateInfo->attachmentCount;
- for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
- ANV_FROM_HANDLE(anv_attachment_view, view,
- pCreateInfo->pAttachments[i].view);
-
- framebuffer->attachments[i] = view;
- }
-
- framebuffer->width = pCreateInfo->width;
- framebuffer->height = pCreateInfo->height;
- framebuffer->layers = pCreateInfo->layers;
-
- anv_CreateDynamicViewportState(anv_device_to_handle(device),
- &(VkDynamicViewportStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_DYNAMIC_VIEWPORT_STATE_CREATE_INFO,
- .viewportAndScissorCount = 1,
- .pViewports = (VkViewport[]) {
- {
- .originX = 0,
- .originY = 0,
- .width = pCreateInfo->width,
- .height = pCreateInfo->height,
- .minDepth = 0,
- .maxDepth = 1
- },
- },
- .pScissors = (VkRect2D[]) {
- { { 0, 0 },
- { pCreateInfo->width, pCreateInfo->height } },
- }
- },
- &framebuffer->vp_state);
-
- *pFramebuffer = anv_framebuffer_to_handle(framebuffer);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyFramebuffer(
- VkDevice _device,
- VkFramebuffer _fb)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_framebuffer, fb, _fb);
-
- anv_DestroyDynamicViewportState(anv_device_to_handle(device),
- fb->vp_state);
- anv_device_free(device, fb);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_CreateRenderPass(
- VkDevice _device,
- const VkRenderPassCreateInfo* pCreateInfo,
- VkRenderPass* pRenderPass)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_render_pass *pass;
- size_t size;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
-
- size = sizeof(*pass) +
- pCreateInfo->subpassCount * sizeof(struct anv_subpass);
- pass = anv_device_alloc(device, size, 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (pass == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- /* Clear the subpasses along with the parent pass. This required because
- * each array member of anv_subpass must be a valid pointer if not NULL.
- */
- memset(pass, 0, size);
-
- pass->attachment_count = pCreateInfo->attachmentCount;
- pass->subpass_count = pCreateInfo->subpassCount;
-
- size = pCreateInfo->attachmentCount * sizeof(*pass->attachments);
- pass->attachments = anv_device_alloc(device, size, 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
- pass->attachments[i].format = pCreateInfo->pAttachments[i].format;
- pass->attachments[i].samples = pCreateInfo->pAttachments[i].samples;
- pass->attachments[i].load_op = pCreateInfo->pAttachments[i].loadOp;
- pass->attachments[i].stencil_load_op = pCreateInfo->pAttachments[i].stencilLoadOp;
- // pass->attachments[i].store_op = pCreateInfo->pAttachments[i].storeOp;
- // pass->attachments[i].stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
- }
-
- for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
- const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i];
- struct anv_subpass *subpass = &pass->subpasses[i];
-
- subpass->input_count = desc->inputCount;
- subpass->color_count = desc->colorCount;
-
- if (desc->inputCount > 0) {
- subpass->input_attachments =
- anv_device_alloc(device, desc->inputCount * sizeof(uint32_t),
- 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
-
- for (uint32_t j = 0; j < desc->inputCount; j++) {
- subpass->input_attachments[j]
- = desc->inputAttachments[j].attachment;
- }
- }
-
- if (desc->colorCount > 0) {
- subpass->color_attachments =
- anv_device_alloc(device, desc->colorCount * sizeof(uint32_t),
- 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
-
- for (uint32_t j = 0; j < desc->colorCount; j++) {
- subpass->color_attachments[j]
- = desc->colorAttachments[j].attachment;
- }
- }
-
- if (desc->resolveAttachments) {
- subpass->resolve_attachments =
- anv_device_alloc(device, desc->colorCount * sizeof(uint32_t),
- 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
-
- for (uint32_t j = 0; j < desc->colorCount; j++) {
- subpass->resolve_attachments[j]
- = desc->resolveAttachments[j].attachment;
- }
- }
-
- subpass->depth_stencil_attachment = desc->depthStencilAttachment.attachment;
- }
-
- *pRenderPass = anv_render_pass_to_handle(pass);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyRenderPass(
- VkDevice _device,
- VkRenderPass _pass)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_render_pass, pass, _pass);
-
- anv_device_free(device, pass->attachments);
-
- for (uint32_t i = 0; i < pass->subpass_count; i++) {
- /* In VkSubpassCreateInfo, each of the attachment arrays may be null.
- * Don't free the null arrays.
- */
- struct anv_subpass *subpass = &pass->subpasses[i];
-
- anv_device_free(device, subpass->input_attachments);
- anv_device_free(device, subpass->color_attachments);
- anv_device_free(device, subpass->resolve_attachments);
- }
-
- anv_device_free(device, pass);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetRenderAreaGranularity(
- VkDevice device,
- VkRenderPass renderPass,
- VkExtent2D* pGranularity)
-{
- *pGranularity = (VkExtent2D) { 1, 1 };
-
- return VK_SUCCESS;
-}
-
-void vkCmdDbgMarkerBegin(
- VkCmdBuffer cmdBuffer,
- const char* pMarker)
- __attribute__ ((visibility ("default")));
-
-void vkCmdDbgMarkerEnd(
- VkCmdBuffer cmdBuffer)
- __attribute__ ((visibility ("default")));
-
-void vkCmdDbgMarkerBegin(
- VkCmdBuffer cmdBuffer,
- const char* pMarker)
-{
-}
-
-void vkCmdDbgMarkerEnd(
- VkCmdBuffer cmdBuffer)
-{
-}
+++ /dev/null
-/*
- * 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 "private.h"
-
-#define UNSUPPORTED 0xffff
-
-#define fmt(__vk_fmt, ...) \
- [__vk_fmt] = { .name = #__vk_fmt, __VA_ARGS__ }
-
-static const struct anv_format anv_formats[] = {
- fmt(VK_FORMAT_UNDEFINED, RAW, .cpp = 1, .num_channels = 1),
- fmt(VK_FORMAT_R4G4_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_R4G4_USCALED, UNSUPPORTED),
- fmt(VK_FORMAT_R4G4B4A4_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_R4G4B4A4_USCALED, UNSUPPORTED),
- fmt(VK_FORMAT_R5G6B5_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_R5G6B5_USCALED, UNSUPPORTED),
- fmt(VK_FORMAT_R5G5B5A1_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_R5G5B5A1_USCALED, UNSUPPORTED),
- fmt(VK_FORMAT_R8_UNORM, R8_UNORM, .cpp = 1, .num_channels = 1),
- fmt(VK_FORMAT_R8_SNORM, R8_SNORM, .cpp = 1, .num_channels = 1,),
- fmt(VK_FORMAT_R8_USCALED, R8_USCALED, .cpp = 1, .num_channels = 1),
- fmt(VK_FORMAT_R8_SSCALED, R8_SSCALED, .cpp = 1, .num_channels = 1),
- fmt(VK_FORMAT_R8_UINT, R8_UINT, .cpp = 1, .num_channels = 1),
- fmt(VK_FORMAT_R8_SINT, R8_SINT, .cpp = 1, .num_channels = 1),
- fmt(VK_FORMAT_R8_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_R8G8_UNORM, R8G8_UNORM, .cpp = 2, .num_channels = 2),
- fmt(VK_FORMAT_R8G8_SNORM, R8G8_SNORM, .cpp = 2, .num_channels = 2),
- fmt(VK_FORMAT_R8G8_USCALED, R8G8_USCALED, .cpp = 2, .num_channels = 2),
- fmt(VK_FORMAT_R8G8_SSCALED, R8G8_SSCALED, .cpp = 2, .num_channels = 2),
- fmt(VK_FORMAT_R8G8_UINT, R8G8_UINT, .cpp = 2, .num_channels = 2),
- fmt(VK_FORMAT_R8G8_SINT, R8G8_SINT, .cpp = 2, .num_channels = 2),
- fmt(VK_FORMAT_R8G8_SRGB, UNSUPPORTED), /* L8A8_UNORM_SRGB */
- fmt(VK_FORMAT_R8G8B8_UNORM, R8G8B8X8_UNORM, .cpp = 3, .num_channels = 3),
- fmt(VK_FORMAT_R8G8B8_SNORM, R8G8B8_SNORM, .cpp = 3, .num_channels = 3),
- fmt(VK_FORMAT_R8G8B8_USCALED, R8G8B8_USCALED, .cpp = 3, .num_channels = 3),
- fmt(VK_FORMAT_R8G8B8_SSCALED, R8G8B8_SSCALED, .cpp = 3, .num_channels = 3),
- fmt(VK_FORMAT_R8G8B8_UINT, R8G8B8_UINT, .cpp = 3, .num_channels = 3),
- fmt(VK_FORMAT_R8G8B8_SINT, R8G8B8_SINT, .cpp = 3, .num_channels = 3),
- fmt(VK_FORMAT_R8G8B8_SRGB, UNSUPPORTED), /* B8G8R8A8_UNORM_SRGB */
- fmt(VK_FORMAT_R8G8B8A8_UNORM, R8G8B8A8_UNORM, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R8G8B8A8_SNORM, R8G8B8A8_SNORM, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R8G8B8A8_USCALED, R8G8B8A8_USCALED, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R8G8B8A8_SSCALED, R8G8B8A8_SSCALED, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R8G8B8A8_UINT, R8G8B8A8_UINT, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R8G8B8A8_SINT, R8G8B8A8_SINT, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R8G8B8A8_SRGB, R8G8B8A8_UNORM_SRGB, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R10G10B10A2_UNORM, R10G10B10A2_UNORM, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R10G10B10A2_SNORM, R10G10B10A2_SNORM, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R10G10B10A2_USCALED, R10G10B10A2_USCALED, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R10G10B10A2_SSCALED, R10G10B10A2_SSCALED, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R10G10B10A2_UINT, R10G10B10A2_UINT, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R10G10B10A2_SINT, R10G10B10A2_SINT, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_R16_UNORM, R16_UNORM, .cpp = 2, .num_channels = 1),
- fmt(VK_FORMAT_R16_SNORM, R16_SNORM, .cpp = 2, .num_channels = 1),
- fmt(VK_FORMAT_R16_USCALED, R16_USCALED, .cpp = 2, .num_channels = 1),
- fmt(VK_FORMAT_R16_SSCALED, R16_SSCALED, .cpp = 2, .num_channels = 1),
- fmt(VK_FORMAT_R16_UINT, R16_UINT, .cpp = 2, .num_channels = 1),
- fmt(VK_FORMAT_R16_SINT, R16_SINT, .cpp = 2, .num_channels = 1),
- fmt(VK_FORMAT_R16_SFLOAT, R16_FLOAT, .cpp = 2, .num_channels = 1),
- fmt(VK_FORMAT_R16G16_UNORM, R16G16_UNORM, .cpp = 4, .num_channels = 2),
- fmt(VK_FORMAT_R16G16_SNORM, R16G16_SNORM, .cpp = 4, .num_channels = 2),
- fmt(VK_FORMAT_R16G16_USCALED, R16G16_USCALED, .cpp = 4, .num_channels = 2),
- fmt(VK_FORMAT_R16G16_SSCALED, R16G16_SSCALED, .cpp = 4, .num_channels = 2),
- fmt(VK_FORMAT_R16G16_UINT, R16G16_UINT, .cpp = 4, .num_channels = 2),
- fmt(VK_FORMAT_R16G16_SINT, R16G16_SINT, .cpp = 4, .num_channels = 2),
- fmt(VK_FORMAT_R16G16_SFLOAT, R16G16_FLOAT, .cpp = 4, .num_channels = 2),
- fmt(VK_FORMAT_R16G16B16_UNORM, R16G16B16_UNORM, .cpp = 6, .num_channels = 3),
- fmt(VK_FORMAT_R16G16B16_SNORM, R16G16B16_SNORM, .cpp = 6, .num_channels = 3),
- fmt(VK_FORMAT_R16G16B16_USCALED, R16G16B16_USCALED, .cpp = 6, .num_channels = 3),
- fmt(VK_FORMAT_R16G16B16_SSCALED, R16G16B16_SSCALED, .cpp = 6, .num_channels = 3),
- fmt(VK_FORMAT_R16G16B16_UINT, R16G16B16_UINT, .cpp = 6, .num_channels = 3),
- fmt(VK_FORMAT_R16G16B16_SINT, R16G16B16_SINT, .cpp = 6, .num_channels = 3),
- fmt(VK_FORMAT_R16G16B16_SFLOAT, R16G16B16_FLOAT, .cpp = 6, .num_channels = 3),
- fmt(VK_FORMAT_R16G16B16A16_UNORM, R16G16B16A16_UNORM, .cpp = 8, .num_channels = 4),
- fmt(VK_FORMAT_R16G16B16A16_SNORM, R16G16B16A16_SNORM, .cpp = 8, .num_channels = 4),
- fmt(VK_FORMAT_R16G16B16A16_USCALED, R16G16B16A16_USCALED, .cpp = 8, .num_channels = 4),
- fmt(VK_FORMAT_R16G16B16A16_SSCALED, R16G16B16A16_SSCALED, .cpp = 8, .num_channels = 4),
- fmt(VK_FORMAT_R16G16B16A16_UINT, R16G16B16A16_UINT, .cpp = 8, .num_channels = 4),
- fmt(VK_FORMAT_R16G16B16A16_SINT, R16G16B16A16_SINT, .cpp = 8, .num_channels = 4),
- fmt(VK_FORMAT_R16G16B16A16_SFLOAT, R16G16B16A16_FLOAT, .cpp = 8, .num_channels = 4),
- fmt(VK_FORMAT_R32_UINT, R32_UINT, .cpp = 4, .num_channels = 1,),
- fmt(VK_FORMAT_R32_SINT, R32_SINT, .cpp = 4, .num_channels = 1,),
- fmt(VK_FORMAT_R32_SFLOAT, R32_FLOAT, .cpp = 4, .num_channels = 1,),
- fmt(VK_FORMAT_R32G32_UINT, R32G32_UINT, .cpp = 8, .num_channels = 2,),
- fmt(VK_FORMAT_R32G32_SINT, R32G32_SINT, .cpp = 8, .num_channels = 2,),
- fmt(VK_FORMAT_R32G32_SFLOAT, R32G32_FLOAT, .cpp = 8, .num_channels = 2,),
- fmt(VK_FORMAT_R32G32B32_UINT, R32G32B32_UINT, .cpp = 12, .num_channels = 3,),
- fmt(VK_FORMAT_R32G32B32_SINT, R32G32B32_SINT, .cpp = 12, .num_channels = 3,),
- fmt(VK_FORMAT_R32G32B32_SFLOAT, R32G32B32_FLOAT, .cpp = 12, .num_channels = 3,),
- fmt(VK_FORMAT_R32G32B32A32_UINT, R32G32B32A32_UINT, .cpp = 16, .num_channels = 4,),
- fmt(VK_FORMAT_R32G32B32A32_SINT, R32G32B32A32_SINT, .cpp = 16, .num_channels = 4,),
- fmt(VK_FORMAT_R32G32B32A32_SFLOAT, R32G32B32A32_FLOAT, .cpp = 16, .num_channels = 4,),
- fmt(VK_FORMAT_R64_SFLOAT, R64_FLOAT, .cpp = 8, .num_channels = 1),
- fmt(VK_FORMAT_R64G64_SFLOAT, R64G64_FLOAT, .cpp = 16, .num_channels = 2),
- fmt(VK_FORMAT_R64G64B64_SFLOAT, R64G64B64_FLOAT, .cpp = 24, .num_channels = 3),
- fmt(VK_FORMAT_R64G64B64A64_SFLOAT, R64G64B64A64_FLOAT, .cpp = 32, .num_channels = 4),
- fmt(VK_FORMAT_R11G11B10_UFLOAT, R11G11B10_FLOAT, .cpp = 4, .num_channels = 3),
- fmt(VK_FORMAT_R9G9B9E5_UFLOAT, R9G9B9E5_SHAREDEXP, .cpp = 4, .num_channels = 3),
-
- fmt(VK_FORMAT_D16_UNORM, R16_UNORM, .cpp = 2, .num_channels = 1, .depth_format = D16_UNORM),
- fmt(VK_FORMAT_D24_UNORM, R24_UNORM_X8_TYPELESS, .cpp = 4, .num_channels = 1, .depth_format = D24_UNORM_X8_UINT),
- fmt(VK_FORMAT_D32_SFLOAT, R32_FLOAT, .cpp = 4, .num_channels = 1, .depth_format = D32_FLOAT),
- fmt(VK_FORMAT_S8_UINT, R8_UINT, .cpp = 1, .num_channels = 1, .has_stencil = true),
- fmt(VK_FORMAT_D16_UNORM_S8_UINT, R16_UNORM, .cpp = 2, .num_channels = 2, .depth_format = D16_UNORM, .has_stencil = true),
- fmt(VK_FORMAT_D24_UNORM_S8_UINT, R24_UNORM_X8_TYPELESS, .cpp = 4, .num_channels = 2, .depth_format = D24_UNORM_X8_UINT, .has_stencil = true),
- fmt(VK_FORMAT_D32_SFLOAT_S8_UINT, R32_FLOAT, .cpp = 4, .num_channels = 2, .depth_format = D32_FLOAT, .has_stencil = true),
-
- fmt(VK_FORMAT_BC1_RGB_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_BC1_RGB_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_BC1_RGBA_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_BC1_RGBA_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_BC2_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_BC2_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_BC3_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_BC3_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_BC4_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_BC4_SNORM, UNSUPPORTED),
- fmt(VK_FORMAT_BC5_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_BC5_SNORM, UNSUPPORTED),
- fmt(VK_FORMAT_BC6H_UFLOAT, UNSUPPORTED),
- fmt(VK_FORMAT_BC6H_SFLOAT, UNSUPPORTED),
- fmt(VK_FORMAT_BC7_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_BC7_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ETC2_R8G8B8_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ETC2_R8G8B8_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ETC2_R8G8B8A1_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ETC2_R8G8B8A1_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ETC2_R8G8B8A8_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ETC2_R8G8B8A8_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_EAC_R11_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_EAC_R11_SNORM, UNSUPPORTED),
- fmt(VK_FORMAT_EAC_R11G11_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_EAC_R11G11_SNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_4x4_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_4x4_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_5x4_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_5x4_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_5x5_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_5x5_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_6x5_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_6x5_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_6x6_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_6x6_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_8x5_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_8x5_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_8x6_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_8x6_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_8x8_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_8x8_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_10x5_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_10x5_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_10x6_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_10x6_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_10x8_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_10x8_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_10x10_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_10x10_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_12x10_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_12x10_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_12x12_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_ASTC_12x12_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_B4G4R4A4_UNORM, B4G4R4A4_UNORM, .cpp = 2, .num_channels = 4),
- fmt(VK_FORMAT_B5G5R5A1_UNORM, B5G5R5A1_UNORM, .cpp = 2, .num_channels = 4),
- fmt(VK_FORMAT_B5G6R5_UNORM, B5G6R5_UNORM, .cpp = 2, .num_channels = 3),
- fmt(VK_FORMAT_B5G6R5_USCALED, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8_UNORM, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8_SNORM, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8_USCALED, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8_SSCALED, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8_UINT, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8_SINT, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8_SRGB, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8A8_UNORM, B8G8R8A8_UNORM, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_B8G8R8A8_SNORM, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8A8_USCALED, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8A8_SSCALED, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8A8_UINT, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8A8_SINT, UNSUPPORTED),
- fmt(VK_FORMAT_B8G8R8A8_SRGB, B8G8R8A8_UNORM_SRGB, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_B10G10R10A2_UNORM, B10G10R10A2_UNORM, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_B10G10R10A2_SNORM, B10G10R10A2_SNORM, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_B10G10R10A2_USCALED, B10G10R10A2_USCALED, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_B10G10R10A2_SSCALED, B10G10R10A2_SSCALED, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_B10G10R10A2_UINT, B10G10R10A2_UINT, .cpp = 4, .num_channels = 4),
- fmt(VK_FORMAT_B10G10R10A2_SINT, B10G10R10A2_SINT, .cpp = 4, .num_channels = 4)
-};
-
-#undef fmt
-
-const struct anv_format *
-anv_format_for_vk_format(VkFormat format)
-{
- return &anv_formats[format];
-}
-
-bool
-anv_is_vk_format_depth_or_stencil(VkFormat format)
-{
- const struct anv_format *format_info =
- anv_format_for_vk_format(format);
-
- if (format_info->depth_format != UNSUPPORTED &&
- format_info->depth_format != 0)
- return true;
-
- return format_info->has_stencil;
-}
-
-// Format capabilities
-
-struct surface_format_info {
- bool exists;
- int sampling;
- int filtering;
- int shadow_compare;
- int chroma_key;
- int render_target;
- int alpha_blend;
- int input_vb;
- int streamed_output_vb;
- int color_processing;
-};
-
-extern const struct surface_format_info surface_formats[];
-
-VkResult anv_validate_GetPhysicalDeviceFormatProperties(
- VkPhysicalDevice physicalDevice,
- VkFormat _format,
- VkFormatProperties* pFormatProperties)
-{
- const struct anv_format *format = anv_format_for_vk_format(_format);
- fprintf(stderr, "vkGetFormatProperties(%s)\n", format->name);
- return anv_GetPhysicalDeviceFormatProperties(physicalDevice, _format, pFormatProperties);
-}
-
-VkResult anv_GetPhysicalDeviceFormatProperties(
- VkPhysicalDevice physicalDevice,
- VkFormat _format,
- VkFormatProperties* pFormatProperties)
-{
- ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
- const struct surface_format_info *info;
- int gen;
-
- const struct anv_format *format = anv_format_for_vk_format(_format);
- if (format == NULL)
- return vk_error(VK_ERROR_INVALID_VALUE);
-
- gen = physical_device->info->gen * 10;
- if (physical_device->info->is_haswell)
- gen += 5;
-
- if (format->surface_format == UNSUPPORTED)
- goto unsupported;
-
- info = &surface_formats[format->surface_format];
- if (!info->exists)
- goto unsupported;
-
- uint32_t linear = 0, tiled = 0;
- if (info->sampling <= gen) {
- linear |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
- tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
- }
- if (info->render_target <= gen) {
- linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
- tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
- }
- if (info->alpha_blend <= gen) {
- linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
- tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
- }
- if (info->input_vb <= gen) {
- linear |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
- }
-
- pFormatProperties->linearTilingFeatures = linear;
- pFormatProperties->optimalTilingFeatures = tiled;
-
- return VK_SUCCESS;
-
- unsupported:
- pFormatProperties->linearTilingFeatures = 0;
- pFormatProperties->optimalTilingFeatures = 0;
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetPhysicalDeviceImageFormatProperties(
- VkPhysicalDevice physicalDevice,
- VkFormat format,
- VkImageType type,
- VkImageTiling tiling,
- VkImageUsageFlags usage,
- VkImageFormatProperties* pImageFormatProperties)
-{
- /* TODO: We should do something here. Chad? */
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_GetPhysicalDeviceSparseImageFormatProperties(
- VkPhysicalDevice physicalDevice,
- VkFormat format,
- VkImageType type,
- uint32_t samples,
- VkImageUsageFlags usage,
- VkImageTiling tiling,
- uint32_t* pNumProperties,
- VkSparseImageFormatProperties* pProperties)
-{
- stub_return(VK_UNSUPPORTED);
-}
+++ /dev/null
-/*
- * 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.
- */
-
-#define _DEFAULT_SOURCE
-
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "private.h"
-
-#define VG_CLEAR(s) VG(memset(&s, 0, sizeof(s)))
-
-static int
-anv_ioctl(int fd, unsigned long request, void *arg)
-{
- int ret;
-
- do {
- ret = ioctl(fd, request, arg);
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
-
- return ret;
-}
-
-/**
- * Wrapper around DRM_IOCTL_I915_GEM_CREATE.
- *
- * Return gem handle, or 0 on failure. Gem handles are never 0.
- */
-uint32_t
-anv_gem_create(struct anv_device *device, size_t size)
-{
- struct drm_i915_gem_create gem_create;
- int ret;
-
- VG_CLEAR(gem_create);
- gem_create.size = size;
-
- ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
- if (ret != 0) {
- /* FIXME: What do we do if this fails? */
- return 0;
- }
-
- return gem_create.handle;
-}
-
-void
-anv_gem_close(struct anv_device *device, int gem_handle)
-{
- struct drm_gem_close close;
-
- VG_CLEAR(close);
- close.handle = gem_handle;
- anv_ioctl(device->fd, DRM_IOCTL_GEM_CLOSE, &close);
-}
-
-/**
- * Wrapper around DRM_IOCTL_I915_GEM_MMAP.
- */
-void*
-anv_gem_mmap(struct anv_device *device, uint32_t gem_handle,
- uint64_t offset, uint64_t size)
-{
- struct drm_i915_gem_mmap gem_mmap;
- int ret;
-
- gem_mmap.handle = gem_handle;
- VG_CLEAR(gem_mmap.pad);
- gem_mmap.offset = offset;
- gem_mmap.size = size;
- VG_CLEAR(gem_mmap.addr_ptr);
-
-#ifdef I915_MMAP_WC
- gem_mmap.flags = 0;
-#endif
-
- ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_mmap);
- if (ret != 0) {
- /* FIXME: Is NULL the right error return? Cf MAP_INVALID */
- return NULL;
- }
-
- VG(VALGRIND_MALLOCLIKE_BLOCK(gem_mmap.addr_ptr, gem_mmap.size, 0, 1));
- return (void *)(uintptr_t) gem_mmap.addr_ptr;
-}
-
-/* This is just a wrapper around munmap, but it also notifies valgrind that
- * this map is no longer valid. Pair this with anv_gem_mmap().
- */
-void
-anv_gem_munmap(void *p, uint64_t size)
-{
- VG(VALGRIND_FREELIKE_BLOCK(p, 0));
- munmap(p, size);
-}
-
-int
-anv_gem_userptr(struct anv_device *device, void *mem, size_t size)
-{
- struct drm_i915_gem_userptr userptr;
- int ret;
-
- VG_CLEAR(userptr);
- userptr.user_ptr = (__u64)((unsigned long) mem);
- userptr.user_size = size;
- userptr.flags = 0;
-
- ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_USERPTR, &userptr);
- if (ret == -1)
- return 0;
-
- return userptr.handle;
-}
-
-/**
- * On error, \a timeout_ns holds the remaining time.
- */
-int
-anv_gem_wait(struct anv_device *device, int gem_handle, int64_t *timeout_ns)
-{
- struct drm_i915_gem_wait wait;
- int ret;
-
- VG_CLEAR(wait);
- wait.bo_handle = gem_handle;
- wait.timeout_ns = *timeout_ns;
- wait.flags = 0;
-
- ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_WAIT, &wait);
- *timeout_ns = wait.timeout_ns;
-
- return ret;
-}
-
-int
-anv_gem_execbuffer(struct anv_device *device,
- struct drm_i915_gem_execbuffer2 *execbuf)
-{
- return anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
-}
-
-int
-anv_gem_set_tiling(struct anv_device *device,
- int gem_handle, uint32_t stride, uint32_t tiling)
-{
- struct drm_i915_gem_set_tiling set_tiling;
- int ret;
-
- /* set_tiling overwrites the input on the error path, so we have to open
- * code anv_ioctl.
- */
-
- do {
- VG_CLEAR(set_tiling);
- set_tiling.handle = gem_handle;
- set_tiling.tiling_mode = I915_TILING_X;
- set_tiling.stride = stride;
-
- ret = ioctl(device->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
-
- return ret;
-}
-
-int
-anv_gem_get_param(int fd, uint32_t param)
-{
- drm_i915_getparam_t gp;
- int ret, tmp;
-
- VG_CLEAR(gp);
- gp.param = param;
- gp.value = &tmp;
- ret = anv_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
- if (ret == 0)
- return tmp;
-
- return 0;
-}
-
-int
-anv_gem_create_context(struct anv_device *device)
-{
- struct drm_i915_gem_context_create create;
- int ret;
-
- VG_CLEAR(create);
-
- ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create);
- if (ret == -1)
- return -1;
-
- return create.ctx_id;
-}
-
-int
-anv_gem_destroy_context(struct anv_device *device, int context)
-{
- struct drm_i915_gem_context_destroy destroy;
-
- VG_CLEAR(destroy);
- destroy.ctx_id = context;
-
- return anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy);
-}
-
-int
-anv_gem_get_aperture(struct anv_physical_device *physical_dev, uint64_t *size)
-{
- struct drm_i915_gem_get_aperture aperture;
- int ret;
-
- VG_CLEAR(aperture);
- ret = anv_ioctl(physical_dev->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
- if (ret == -1)
- return -1;
-
- *size = aperture.aper_available_size;
-
- return 0;
-}
-
-int
-anv_gem_handle_to_fd(struct anv_device *device, int gem_handle)
-{
- struct drm_prime_handle args;
- int ret;
-
- VG_CLEAR(args);
- args.handle = gem_handle;
- args.flags = DRM_CLOEXEC;
-
- ret = anv_ioctl(device->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
- if (ret == -1)
- return -1;
-
- return args.fd;
-}
-
-int
-anv_gem_fd_to_handle(struct anv_device *device, int fd)
-{
- struct drm_prime_handle args;
- int ret;
-
- VG_CLEAR(args);
- args.fd = fd;
-
- ret = anv_ioctl(device->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
- if (ret == -1)
- return 0;
-
- return args.handle;
-}
+++ /dev/null
-/*
- * 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 <assert.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "private.h"
-
-struct anv_image_view_info {
- uint8_t surface_type; /**< RENDER_SURFACE_STATE.SurfaceType */
- bool is_array:1; /**< RENDER_SURFACE_STATE.SurfaceArray */
- bool is_cube:1; /**< RENDER_SURFACE_STATE.CubeFaceEnable* */
-};
-
-static const uint8_t anv_halign[] = {
- [4] = HALIGN4,
- [8] = HALIGN8,
- [16] = HALIGN16,
-};
-
-static const uint8_t anv_valign[] = {
- [4] = VALIGN4,
- [8] = VALIGN8,
- [16] = VALIGN16,
-};
-
-static const uint8_t anv_surf_type_from_image_type[] = {
- [VK_IMAGE_TYPE_1D] = SURFTYPE_1D,
- [VK_IMAGE_TYPE_2D] = SURFTYPE_2D,
- [VK_IMAGE_TYPE_3D] = SURFTYPE_3D,
-
-};
-
-static const struct anv_image_view_info
-anv_image_view_info_table[] = {
- #define INFO(s, ...) { .surface_type = s, __VA_ARGS__ }
- [VK_IMAGE_VIEW_TYPE_1D] = INFO(SURFTYPE_1D),
- [VK_IMAGE_VIEW_TYPE_2D] = INFO(SURFTYPE_2D),
- [VK_IMAGE_VIEW_TYPE_3D] = INFO(SURFTYPE_3D),
- [VK_IMAGE_VIEW_TYPE_CUBE] = INFO(SURFTYPE_CUBE, .is_cube = 1),
- [VK_IMAGE_VIEW_TYPE_1D_ARRAY] = INFO(SURFTYPE_1D, .is_array = 1),
- [VK_IMAGE_VIEW_TYPE_2D_ARRAY] = INFO(SURFTYPE_2D, .is_array = 1),
- [VK_IMAGE_VIEW_TYPE_CUBE_ARRAY] = INFO(SURFTYPE_CUBE, .is_array = 1, .is_cube = 1),
- #undef INFO
-};
-
-static const struct anv_surf_type_limits {
- int32_t width;
- int32_t height;
- int32_t depth;
-} anv_surf_type_limits[] = {
- [SURFTYPE_1D] = {16384, 0, 2048},
- [SURFTYPE_2D] = {16384, 16384, 2048},
- [SURFTYPE_3D] = {2048, 2048, 2048},
- [SURFTYPE_CUBE] = {16384, 16384, 340},
- [SURFTYPE_BUFFER] = {128, 16384, 64},
- [SURFTYPE_STRBUF] = {128, 16384, 64},
-};
-
-static const struct anv_tile_info {
- uint32_t width;
- uint32_t height;
-
- /**
- * Alignment for RENDER_SURFACE_STATE.SurfaceBaseAddress.
- *
- * To simplify calculations, the alignments defined in the table are
- * sometimes larger than required. For example, Skylake requires that X and
- * Y tiled buffers be aligned to 4K, but Broadwell permits smaller
- * alignment. We choose 4K to accomodate both chipsets. The alignment of
- * a linear buffer depends on its element type and usage. Linear depth
- * buffers have the largest alignment, 64B, so we choose that for all linear
- * buffers.
- */
- uint32_t surface_alignment;
-} anv_tile_info_table[] = {
- [LINEAR] = { 1, 1, 64 },
- [XMAJOR] = { 512, 8, 4096 },
- [YMAJOR] = { 128, 32, 4096 },
- [WMAJOR] = { 128, 32, 4096 },
-};
-
-static uint32_t
-anv_image_choose_tile_mode(const struct anv_image_create_info *anv_info)
-{
- if (anv_info->force_tile_mode)
- return anv_info->tile_mode;
-
- if (anv_info->vk_info->format == VK_FORMAT_S8_UINT)
- return WMAJOR;
-
- switch (anv_info->vk_info->tiling) {
- case VK_IMAGE_TILING_LINEAR:
- return LINEAR;
- case VK_IMAGE_TILING_OPTIMAL:
- return YMAJOR;
- default:
- assert(!"bad VKImageTiling");
- return LINEAR;
- }
-}
-
-static VkResult
-anv_image_make_surface(const struct anv_image_create_info *create_info,
- uint64_t *inout_image_size,
- uint32_t *inout_image_alignment,
- struct anv_surface *out_surface)
-{
- /* See RENDER_SURFACE_STATE.SurfaceQPitch */
- static const uint16_t min_qpitch UNUSED = 0x4;
- static const uint16_t max_qpitch UNUSED = 0x1ffc;
-
- const VkExtent3D *restrict extent = &create_info->vk_info->extent;
- const uint32_t levels = create_info->vk_info->mipLevels;
- const uint32_t array_size = create_info->vk_info->arraySize;
-
- const uint8_t tile_mode = anv_image_choose_tile_mode(create_info);
-
- const struct anv_tile_info *tile_info =
- &anv_tile_info_table[tile_mode];
-
- const struct anv_format *format_info =
- anv_format_for_vk_format(create_info->vk_info->format);
-
- const uint32_t i = 4; /* FINISHME: Stop hardcoding subimage alignment */
- const uint32_t j = 4; /* FINISHME: Stop hardcoding subimage alignment */
- const uint32_t w0 = align_u32(extent->width, i);
- const uint32_t h0 = align_u32(extent->height, j);
-
- uint16_t qpitch;
- uint32_t mt_width;
- uint32_t mt_height;
-
- if (levels == 1 && array_size == 1) {
- qpitch = min_qpitch;
- mt_width = w0;
- mt_height = h0;
- } else {
- uint32_t w1 = align_u32(anv_minify(extent->width, 1), i);
- uint32_t h1 = align_u32(anv_minify(extent->height, 1), j);
- uint32_t w2 = align_u32(anv_minify(extent->width, 2), i);
-
- qpitch = h0 + h1 + 11 * j;
- mt_width = MAX(w0, w1 + w2);
- mt_height = array_size * qpitch;
- }
-
- assert(qpitch >= min_qpitch);
- if (qpitch > max_qpitch) {
- anv_loge("image qpitch > 0x%x\n", max_qpitch);
- return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
- }
-
- /* From the Broadwell PRM, RENDER_SURFACE_STATE.SurfaceQpitch:
- *
- * This field must be set an integer multiple of the Surface Vertical
- * Alignment.
- */
- assert(anv_is_aligned(qpitch, j));
-
- const uint32_t stride = align_u32(mt_width * format_info->cpp,
- tile_info->width);
- const uint32_t size = stride * align_u32(mt_height, tile_info->height);
- const uint32_t offset = align_u32(*inout_image_size,
- tile_info->surface_alignment);
-
- *inout_image_size = offset + size;
- *inout_image_alignment = MAX(*inout_image_alignment,
- tile_info->surface_alignment);
-
- *out_surface = (struct anv_surface) {
- .offset = offset,
- .stride = stride,
- .tile_mode = tile_mode,
- .qpitch = qpitch,
- .h_align = i,
- .v_align = j,
- };
-
- return VK_SUCCESS;
-}
-
-VkResult
-anv_image_create(VkDevice _device,
- const struct anv_image_create_info *create_info,
- VkImage *pImage)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
- const VkExtent3D *restrict extent = &pCreateInfo->extent;
- struct anv_image *image = NULL;
- VkResult r;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
-
- /* XXX: We don't handle any of these */
- anv_assert(pCreateInfo->imageType == VK_IMAGE_TYPE_2D);
- anv_assert(pCreateInfo->mipLevels > 0);
- anv_assert(pCreateInfo->arraySize > 0);
- anv_assert(pCreateInfo->samples == 1);
- anv_assert(pCreateInfo->extent.width > 0);
- anv_assert(pCreateInfo->extent.height > 0);
- anv_assert(pCreateInfo->extent.depth > 0);
-
- /* TODO(chadv): How should we validate inputs? */
- const uint8_t surf_type =
- anv_surf_type_from_image_type[pCreateInfo->imageType];
-
- const struct anv_surf_type_limits *limits =
- &anv_surf_type_limits[surf_type];
-
- if (extent->width > limits->width ||
- extent->height > limits->height ||
- extent->depth > limits->depth) {
- /* TODO(chadv): What is the correct error? */
- anv_loge("image extent is too large");
- return vk_error(VK_ERROR_INVALID_MEMORY_SIZE);
- }
-
- const struct anv_format *format_info =
- anv_format_for_vk_format(pCreateInfo->format);
-
- image = anv_device_alloc(device, sizeof(*image), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (!image)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- memset(image, 0, sizeof(*image));
- image->type = pCreateInfo->imageType;
- image->extent = pCreateInfo->extent;
- image->format = pCreateInfo->format;
- image->levels = pCreateInfo->mipLevels;
- image->array_size = pCreateInfo->arraySize;
- image->surf_type = surf_type;
-
- if (likely(!format_info->has_stencil || format_info->depth_format)) {
- /* The image's primary surface is a color or depth surface. */
- r = anv_image_make_surface(create_info, &image->size, &image->alignment,
- &image->primary_surface);
- if (r != VK_SUCCESS)
- goto fail;
- }
-
- if (format_info->has_stencil) {
- /* From the GPU's perspective, the depth buffer and stencil buffer are
- * separate buffers. From Vulkan's perspective, though, depth and
- * stencil reside in the same image. To satisfy Vulkan and the GPU, we
- * place the depth and stencil buffers in the same bo.
- */
- VkImageCreateInfo stencil_info = *pCreateInfo;
- stencil_info.format = VK_FORMAT_S8_UINT;
-
- r = anv_image_make_surface(
- &(struct anv_image_create_info) {
- .vk_info = &stencil_info,
- },
- &image->size, &image->alignment, &image->stencil_surface);
-
- if (r != VK_SUCCESS)
- goto fail;
- }
-
- *pImage = anv_image_to_handle(image);
-
- return VK_SUCCESS;
-
-fail:
- if (image)
- anv_device_free(device, image);
-
- return r;
-}
-
-VkResult
-anv_CreateImage(VkDevice device,
- const VkImageCreateInfo *pCreateInfo,
- VkImage *pImage)
-{
- return anv_image_create(device,
- &(struct anv_image_create_info) {
- .vk_info = pCreateInfo,
- },
- pImage);
-}
-
-VkResult
-anv_DestroyImage(VkDevice _device, VkImage _image)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
-
- anv_device_free(device, anv_image_from_handle(_image));
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetImageSubresourceLayout(
- VkDevice device,
- VkImage image,
- const VkImageSubresource* pSubresource,
- VkSubresourceLayout* pLayout)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-void
-anv_surface_view_fini(struct anv_device *device,
- struct anv_surface_view *view)
-{
- anv_state_pool_free(&device->surface_state_pool, view->surface_state);
-}
-
-void
-anv_image_view_init(struct anv_image_view *iview,
- struct anv_device *device,
- const VkImageViewCreateInfo* pCreateInfo,
- struct anv_cmd_buffer *cmd_buffer)
-{
- ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
-
- const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
- struct anv_surface_view *view = &iview->view;
- struct anv_surface *surface;
-
- const struct anv_format *format_info =
- anv_format_for_vk_format(pCreateInfo->format);
-
- const struct anv_image_view_info *view_type_info
- = &anv_image_view_info_table[pCreateInfo->viewType];
-
- if (pCreateInfo->viewType != VK_IMAGE_VIEW_TYPE_2D)
- anv_finishme("non-2D image views");
-
- switch (pCreateInfo->subresourceRange.aspect) {
- case VK_IMAGE_ASPECT_STENCIL:
- anv_finishme("stencil image views");
- abort();
- break;
- case VK_IMAGE_ASPECT_DEPTH:
- case VK_IMAGE_ASPECT_COLOR:
- view->offset = image->offset;
- surface = &image->primary_surface;
- break;
- default:
- unreachable("");
- break;
- }
-
- view->bo = image->bo;
- view->offset = image->offset + surface->offset;
- view->format = pCreateInfo->format;
-
- iview->extent = (VkExtent3D) {
- .width = anv_minify(image->extent.width, range->baseMipLevel),
- .height = anv_minify(image->extent.height, range->baseMipLevel),
- .depth = anv_minify(image->extent.depth, range->baseMipLevel),
- };
-
- uint32_t depth = 1;
- if (range->arraySize > 1) {
- depth = range->arraySize;
- } else if (image->extent.depth > 1) {
- depth = image->extent.depth;
- }
-
- static const uint32_t vk_to_gen_swizzle[] = {
- [VK_CHANNEL_SWIZZLE_ZERO] = SCS_ZERO,
- [VK_CHANNEL_SWIZZLE_ONE] = SCS_ONE,
- [VK_CHANNEL_SWIZZLE_R] = SCS_RED,
- [VK_CHANNEL_SWIZZLE_G] = SCS_GREEN,
- [VK_CHANNEL_SWIZZLE_B] = SCS_BLUE,
- [VK_CHANNEL_SWIZZLE_A] = SCS_ALPHA
- };
-
- struct GEN8_RENDER_SURFACE_STATE surface_state = {
- .SurfaceType = view_type_info->surface_type,
- .SurfaceArray = image->array_size > 1,
- .SurfaceFormat = format_info->surface_format,
- .SurfaceVerticalAlignment = anv_valign[surface->v_align],
- .SurfaceHorizontalAlignment = anv_halign[surface->h_align],
- .TileMode = surface->tile_mode,
- .VerticalLineStride = 0,
- .VerticalLineStrideOffset = 0,
- .SamplerL2BypassModeDisable = true,
- .RenderCacheReadWriteMode = WriteOnlyCache,
- .MemoryObjectControlState = GEN8_MOCS,
-
- /* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
- * RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
- * both Base Mip Level fields nonzero".
- */
- .BaseMipLevel = 0.0,
-
- .SurfaceQPitch = surface->qpitch >> 2,
- .Height = image->extent.height - 1,
- .Width = image->extent.width - 1,
- .Depth = depth - 1,
- .SurfacePitch = surface->stride - 1,
- .MinimumArrayElement = range->baseArraySlice,
- .NumberofMultisamples = MULTISAMPLECOUNT_1,
- .XOffset = 0,
- .YOffset = 0,
-
- /* For sampler surfaces, the hardware interprets field MIPCount/LOD as
- * MIPCount. The range of levels accessible by the sampler engine is
- * [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
- */
- .MIPCountLOD = range->mipLevels - 1,
- .SurfaceMinLOD = range->baseMipLevel,
-
- .AuxiliarySurfaceMode = AUX_NONE,
- .RedClearColor = 0,
- .GreenClearColor = 0,
- .BlueClearColor = 0,
- .AlphaClearColor = 0,
- .ShaderChannelSelectRed = vk_to_gen_swizzle[pCreateInfo->channels.r],
- .ShaderChannelSelectGreen = vk_to_gen_swizzle[pCreateInfo->channels.g],
- .ShaderChannelSelectBlue = vk_to_gen_swizzle[pCreateInfo->channels.b],
- .ShaderChannelSelectAlpha = vk_to_gen_swizzle[pCreateInfo->channels.a],
- .ResourceMinLOD = 0.0,
- .SurfaceBaseAddress = { NULL, view->offset },
- };
-
- if (cmd_buffer) {
- view->surface_state =
- anv_state_stream_alloc(&cmd_buffer->surface_state_stream, 64, 64);
- } else {
- view->surface_state =
- anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
- }
-
- GEN8_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &surface_state);
-}
-
-VkResult
-anv_validate_CreateImageView(VkDevice _device,
- const VkImageViewCreateInfo *pCreateInfo,
- VkImageView *pView)
-{
- ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
- const VkImageSubresourceRange *subresource;
- const struct anv_image_view_info *view_info;
- const struct anv_format *view_format_info;
- const struct anv_format *image_format_info;
-
- /* Validate structure type before dereferencing it. */
- assert(pCreateInfo);
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
- subresource = &pCreateInfo->subresourceRange;
-
- /* Validate viewType is in range before using it. */
- assert(pCreateInfo->viewType >= VK_IMAGE_VIEW_TYPE_BEGIN_RANGE);
- assert(pCreateInfo->viewType <= VK_IMAGE_VIEW_TYPE_END_RANGE);
- view_info = &anv_image_view_info_table[pCreateInfo->viewType];
-
- /* Validate format is in range before using it. */
- assert(pCreateInfo->format >= VK_FORMAT_BEGIN_RANGE);
- assert(pCreateInfo->format <= VK_FORMAT_END_RANGE);
- image_format_info = anv_format_for_vk_format(image->format);
- view_format_info = anv_format_for_vk_format(pCreateInfo->format);
-
- /* Validate channel swizzles. */
- assert(pCreateInfo->channels.r >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
- assert(pCreateInfo->channels.r <= VK_CHANNEL_SWIZZLE_END_RANGE);
- assert(pCreateInfo->channels.g >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
- assert(pCreateInfo->channels.g <= VK_CHANNEL_SWIZZLE_END_RANGE);
- assert(pCreateInfo->channels.b >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
- assert(pCreateInfo->channels.b <= VK_CHANNEL_SWIZZLE_END_RANGE);
- assert(pCreateInfo->channels.a >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
- assert(pCreateInfo->channels.a <= VK_CHANNEL_SWIZZLE_END_RANGE);
-
- /* Validate subresource. */
- assert(subresource->aspect >= VK_IMAGE_ASPECT_BEGIN_RANGE);
- assert(subresource->aspect <= VK_IMAGE_ASPECT_END_RANGE);
- assert(subresource->mipLevels > 0);
- assert(subresource->arraySize > 0);
- assert(subresource->baseMipLevel < image->levels);
- assert(subresource->baseMipLevel + subresource->mipLevels <= image->levels);
- assert(subresource->baseArraySlice < image->array_size);
- assert(subresource->baseArraySlice + subresource->arraySize <= image->array_size);
- assert(pView);
-
- if (view_info->is_cube) {
- assert(subresource->baseArraySlice % 6 == 0);
- assert(subresource->arraySize % 6 == 0);
- }
-
- /* Validate format. */
- switch (subresource->aspect) {
- case VK_IMAGE_ASPECT_COLOR:
- assert(!image_format_info->depth_format);
- assert(!image_format_info->has_stencil);
- assert(!view_format_info->depth_format);
- assert(!view_format_info->has_stencil);
- assert(view_format_info->cpp == image_format_info->cpp);
- break;
- case VK_IMAGE_ASPECT_DEPTH:
- assert(image_format_info->depth_format);
- assert(view_format_info->depth_format);
- assert(view_format_info->cpp == image_format_info->cpp);
- break;
- case VK_IMAGE_ASPECT_STENCIL:
- /* FINISHME: Is it legal to have an R8 view of S8? */
- assert(image_format_info->has_stencil);
- assert(view_format_info->has_stencil);
- break;
- default:
- assert(!"bad VkImageAspect");
- break;
- }
-
- return anv_CreateImageView(_device, pCreateInfo, pView);
-}
-
-VkResult
-anv_CreateImageView(VkDevice _device,
- const VkImageViewCreateInfo *pCreateInfo,
- VkImageView *pView)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_image_view *view;
-
- view = anv_device_alloc(device, sizeof(*view), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (view == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- anv_image_view_init(view, device, pCreateInfo, NULL);
-
- *pView = anv_image_view_to_handle(view);
-
- return VK_SUCCESS;
-}
-
-VkResult
-anv_DestroyImageView(VkDevice _device, VkImageView _iview)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_image_view, iview, _iview);
-
- anv_surface_view_fini(device, &iview->view);
- anv_device_free(device, iview);
-
- return VK_SUCCESS;
-}
-
-void
-anv_color_attachment_view_init(struct anv_color_attachment_view *aview,
- struct anv_device *device,
- const VkAttachmentViewCreateInfo* pCreateInfo,
- struct anv_cmd_buffer *cmd_buffer)
-{
- ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
- struct anv_surface_view *view = &aview->view;
- struct anv_surface *surface = &image->primary_surface;
- const struct anv_format *format_info =
- anv_format_for_vk_format(pCreateInfo->format);
-
- aview->base.attachment_type = ANV_ATTACHMENT_VIEW_TYPE_COLOR;
-
- anv_assert(pCreateInfo->arraySize > 0);
- anv_assert(pCreateInfo->mipLevel < image->levels);
- anv_assert(pCreateInfo->baseArraySlice + pCreateInfo->arraySize <= image->array_size);
-
- view->bo = image->bo;
- view->offset = image->offset + surface->offset;
- view->format = pCreateInfo->format;
-
- aview->base.extent = (VkExtent3D) {
- .width = anv_minify(image->extent.width, pCreateInfo->mipLevel),
- .height = anv_minify(image->extent.height, pCreateInfo->mipLevel),
- .depth = anv_minify(image->extent.depth, pCreateInfo->mipLevel),
- };
-
- uint32_t depth = 1;
- if (pCreateInfo->arraySize > 1) {
- depth = pCreateInfo->arraySize;
- } else if (image->extent.depth > 1) {
- depth = image->extent.depth;
- }
-
- if (cmd_buffer) {
- view->surface_state =
- anv_state_stream_alloc(&cmd_buffer->surface_state_stream, 64, 64);
- } else {
- view->surface_state =
- anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
- }
-
- struct GEN8_RENDER_SURFACE_STATE surface_state = {
- .SurfaceType = SURFTYPE_2D,
- .SurfaceArray = image->array_size > 1,
- .SurfaceFormat = format_info->surface_format,
- .SurfaceVerticalAlignment = anv_valign[surface->v_align],
- .SurfaceHorizontalAlignment = anv_halign[surface->h_align],
- .TileMode = surface->tile_mode,
- .VerticalLineStride = 0,
- .VerticalLineStrideOffset = 0,
- .SamplerL2BypassModeDisable = true,
- .RenderCacheReadWriteMode = WriteOnlyCache,
- .MemoryObjectControlState = GEN8_MOCS,
-
- /* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
- * RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
- * both Base Mip Level fields nonzero".
- */
- .BaseMipLevel = 0.0,
-
- .SurfaceQPitch = surface->qpitch >> 2,
- .Height = image->extent.height - 1,
- .Width = image->extent.width - 1,
- .Depth = depth - 1,
- .SurfacePitch = surface->stride - 1,
- .MinimumArrayElement = pCreateInfo->baseArraySlice,
- .NumberofMultisamples = MULTISAMPLECOUNT_1,
- .XOffset = 0,
- .YOffset = 0,
-
- /* For render target surfaces, the hardware interprets field MIPCount/LOD as
- * LOD. The Broadwell PRM says:
- *
- * MIPCountLOD defines the LOD that will be rendered into.
- * SurfaceMinLOD is ignored.
- */
- .SurfaceMinLOD = 0,
- .MIPCountLOD = pCreateInfo->mipLevel,
-
- .AuxiliarySurfaceMode = AUX_NONE,
- .RedClearColor = 0,
- .GreenClearColor = 0,
- .BlueClearColor = 0,
- .AlphaClearColor = 0,
- .ShaderChannelSelectRed = SCS_RED,
- .ShaderChannelSelectGreen = SCS_GREEN,
- .ShaderChannelSelectBlue = SCS_BLUE,
- .ShaderChannelSelectAlpha = SCS_ALPHA,
- .ResourceMinLOD = 0.0,
- .SurfaceBaseAddress = { NULL, view->offset },
- };
-
- GEN8_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &surface_state);
-}
-
-static void
-anv_depth_stencil_view_init(struct anv_depth_stencil_view *view,
- const VkAttachmentViewCreateInfo *pCreateInfo)
-{
- ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
- struct anv_surface *depth_surface = &image->primary_surface;
- struct anv_surface *stencil_surface = &image->stencil_surface;
- const struct anv_format *format =
- anv_format_for_vk_format(image->format);
-
- view->base.attachment_type = ANV_ATTACHMENT_VIEW_TYPE_DEPTH_STENCIL;
-
- /* XXX: We don't handle any of these */
- anv_assert(pCreateInfo->mipLevel == 0);
- anv_assert(pCreateInfo->baseArraySlice == 0);
- anv_assert(pCreateInfo->arraySize == 1);
-
- view->bo = image->bo;
-
- view->depth_stride = depth_surface->stride;
- view->depth_offset = image->offset + depth_surface->offset;
- view->depth_format = format->depth_format;
- view->depth_qpitch = 0; /* FINISHME: QPitch */
-
- view->stencil_stride = stencil_surface->stride;
- view->stencil_offset = image->offset + stencil_surface->offset;
- view->stencil_qpitch = 0; /* FINISHME: QPitch */
-}
-
-VkResult
-anv_CreateAttachmentView(VkDevice _device,
- const VkAttachmentViewCreateInfo *pCreateInfo,
- VkAttachmentView *pView)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO);
-
- if (anv_is_vk_format_depth_or_stencil(pCreateInfo->format)) {
- struct anv_depth_stencil_view *view =
- anv_device_alloc(device, sizeof(*view), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (view == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- anv_depth_stencil_view_init(view, pCreateInfo);
-
- *pView = anv_attachment_view_to_handle(&view->base);
- } else {
- struct anv_color_attachment_view *view =
- anv_device_alloc(device, sizeof(*view), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (view == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- anv_color_attachment_view_init(view, device, pCreateInfo, NULL);
-
- *pView = anv_attachment_view_to_handle(&view->base);
- }
-
- return VK_SUCCESS;
-}
-
-VkResult
-anv_DestroyAttachmentView(VkDevice _device, VkAttachmentView _view)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_attachment_view, view, _view);
-
- if (view->attachment_type == ANV_ATTACHMENT_VIEW_TYPE_COLOR) {
- struct anv_color_attachment_view *aview =
- (struct anv_color_attachment_view *)view;
-
- anv_surface_view_fini(device, &aview->view);
- }
-
- anv_device_free(device, view);
-
- return VK_SUCCESS;
-}
+++ /dev/null
-/*
- * 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 <assert.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "private.h"
-
-VkResult anv_CreateDmaBufImageINTEL(
- VkDevice _device,
- const VkDmaBufImageCreateInfo* pCreateInfo,
- VkDeviceMemory* pMem,
- VkImage* pImage)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_device_memory *mem;
- struct anv_image *image;
- VkResult result;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL);
-
- mem = anv_device_alloc(device, sizeof(*mem), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (mem == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- mem->bo.gem_handle = anv_gem_fd_to_handle(device, pCreateInfo->fd);
- if (!mem->bo.gem_handle) {
- result = vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
- goto fail;
- }
-
- mem->bo.map = NULL;
- mem->bo.index = 0;
- mem->bo.offset = 0;
- mem->bo.size = pCreateInfo->strideInBytes * pCreateInfo->extent.height;
-
- image = anv_device_alloc(device, sizeof(*image), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (image == NULL) {
- result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
- goto fail_mem;
- }
-
- *image = (struct anv_image) {
- .bo = &mem->bo,
- .offset = 0,
- .type = VK_IMAGE_TYPE_2D,
- .extent = pCreateInfo->extent,
- .size = mem->bo.size,
-
- .primary_surface = {
- .offset = 0,
- .stride = pCreateInfo->strideInBytes,
- .tile_mode = XMAJOR,
- },
- };
-
- assert(image->extent.width > 0);
- assert(image->extent.height > 0);
- assert(image->extent.depth == 1);
-
- *pMem = anv_device_memory_to_handle(mem);
- *pImage = anv_image_to_handle(image);
-
- return VK_SUCCESS;
-
- fail_mem:
- anv_gem_close(device, mem->bo.gem_handle);
- fail:
- anv_device_free(device, mem);
-
- return result;
-}
+++ /dev/null
-/*
- * 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 <assert.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "private.h"
-#include "meta-spirv.h"
-
-static void
-anv_device_init_meta_clear_state(struct anv_device *device)
-{
- /* We don't use a vertex shader for clearing, but instead build and pass
- * the VUEs directly to the rasterization backend.
- */
- VkShaderModule fsm = GLSL_VK_SHADER_MODULE(device, FRAGMENT,
- out vec4 f_color;
- flat in vec4 v_color;
- void main()
- {
- f_color = v_color;
- }
- );
-
- VkShader fs;
- anv_CreateShader(anv_device_to_handle(device),
- &(VkShaderCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
- .module = fsm,
- .pName = "main",
- }, &fs);
-
- /* We use instanced rendering to clear multiple render targets. We have two
- * vertex buffers: the first vertex buffer holds per-vertex data and
- * provides the vertices for the clear rectangle. The second one holds
- * per-instance data, which consists of the VUE header (which selects the
- * layer) and the color (Vulkan supports per-RT clear colors).
- */
- VkPipelineVertexInputStateCreateInfo vi_create_info = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
- .bindingCount = 2,
- .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
- {
- .binding = 0,
- .strideInBytes = 8,
- .stepRate = VK_VERTEX_INPUT_STEP_RATE_VERTEX
- },
- {
- .binding = 1,
- .strideInBytes = 32,
- .stepRate = VK_VERTEX_INPUT_STEP_RATE_INSTANCE
- },
- },
- .attributeCount = 3,
- .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
- {
- /* VUE Header */
- .location = 0,
- .binding = 1,
- .format = VK_FORMAT_R32G32B32A32_UINT,
- .offsetInBytes = 0
- },
- {
- /* Position */
- .location = 1,
- .binding = 0,
- .format = VK_FORMAT_R32G32_SFLOAT,
- .offsetInBytes = 0
- },
- {
- /* Color */
- .location = 2,
- .binding = 1,
- .format = VK_FORMAT_R32G32B32A32_SFLOAT,
- .offsetInBytes = 16
- }
- }
- };
-
- anv_pipeline_create(anv_device_to_handle(device),
- &(VkGraphicsPipelineCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
- .stageCount = 1,
- .pStages = &(VkPipelineShaderStageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_FRAGMENT,
- .shader = fs,
- .pSpecializationInfo = NULL,
- },
- .pVertexInputState = &vi_create_info,
- .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
- .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
- .primitiveRestartEnable = false,
- },
- .pRasterState = &(VkPipelineRasterStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTER_STATE_CREATE_INFO,
- .depthClipEnable = true,
- .rasterizerDiscardEnable = false,
- .fillMode = VK_FILL_MODE_SOLID,
- .cullMode = VK_CULL_MODE_NONE,
- .frontFace = VK_FRONT_FACE_CCW
- },
- .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
- .attachmentCount = 1,
- .pAttachments = (VkPipelineColorBlendAttachmentState []) {
- { .channelWriteMask = VK_CHANNEL_A_BIT |
- VK_CHANNEL_R_BIT | VK_CHANNEL_G_BIT | VK_CHANNEL_B_BIT },
- }
- },
- .flags = 0,
- },
- &(struct anv_pipeline_create_info) {
- .use_repclear = true,
- .disable_viewport = true,
- .use_rectlist = true
- },
- &device->meta_state.clear.pipeline);
-
- anv_DestroyShader(anv_device_to_handle(device), fs);
-}
-
-#define NUM_VB_USED 2
-struct anv_saved_state {
- struct anv_vertex_binding old_vertex_bindings[NUM_VB_USED];
- struct anv_descriptor_set *old_descriptor_set0;
- struct anv_pipeline *old_pipeline;
- VkDynamicColorBlendState cb_state;
-};
-
-static void
-anv_cmd_buffer_save(struct anv_cmd_buffer *cmd_buffer,
- struct anv_saved_state *state)
-{
- state->old_pipeline = cmd_buffer->state.pipeline;
- state->old_descriptor_set0 = cmd_buffer->state.descriptors[0].set;
- memcpy(state->old_vertex_bindings, cmd_buffer->state.vertex_bindings,
- sizeof(state->old_vertex_bindings));
-}
-
-static void
-anv_cmd_buffer_restore(struct anv_cmd_buffer *cmd_buffer,
- const struct anv_saved_state *state)
-{
- cmd_buffer->state.pipeline = state->old_pipeline;
- cmd_buffer->state.descriptors[0].set = state->old_descriptor_set0;
- memcpy(cmd_buffer->state.vertex_bindings, state->old_vertex_bindings,
- sizeof(state->old_vertex_bindings));
-
- cmd_buffer->state.vb_dirty |= (1 << NUM_VB_USED) - 1;
- cmd_buffer->state.dirty |= ANV_CMD_BUFFER_PIPELINE_DIRTY;
- cmd_buffer->state.descriptors_dirty |= VK_SHADER_STAGE_VERTEX_BIT;
-}
-
-struct vue_header {
- uint32_t Reserved;
- uint32_t RTAIndex;
- uint32_t ViewportIndex;
- float PointWidth;
-};
-
-struct clear_instance_data {
- struct vue_header vue_header;
- VkClearColorValue color;
-};
-
-static void
-meta_emit_clear(struct anv_cmd_buffer *cmd_buffer,
- int num_instances,
- struct clear_instance_data *instance_data)
-{
- struct anv_device *device = cmd_buffer->device;
- struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
- struct anv_state state;
- uint32_t size;
-
- const float vertex_data[] = {
- /* Rect-list coordinates */
- 0.0, 0.0,
- fb->width, 0.0,
- fb->width, fb->height,
-
- /* Align to 16 bytes */
- 0.0, 0.0,
- };
-
- size = sizeof(vertex_data) + num_instances * sizeof(*instance_data);
- state = anv_state_stream_alloc(&cmd_buffer->surface_state_stream, size, 16);
-
- /* Copy in the vertex and instance data */
- memcpy(state.map, vertex_data, sizeof(vertex_data));
- memcpy(state.map + sizeof(vertex_data), instance_data,
- num_instances * sizeof(*instance_data));
-
- struct anv_buffer vertex_buffer = {
- .device = cmd_buffer->device,
- .size = size,
- .bo = &device->surface_state_block_pool.bo,
- .offset = state.offset
- };
-
- anv_CmdBindVertexBuffers(anv_cmd_buffer_to_handle(cmd_buffer), 0, 2,
- (VkBuffer[]) {
- anv_buffer_to_handle(&vertex_buffer),
- anv_buffer_to_handle(&vertex_buffer)
- },
- (VkDeviceSize[]) {
- 0,
- sizeof(vertex_data)
- });
-
- if (cmd_buffer->state.pipeline != anv_pipeline_from_handle(device->meta_state.clear.pipeline))
- anv_CmdBindPipeline(anv_cmd_buffer_to_handle(cmd_buffer),
- VK_PIPELINE_BIND_POINT_GRAPHICS,
- device->meta_state.clear.pipeline);
-
- /* We don't need anything here, only set if not already set. */
- if (cmd_buffer->state.rs_state == NULL)
- anv_CmdBindDynamicRasterState(anv_cmd_buffer_to_handle(cmd_buffer),
- device->meta_state.shared.rs_state);
-
- if (cmd_buffer->state.vp_state == NULL)
- anv_CmdBindDynamicViewportState(anv_cmd_buffer_to_handle(cmd_buffer),
- cmd_buffer->state.framebuffer->vp_state);
-
- if (cmd_buffer->state.ds_state == NULL)
- anv_CmdBindDynamicDepthStencilState(anv_cmd_buffer_to_handle(cmd_buffer),
- device->meta_state.shared.ds_state);
-
- if (cmd_buffer->state.cb_state == NULL)
- anv_CmdBindDynamicColorBlendState(anv_cmd_buffer_to_handle(cmd_buffer),
- device->meta_state.shared.cb_state);
-
- anv_CmdDraw(anv_cmd_buffer_to_handle(cmd_buffer), 0, 3, 0, num_instances);
-}
-
-void
-anv_cmd_buffer_clear_attachments(struct anv_cmd_buffer *cmd_buffer,
- struct anv_render_pass *pass,
- const VkClearValue *clear_values)
-{
- struct anv_saved_state saved_state;
-
- int num_clear_layers = 0;
- for (uint32_t i = 0; i < pass->attachment_count; i++) {
- if (pass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
- if (anv_is_vk_format_depth_or_stencil(pass->attachments[i].format)) {
- anv_finishme("Can't clear depth-stencil yet");
- continue;
- }
- num_clear_layers++;
- }
- }
-
- if (num_clear_layers == 0)
- return;
-
- struct clear_instance_data instance_data[num_clear_layers];
- uint32_t color_attachments[num_clear_layers];
-
- int layer = 0;
- for (uint32_t i = 0; i < pass->attachment_count; i++) {
- if (pass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_CLEAR &&
- !anv_is_vk_format_depth_or_stencil(pass->attachments[i].format)) {
- instance_data[layer] = (struct clear_instance_data) {
- .vue_header = {
- .RTAIndex = i,
- .ViewportIndex = 0,
- .PointWidth = 0.0
- },
- .color = clear_values[i].color,
- };
- color_attachments[layer] = i;
- layer++;
- }
- }
-
- anv_cmd_buffer_save(cmd_buffer, &saved_state);
-
- struct anv_subpass subpass = {
- .input_count = 0,
- .color_count = num_clear_layers,
- .color_attachments = color_attachments,
- .depth_stencil_attachment = VK_ATTACHMENT_UNUSED,
- };
-
- anv_cmd_buffer_begin_subpass(cmd_buffer, &subpass);
-
- meta_emit_clear(cmd_buffer, num_clear_layers, instance_data);
-
- /* Restore API state */
- anv_cmd_buffer_restore(cmd_buffer, &saved_state);
-}
-
-static void
-anv_device_init_meta_blit_state(struct anv_device *device)
-{
- /* We don't use a vertex shader for clearing, but instead build and pass
- * the VUEs directly to the rasterization backend. However, we do need
- * to provide GLSL source for the vertex shader so that the compiler
- * does not dead-code our inputs.
- */
- VkShaderModule vsm = GLSL_VK_SHADER_MODULE(device, VERTEX,
- in vec2 a_pos;
- in vec2 a_tex_coord;
- out vec4 v_tex_coord;
- void main()
- {
- v_tex_coord = vec4(a_tex_coord, 0, 1);
- gl_Position = vec4(a_pos, 0, 1);
- }
- );
-
- VkShaderModule fsm = GLSL_VK_SHADER_MODULE(device, FRAGMENT,
- out vec4 f_color;
- in vec4 v_tex_coord;
- layout(set = 0, binding = 0) uniform sampler2D u_tex;
- void main()
- {
- f_color = texture(u_tex, v_tex_coord.xy);
- }
- );
-
- VkShader vs;
- anv_CreateShader(anv_device_to_handle(device),
- &(VkShaderCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
- .module = vsm,
- .pName = "main",
- }, &vs);
-
- VkShader fs;
- anv_CreateShader(anv_device_to_handle(device),
- &(VkShaderCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
- .module = fsm,
- .pName = "main",
- }, &fs);
-
- VkPipelineVertexInputStateCreateInfo vi_create_info = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
- .bindingCount = 2,
- .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
- {
- .binding = 0,
- .strideInBytes = 0,
- .stepRate = VK_VERTEX_INPUT_STEP_RATE_VERTEX
- },
- {
- .binding = 1,
- .strideInBytes = 16,
- .stepRate = VK_VERTEX_INPUT_STEP_RATE_VERTEX
- },
- },
- .attributeCount = 3,
- .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
- {
- /* VUE Header */
- .location = 0,
- .binding = 0,
- .format = VK_FORMAT_R32G32B32A32_UINT,
- .offsetInBytes = 0
- },
- {
- /* Position */
- .location = 1,
- .binding = 1,
- .format = VK_FORMAT_R32G32_SFLOAT,
- .offsetInBytes = 0
- },
- {
- /* Texture Coordinate */
- .location = 2,
- .binding = 1,
- .format = VK_FORMAT_R32G32_SFLOAT,
- .offsetInBytes = 8
- }
- }
- };
-
- VkDescriptorSetLayoutCreateInfo ds_layout_info = {
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .count = 1,
- .pBinding = (VkDescriptorSetLayoutBinding[]) {
- {
- .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
- .arraySize = 1,
- .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
- .pImmutableSamplers = NULL
- },
- }
- };
- anv_CreateDescriptorSetLayout(anv_device_to_handle(device), &ds_layout_info,
- &device->meta_state.blit.ds_layout);
-
- anv_CreatePipelineLayout(anv_device_to_handle(device),
- &(VkPipelineLayoutCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- .descriptorSetCount = 1,
- .pSetLayouts = &device->meta_state.blit.ds_layout,
- },
- &device->meta_state.blit.pipeline_layout);
-
- anv_pipeline_create(anv_device_to_handle(device),
- &(VkGraphicsPipelineCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
- .stageCount = 2,
- .pStages = (VkPipelineShaderStageCreateInfo[]) {
- {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_VERTEX,
- .shader = vs,
- .pSpecializationInfo = NULL
- }, {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_FRAGMENT,
- .shader = fs,
- .pSpecializationInfo = NULL
- },
- },
- .pVertexInputState = &vi_create_info,
- .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
- .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
- .primitiveRestartEnable = false,
- },
- .pRasterState = &(VkPipelineRasterStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTER_STATE_CREATE_INFO,
- .depthClipEnable = true,
- .rasterizerDiscardEnable = false,
- .fillMode = VK_FILL_MODE_SOLID,
- .cullMode = VK_CULL_MODE_NONE,
- .frontFace = VK_FRONT_FACE_CCW
- },
- .pColorBlendState = &(VkPipelineColorBlendStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
- .attachmentCount = 1,
- .pAttachments = (VkPipelineColorBlendAttachmentState []) {
- { .channelWriteMask = VK_CHANNEL_A_BIT |
- VK_CHANNEL_R_BIT | VK_CHANNEL_G_BIT | VK_CHANNEL_B_BIT },
- }
- },
- .flags = 0,
- .layout = device->meta_state.blit.pipeline_layout,
- },
- &(struct anv_pipeline_create_info) {
- .use_repclear = false,
- .disable_viewport = true,
- .disable_scissor = true,
- .disable_vs = true,
- .use_rectlist = true
- },
- &device->meta_state.blit.pipeline);
-
- anv_DestroyShader(anv_device_to_handle(device), vs);
- anv_DestroyShader(anv_device_to_handle(device), fs);
-}
-
-static void
-meta_prepare_blit(struct anv_cmd_buffer *cmd_buffer,
- struct anv_saved_state *saved_state)
-{
- struct anv_device *device = cmd_buffer->device;
-
- anv_cmd_buffer_save(cmd_buffer, saved_state);
-
- if (cmd_buffer->state.pipeline != anv_pipeline_from_handle(device->meta_state.blit.pipeline))
- anv_CmdBindPipeline(anv_cmd_buffer_to_handle(cmd_buffer),
- VK_PIPELINE_BIND_POINT_GRAPHICS,
- device->meta_state.blit.pipeline);
-
- /* We don't need anything here, only set if not already set. */
- if (cmd_buffer->state.rs_state == NULL)
- anv_CmdBindDynamicRasterState(anv_cmd_buffer_to_handle(cmd_buffer),
- device->meta_state.shared.rs_state);
- if (cmd_buffer->state.ds_state == NULL)
- anv_CmdBindDynamicDepthStencilState(anv_cmd_buffer_to_handle(cmd_buffer),
- device->meta_state.shared.ds_state);
-
- saved_state->cb_state = anv_dynamic_cb_state_to_handle(cmd_buffer->state.cb_state);
- anv_CmdBindDynamicColorBlendState(anv_cmd_buffer_to_handle(cmd_buffer),
- device->meta_state.shared.cb_state);
-}
-
-struct blit_region {
- VkOffset3D src_offset;
- VkExtent3D src_extent;
- VkOffset3D dest_offset;
- VkExtent3D dest_extent;
-};
-
-static void
-meta_emit_blit(struct anv_cmd_buffer *cmd_buffer,
- struct anv_image_view *src,
- VkOffset3D src_offset,
- VkExtent3D src_extent,
- struct anv_color_attachment_view *dest,
- VkOffset3D dest_offset,
- VkExtent3D dest_extent)
-{
- struct anv_device *device = cmd_buffer->device;
- VkDescriptorPool dummy_desc_pool = { .handle = 1 };
-
- struct blit_vb_data {
- float pos[2];
- float tex_coord[2];
- } *vb_data;
-
- unsigned vb_size = sizeof(struct vue_header) + 3 * sizeof(*vb_data);
-
- struct anv_state vb_state =
- anv_state_stream_alloc(&cmd_buffer->surface_state_stream, vb_size, 16);
- memset(vb_state.map, 0, sizeof(struct vue_header));
- vb_data = vb_state.map + sizeof(struct vue_header);
-
- vb_data[0] = (struct blit_vb_data) {
- .pos = {
- dest_offset.x + dest_extent.width,
- dest_offset.y + dest_extent.height,
- },
- .tex_coord = {
- (float)(src_offset.x + src_extent.width) / (float)src->extent.width,
- (float)(src_offset.y + src_extent.height) / (float)src->extent.height,
- },
- };
-
- vb_data[1] = (struct blit_vb_data) {
- .pos = {
- dest_offset.x,
- dest_offset.y + dest_extent.height,
- },
- .tex_coord = {
- (float)src_offset.x / (float)src->extent.width,
- (float)(src_offset.y + src_extent.height) / (float)src->extent.height,
- },
- };
-
- vb_data[2] = (struct blit_vb_data) {
- .pos = {
- dest_offset.x,
- dest_offset.y,
- },
- .tex_coord = {
- (float)src_offset.x / (float)src->extent.width,
- (float)src_offset.y / (float)src->extent.height,
- },
- };
-
- struct anv_buffer vertex_buffer = {
- .device = device,
- .size = vb_size,
- .bo = &device->surface_state_block_pool.bo,
- .offset = vb_state.offset,
- };
-
- anv_CmdBindVertexBuffers(anv_cmd_buffer_to_handle(cmd_buffer), 0, 2,
- (VkBuffer[]) {
- anv_buffer_to_handle(&vertex_buffer),
- anv_buffer_to_handle(&vertex_buffer)
- },
- (VkDeviceSize[]) {
- 0,
- sizeof(struct vue_header),
- });
-
- uint32_t count;
- VkDescriptorSet set;
- anv_AllocDescriptorSets(anv_device_to_handle(device), dummy_desc_pool,
- VK_DESCRIPTOR_SET_USAGE_ONE_SHOT,
- 1, &device->meta_state.blit.ds_layout, &set, &count);
- anv_UpdateDescriptorSets(anv_device_to_handle(device),
- 1, /* writeCount */
- (VkWriteDescriptorSet[]) {
- {
- .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- .destSet = set,
- .destBinding = 0,
- .destArrayElement = 0,
- .count = 1,
- .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
- .pDescriptors = (VkDescriptorInfo[]) {
- {
- .imageView = anv_image_view_to_handle(src),
- .imageLayout = VK_IMAGE_LAYOUT_GENERAL
- },
- }
- }
- }, 0, NULL);
-
- VkFramebuffer fb;
- anv_CreateFramebuffer(anv_device_to_handle(device),
- &(VkFramebufferCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
- .attachmentCount = 1,
- .pAttachments = (VkAttachmentBindInfo[]) {
- {
- .view = anv_attachment_view_to_handle(&dest->base),
- .layout = VK_IMAGE_LAYOUT_GENERAL
- }
- },
- .width = dest->base.extent.width,
- .height = dest->base.extent.height,
- .layers = 1
- }, &fb);
-
- VkRenderPass pass;
- anv_CreateRenderPass(anv_device_to_handle(device),
- &(VkRenderPassCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
- .attachmentCount = 1,
- .pAttachments = &(VkAttachmentDescription) {
- .sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION,
- .format = dest->view.format,
- .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
- .initialLayout = VK_IMAGE_LAYOUT_GENERAL,
- .finalLayout = VK_IMAGE_LAYOUT_GENERAL,
- },
- .subpassCount = 1,
- .pSubpasses = &(VkSubpassDescription) {
- .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION,
- .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
- .inputCount = 0,
- .colorCount = 1,
- .colorAttachments = &(VkAttachmentReference) {
- .attachment = 0,
- .layout = VK_IMAGE_LAYOUT_GENERAL,
- },
- .resolveAttachments = NULL,
- .depthStencilAttachment = (VkAttachmentReference) {
- .attachment = VK_ATTACHMENT_UNUSED,
- .layout = VK_IMAGE_LAYOUT_GENERAL,
- },
- .preserveCount = 1,
- .preserveAttachments = &(VkAttachmentReference) {
- .attachment = 0,
- .layout = VK_IMAGE_LAYOUT_GENERAL,
- },
- },
- .dependencyCount = 0,
- }, &pass);
-
- anv_CmdBeginRenderPass(anv_cmd_buffer_to_handle(cmd_buffer),
- &(VkRenderPassBeginInfo) {
- .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
- .renderPass = pass,
- .framebuffer = fb,
- .renderArea = {
- .offset = { dest_offset.x, dest_offset.y },
- .extent = { dest_extent.width, dest_extent.height },
- },
- .attachmentCount = 1,
- .pAttachmentClearValues = NULL,
- }, VK_RENDER_PASS_CONTENTS_INLINE);
-
- anv_CmdBindDynamicViewportState(anv_cmd_buffer_to_handle(cmd_buffer),
- anv_framebuffer_from_handle(fb)->vp_state);
-
- anv_CmdBindDescriptorSets(anv_cmd_buffer_to_handle(cmd_buffer),
- VK_PIPELINE_BIND_POINT_GRAPHICS,
- device->meta_state.blit.pipeline_layout, 0, 1,
- &set, 0, NULL);
-
- anv_CmdDraw(anv_cmd_buffer_to_handle(cmd_buffer), 0, 3, 0, 1);
-
- anv_CmdEndRenderPass(anv_cmd_buffer_to_handle(cmd_buffer));
-
- /* At the point where we emit the draw call, all data from the
- * descriptor sets, etc. has been used. We are free to delete it.
- */
- anv_descriptor_set_destroy(device, anv_descriptor_set_from_handle(set));
- anv_DestroyFramebuffer(anv_device_to_handle(device), fb);
- anv_DestroyRenderPass(anv_device_to_handle(device), pass);
-}
-
-static void
-meta_finish_blit(struct anv_cmd_buffer *cmd_buffer,
- const struct anv_saved_state *saved_state)
-{
- anv_cmd_buffer_restore(cmd_buffer, saved_state);
- anv_CmdBindDynamicColorBlendState(anv_cmd_buffer_to_handle(cmd_buffer),
- saved_state->cb_state);
-}
-
-static VkFormat
-vk_format_for_cpp(int cpp)
-{
- switch (cpp) {
- case 1: return VK_FORMAT_R8_UINT;
- case 2: return VK_FORMAT_R8G8_UINT;
- case 3: return VK_FORMAT_R8G8B8_UINT;
- case 4: return VK_FORMAT_R8G8B8A8_UINT;
- case 6: return VK_FORMAT_R16G16B16_UINT;
- case 8: return VK_FORMAT_R16G16B16A16_UINT;
- case 12: return VK_FORMAT_R32G32B32_UINT;
- case 16: return VK_FORMAT_R32G32B32A32_UINT;
- default:
- unreachable("Invalid format cpp");
- }
-}
-
-static void
-do_buffer_copy(struct anv_cmd_buffer *cmd_buffer,
- struct anv_bo *src, uint64_t src_offset,
- struct anv_bo *dest, uint64_t dest_offset,
- int width, int height, VkFormat copy_format)
-{
- VkDevice vk_device = anv_device_to_handle(cmd_buffer->device);
-
- VkImageCreateInfo image_info = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
- .imageType = VK_IMAGE_TYPE_2D,
- .format = copy_format,
- .extent = {
- .width = width,
- .height = height,
- .depth = 1,
- },
- .mipLevels = 1,
- .arraySize = 1,
- .samples = 1,
- .tiling = VK_IMAGE_TILING_LINEAR,
- .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
- .flags = 0,
- };
-
- VkImage src_image, dest_image;
- anv_CreateImage(vk_device, &image_info, &src_image);
- anv_CreateImage(vk_device, &image_info, &dest_image);
-
- /* We could use a vk call to bind memory, but that would require
- * creating a dummy memory object etc. so there's really no point.
- */
- anv_image_from_handle(src_image)->bo = src;
- anv_image_from_handle(src_image)->offset = src_offset;
- anv_image_from_handle(dest_image)->bo = dest;
- anv_image_from_handle(dest_image)->offset = dest_offset;
-
- struct anv_image_view src_view;
- anv_image_view_init(&src_view, cmd_buffer->device,
- &(VkImageViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = src_image,
- .viewType = VK_IMAGE_VIEW_TYPE_2D,
- .format = copy_format,
- .channels = {
- VK_CHANNEL_SWIZZLE_R,
- VK_CHANNEL_SWIZZLE_G,
- VK_CHANNEL_SWIZZLE_B,
- VK_CHANNEL_SWIZZLE_A
- },
- .subresourceRange = {
- .aspect = VK_IMAGE_ASPECT_COLOR,
- .baseMipLevel = 0,
- .mipLevels = 1,
- .baseArraySlice = 0,
- .arraySize = 1
- },
- },
- cmd_buffer);
-
- struct anv_color_attachment_view dest_view;
- anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
- &(VkAttachmentViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
- .image = dest_image,
- .format = copy_format,
- .mipLevel = 0,
- .baseArraySlice = 0,
- .arraySize = 1,
- },
- cmd_buffer);
-
- meta_emit_blit(cmd_buffer,
- &src_view,
- (VkOffset3D) { 0, 0, 0 },
- (VkExtent3D) { width, height, 1 },
- &dest_view,
- (VkOffset3D) { 0, 0, 0 },
- (VkExtent3D) { width, height, 1 });
-
- anv_DestroyImage(vk_device, src_image);
- anv_DestroyImage(vk_device, dest_image);
-}
-
-void anv_CmdCopyBuffer(
- VkCmdBuffer cmdBuffer,
- VkBuffer srcBuffer,
- VkBuffer destBuffer,
- uint32_t regionCount,
- const VkBufferCopy* pRegions)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_buffer, src_buffer, srcBuffer);
- ANV_FROM_HANDLE(anv_buffer, dest_buffer, destBuffer);
-
- struct anv_saved_state saved_state;
-
- meta_prepare_blit(cmd_buffer, &saved_state);
-
- for (unsigned r = 0; r < regionCount; r++) {
- uint64_t src_offset = src_buffer->offset + pRegions[r].srcOffset;
- uint64_t dest_offset = dest_buffer->offset + pRegions[r].destOffset;
- uint64_t copy_size = pRegions[r].copySize;
-
- /* First, we compute the biggest format that can be used with the
- * given offsets and size.
- */
- int cpp = 16;
-
- int fs = ffs(src_offset) - 1;
- if (fs != -1)
- cpp = MIN2(cpp, 1 << fs);
- assert(src_offset % cpp == 0);
-
- fs = ffs(dest_offset) - 1;
- if (fs != -1)
- cpp = MIN2(cpp, 1 << fs);
- assert(dest_offset % cpp == 0);
-
- fs = ffs(pRegions[r].copySize) - 1;
- if (fs != -1)
- cpp = MIN2(cpp, 1 << fs);
- assert(pRegions[r].copySize % cpp == 0);
-
- VkFormat copy_format = vk_format_for_cpp(cpp);
-
- /* This is maximum possible width/height our HW can handle */
- uint64_t max_surface_dim = 1 << 14;
-
- /* First, we make a bunch of max-sized copies */
- uint64_t max_copy_size = max_surface_dim * max_surface_dim * cpp;
- while (copy_size > max_copy_size) {
- do_buffer_copy(cmd_buffer, src_buffer->bo, src_offset,
- dest_buffer->bo, dest_offset,
- max_surface_dim, max_surface_dim, copy_format);
- copy_size -= max_copy_size;
- src_offset += max_copy_size;
- dest_offset += max_copy_size;
- }
-
- uint64_t height = copy_size / (max_surface_dim * cpp);
- assert(height < max_surface_dim);
- if (height != 0) {
- uint64_t rect_copy_size = height * max_surface_dim * cpp;
- do_buffer_copy(cmd_buffer, src_buffer->bo, src_offset,
- dest_buffer->bo, dest_offset,
- max_surface_dim, height, copy_format);
- copy_size -= rect_copy_size;
- src_offset += rect_copy_size;
- dest_offset += rect_copy_size;
- }
-
- if (copy_size != 0) {
- do_buffer_copy(cmd_buffer, src_buffer->bo, src_offset,
- dest_buffer->bo, dest_offset,
- copy_size / cpp, 1, copy_format);
- }
- }
-
- meta_finish_blit(cmd_buffer, &saved_state);
-}
-
-void anv_CmdCopyImage(
- VkCmdBuffer cmdBuffer,
- VkImage srcImage,
- VkImageLayout srcImageLayout,
- VkImage destImage,
- VkImageLayout destImageLayout,
- uint32_t regionCount,
- const VkImageCopy* pRegions)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_image, src_image, srcImage);
-
- struct anv_saved_state saved_state;
-
- meta_prepare_blit(cmd_buffer, &saved_state);
-
- for (unsigned r = 0; r < regionCount; r++) {
- struct anv_image_view src_view;
- anv_image_view_init(&src_view, cmd_buffer->device,
- &(VkImageViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = srcImage,
- .viewType = VK_IMAGE_VIEW_TYPE_2D,
- .format = src_image->format,
- .channels = {
- VK_CHANNEL_SWIZZLE_R,
- VK_CHANNEL_SWIZZLE_G,
- VK_CHANNEL_SWIZZLE_B,
- VK_CHANNEL_SWIZZLE_A
- },
- .subresourceRange = {
- .aspect = pRegions[r].srcSubresource.aspect,
- .baseMipLevel = pRegions[r].srcSubresource.mipLevel,
- .mipLevels = 1,
- .baseArraySlice = pRegions[r].srcSubresource.arraySlice,
- .arraySize = 1
- },
- },
- cmd_buffer);
-
- struct anv_color_attachment_view dest_view;
- anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
- &(VkAttachmentViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
- .image = destImage,
- .format = src_image->format,
- .mipLevel = pRegions[r].destSubresource.mipLevel,
- .baseArraySlice = pRegions[r].destSubresource.arraySlice,
- .arraySize = 1,
- },
- cmd_buffer);
-
- meta_emit_blit(cmd_buffer,
- &src_view,
- pRegions[r].srcOffset,
- pRegions[r].extent,
- &dest_view,
- pRegions[r].destOffset,
- pRegions[r].extent);
- }
-
- meta_finish_blit(cmd_buffer, &saved_state);
-}
-
-void anv_CmdBlitImage(
- VkCmdBuffer cmdBuffer,
- VkImage srcImage,
- VkImageLayout srcImageLayout,
- VkImage destImage,
- VkImageLayout destImageLayout,
- uint32_t regionCount,
- const VkImageBlit* pRegions,
- VkTexFilter filter)
-
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_image, src_image, srcImage);
- ANV_FROM_HANDLE(anv_image, dest_image, destImage);
-
- struct anv_saved_state saved_state;
-
- anv_finishme("respect VkTexFilter");
-
- meta_prepare_blit(cmd_buffer, &saved_state);
-
- for (unsigned r = 0; r < regionCount; r++) {
- struct anv_image_view src_view;
- anv_image_view_init(&src_view, cmd_buffer->device,
- &(VkImageViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = srcImage,
- .viewType = VK_IMAGE_VIEW_TYPE_2D,
- .format = src_image->format,
- .channels = {
- VK_CHANNEL_SWIZZLE_R,
- VK_CHANNEL_SWIZZLE_G,
- VK_CHANNEL_SWIZZLE_B,
- VK_CHANNEL_SWIZZLE_A
- },
- .subresourceRange = {
- .aspect = pRegions[r].srcSubresource.aspect,
- .baseMipLevel = pRegions[r].srcSubresource.mipLevel,
- .mipLevels = 1,
- .baseArraySlice = pRegions[r].srcSubresource.arraySlice,
- .arraySize = 1
- },
- },
- cmd_buffer);
-
- struct anv_color_attachment_view dest_view;
- anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
- &(VkAttachmentViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
- .image = destImage,
- .format = dest_image->format,
- .mipLevel = pRegions[r].destSubresource.mipLevel,
- .baseArraySlice = pRegions[r].destSubresource.arraySlice,
- .arraySize = 1,
- },
- cmd_buffer);
-
- meta_emit_blit(cmd_buffer,
- &src_view,
- pRegions[r].srcOffset,
- pRegions[r].srcExtent,
- &dest_view,
- pRegions[r].destOffset,
- pRegions[r].destExtent);
- }
-
- meta_finish_blit(cmd_buffer, &saved_state);
-}
-
-void anv_CmdCopyBufferToImage(
- VkCmdBuffer cmdBuffer,
- VkBuffer srcBuffer,
- VkImage destImage,
- VkImageLayout destImageLayout,
- uint32_t regionCount,
- const VkBufferImageCopy* pRegions)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_buffer, src_buffer, srcBuffer);
- ANV_FROM_HANDLE(anv_image, dest_image, destImage);
- VkDevice vk_device = anv_device_to_handle(cmd_buffer->device);
- struct anv_saved_state saved_state;
-
- meta_prepare_blit(cmd_buffer, &saved_state);
-
- for (unsigned r = 0; r < regionCount; r++) {
- if (pRegions[r].bufferRowLength != 0)
- anv_finishme("bufferRowLength not supported in CopyBufferToImage");
- if (pRegions[r].bufferImageHeight != 0)
- anv_finishme("bufferImageHeight not supported in CopyBufferToImage");
-
- VkImage srcImage;
- anv_CreateImage(vk_device,
- &(VkImageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
- .imageType = VK_IMAGE_TYPE_2D,
- .format = dest_image->format,
- .extent = {
- .width = pRegions[r].imageExtent.width,
- .height = pRegions[r].imageExtent.height,
- .depth = 1,
- },
- .mipLevels = 1,
- .arraySize = 1,
- .samples = 1,
- .tiling = VK_IMAGE_TILING_LINEAR,
- .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
- .flags = 0,
- }, &srcImage);
-
- ANV_FROM_HANDLE(anv_image, src_image, srcImage);
-
- /* We could use a vk call to bind memory, but that would require
- * creating a dummy memory object etc. so there's really no point.
- */
- src_image->bo = src_buffer->bo;
- src_image->offset = src_buffer->offset + pRegions[r].bufferOffset;
-
- struct anv_image_view src_view;
- anv_image_view_init(&src_view, cmd_buffer->device,
- &(VkImageViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = anv_image_to_handle(src_image),
- .viewType = VK_IMAGE_VIEW_TYPE_2D,
- .format = dest_image->format,
- .channels = {
- VK_CHANNEL_SWIZZLE_R,
- VK_CHANNEL_SWIZZLE_G,
- VK_CHANNEL_SWIZZLE_B,
- VK_CHANNEL_SWIZZLE_A
- },
- .subresourceRange = {
- .aspect = pRegions[r].imageSubresource.aspect,
- .baseMipLevel = 0,
- .mipLevels = 1,
- .baseArraySlice = 0,
- .arraySize = 1
- },
- },
- cmd_buffer);
-
- struct anv_color_attachment_view dest_view;
- anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
- &(VkAttachmentViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
- .image = anv_image_to_handle(dest_image),
- .format = dest_image->format,
- .mipLevel = pRegions[r].imageSubresource.mipLevel,
- .baseArraySlice = pRegions[r].imageSubresource.arraySlice,
- .arraySize = 1,
- },
- cmd_buffer);
-
- meta_emit_blit(cmd_buffer,
- &src_view,
- (VkOffset3D) { 0, 0, 0 },
- pRegions[r].imageExtent,
- &dest_view,
- pRegions[r].imageOffset,
- pRegions[r].imageExtent);
-
- anv_DestroyImage(vk_device, srcImage);
- }
-
- meta_finish_blit(cmd_buffer, &saved_state);
-}
-
-void anv_CmdCopyImageToBuffer(
- VkCmdBuffer cmdBuffer,
- VkImage srcImage,
- VkImageLayout srcImageLayout,
- VkBuffer destBuffer,
- uint32_t regionCount,
- const VkBufferImageCopy* pRegions)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_image, src_image, srcImage);
- ANV_FROM_HANDLE(anv_buffer, dest_buffer, destBuffer);
- VkDevice vk_device = anv_device_to_handle(cmd_buffer->device);
- struct anv_saved_state saved_state;
-
- meta_prepare_blit(cmd_buffer, &saved_state);
-
- for (unsigned r = 0; r < regionCount; r++) {
- if (pRegions[r].bufferRowLength != 0)
- anv_finishme("bufferRowLength not supported in CopyBufferToImage");
- if (pRegions[r].bufferImageHeight != 0)
- anv_finishme("bufferImageHeight not supported in CopyBufferToImage");
-
- struct anv_image_view src_view;
- anv_image_view_init(&src_view, cmd_buffer->device,
- &(VkImageViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = srcImage,
- .viewType = VK_IMAGE_VIEW_TYPE_2D,
- .format = src_image->format,
- .channels = {
- VK_CHANNEL_SWIZZLE_R,
- VK_CHANNEL_SWIZZLE_G,
- VK_CHANNEL_SWIZZLE_B,
- VK_CHANNEL_SWIZZLE_A
- },
- .subresourceRange = {
- .aspect = pRegions[r].imageSubresource.aspect,
- .baseMipLevel = pRegions[r].imageSubresource.mipLevel,
- .mipLevels = 1,
- .baseArraySlice = pRegions[r].imageSubresource.arraySlice,
- .arraySize = 1
- },
- },
- cmd_buffer);
-
- VkImage destImage;
- anv_CreateImage(vk_device,
- &(VkImageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
- .imageType = VK_IMAGE_TYPE_2D,
- .format = src_image->format,
- .extent = {
- .width = pRegions[r].imageExtent.width,
- .height = pRegions[r].imageExtent.height,
- .depth = 1,
- },
- .mipLevels = 1,
- .arraySize = 1,
- .samples = 1,
- .tiling = VK_IMAGE_TILING_LINEAR,
- .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
- .flags = 0,
- }, &destImage);
-
- ANV_FROM_HANDLE(anv_image, dest_image, destImage);
-
- /* We could use a vk call to bind memory, but that would require
- * creating a dummy memory object etc. so there's really no point.
- */
- dest_image->bo = dest_buffer->bo;
- dest_image->offset = dest_buffer->offset + pRegions[r].bufferOffset;
-
- struct anv_color_attachment_view dest_view;
- anv_color_attachment_view_init(&dest_view, cmd_buffer->device,
- &(VkAttachmentViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
- .image = destImage,
- .format = src_image->format,
- .mipLevel = 0,
- .baseArraySlice = 0,
- .arraySize = 1,
- },
- cmd_buffer);
-
- meta_emit_blit(cmd_buffer,
- &src_view,
- pRegions[r].imageOffset,
- pRegions[r].imageExtent,
- &dest_view,
- (VkOffset3D) { 0, 0, 0 },
- pRegions[r].imageExtent);
-
- anv_DestroyImage(vk_device, destImage);
- }
-
- meta_finish_blit(cmd_buffer, &saved_state);
-}
-
-void anv_CmdUpdateBuffer(
- VkCmdBuffer cmdBuffer,
- VkBuffer destBuffer,
- VkDeviceSize destOffset,
- VkDeviceSize dataSize,
- const uint32_t* pData)
-{
- stub();
-}
-
-void anv_CmdFillBuffer(
- VkCmdBuffer cmdBuffer,
- VkBuffer destBuffer,
- VkDeviceSize destOffset,
- VkDeviceSize fillSize,
- uint32_t data)
-{
- stub();
-}
-
-void anv_CmdClearColorImage(
- VkCmdBuffer cmdBuffer,
- VkImage _image,
- VkImageLayout imageLayout,
- const VkClearColorValue* pColor,
- uint32_t rangeCount,
- const VkImageSubresourceRange* pRanges)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_image, image, _image);
- struct anv_saved_state saved_state;
-
- anv_cmd_buffer_save(cmd_buffer, &saved_state);
-
- for (uint32_t r = 0; r < rangeCount; r++) {
- for (uint32_t l = 0; l < pRanges[r].mipLevels; l++) {
- for (uint32_t s = 0; s < pRanges[r].arraySize; s++) {
- struct anv_color_attachment_view view;
- anv_color_attachment_view_init(&view, cmd_buffer->device,
- &(VkAttachmentViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
- .image = _image,
- .format = image->format,
- .mipLevel = pRanges[r].baseMipLevel + l,
- .baseArraySlice = pRanges[r].baseArraySlice + s,
- .arraySize = 1,
- },
- cmd_buffer);
-
- VkFramebuffer fb;
- anv_CreateFramebuffer(anv_device_to_handle(cmd_buffer->device),
- &(VkFramebufferCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
- .attachmentCount = 1,
- .pAttachments = (VkAttachmentBindInfo[]) {
- {
- .view = anv_attachment_view_to_handle(&view.base),
- .layout = VK_IMAGE_LAYOUT_GENERAL
- }
- },
- .width = view.base.extent.width,
- .height = view.base.extent.height,
- .layers = 1
- }, &fb);
-
- VkRenderPass pass;
- anv_CreateRenderPass(anv_device_to_handle(cmd_buffer->device),
- &(VkRenderPassCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
- .attachmentCount = 1,
- .pAttachments = &(VkAttachmentDescription) {
- .sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION,
- .format = view.view.format,
- .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
- .initialLayout = VK_IMAGE_LAYOUT_GENERAL,
- .finalLayout = VK_IMAGE_LAYOUT_GENERAL,
- },
- .subpassCount = 1,
- .pSubpasses = &(VkSubpassDescription) {
- .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION,
- .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
- .inputCount = 0,
- .colorCount = 1,
- .colorAttachments = &(VkAttachmentReference) {
- .attachment = 0,
- .layout = VK_IMAGE_LAYOUT_GENERAL,
- },
- .resolveAttachments = NULL,
- .depthStencilAttachment = (VkAttachmentReference) {
- .attachment = VK_ATTACHMENT_UNUSED,
- .layout = VK_IMAGE_LAYOUT_GENERAL,
- },
- .preserveCount = 1,
- .preserveAttachments = &(VkAttachmentReference) {
- .attachment = 0,
- .layout = VK_IMAGE_LAYOUT_GENERAL,
- },
- },
- .dependencyCount = 0,
- }, &pass);
-
- anv_CmdBeginRenderPass(anv_cmd_buffer_to_handle(cmd_buffer),
- &(VkRenderPassBeginInfo) {
- .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
- .renderArea = {
- .offset = { 0, 0, },
- .extent = {
- .width = view.base.extent.width,
- .height = view.base.extent.height,
- },
- },
- .renderPass = pass,
- .framebuffer = fb,
- .attachmentCount = 1,
- .pAttachmentClearValues = NULL,
- }, VK_RENDER_PASS_CONTENTS_INLINE);
-
- struct clear_instance_data instance_data = {
- .vue_header = {
- .RTAIndex = 0,
- .ViewportIndex = 0,
- .PointWidth = 0.0
- },
- .color = *pColor,
- };
-
- meta_emit_clear(cmd_buffer, 1, &instance_data);
-
- anv_CmdEndRenderPass(anv_cmd_buffer_to_handle(cmd_buffer));
- }
- }
- }
-
- /* Restore API state */
- anv_cmd_buffer_restore(cmd_buffer, &saved_state);
-}
-
-void anv_CmdClearDepthStencilImage(
- VkCmdBuffer cmdBuffer,
- VkImage image,
- VkImageLayout imageLayout,
- float depth,
- uint32_t stencil,
- uint32_t rangeCount,
- const VkImageSubresourceRange* pRanges)
-{
- stub();
-}
-
-void anv_CmdClearColorAttachment(
- VkCmdBuffer cmdBuffer,
- uint32_t colorAttachment,
- VkImageLayout imageLayout,
- const VkClearColorValue* pColor,
- uint32_t rectCount,
- const VkRect3D* pRects)
-{
- stub();
-}
-
-void anv_CmdClearDepthStencilAttachment(
- VkCmdBuffer cmdBuffer,
- VkImageAspectFlags imageAspectMask,
- VkImageLayout imageLayout,
- float depth,
- uint32_t stencil,
- uint32_t rectCount,
- const VkRect3D* pRects)
-{
- stub();
-}
-
-void anv_CmdResolveImage(
- VkCmdBuffer cmdBuffer,
- VkImage srcImage,
- VkImageLayout srcImageLayout,
- VkImage destImage,
- VkImageLayout destImageLayout,
- uint32_t regionCount,
- const VkImageResolve* pRegions)
-{
- stub();
-}
-
-void
-anv_device_init_meta(struct anv_device *device)
-{
- anv_device_init_meta_clear_state(device);
- anv_device_init_meta_blit_state(device);
-
- anv_CreateDynamicRasterState(anv_device_to_handle(device),
- &(VkDynamicRasterStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_DYNAMIC_RASTER_STATE_CREATE_INFO,
- },
- &device->meta_state.shared.rs_state);
-
- anv_CreateDynamicColorBlendState(anv_device_to_handle(device),
- &(VkDynamicColorBlendStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_DYNAMIC_COLOR_BLEND_STATE_CREATE_INFO
- },
- &device->meta_state.shared.cb_state);
-
- anv_CreateDynamicDepthStencilState(anv_device_to_handle(device),
- &(VkDynamicDepthStencilStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_DYNAMIC_DEPTH_STENCIL_STATE_CREATE_INFO
- },
- &device->meta_state.shared.ds_state);
-}
-
-void
-anv_device_finish_meta(struct anv_device *device)
-{
- /* Clear */
- anv_DestroyPipeline(anv_device_to_handle(device),
- device->meta_state.clear.pipeline);
-
- /* Blit */
- anv_DestroyPipeline(anv_device_to_handle(device),
- device->meta_state.blit.pipeline);
- anv_DestroyPipelineLayout(anv_device_to_handle(device),
- device->meta_state.blit.pipeline_layout);
- anv_DestroyDescriptorSetLayout(anv_device_to_handle(device),
- device->meta_state.blit.ds_layout);
-
- /* Shared */
- anv_DestroyDynamicRasterState(anv_device_to_handle(device),
- device->meta_state.shared.rs_state);
- anv_DestroyDynamicColorBlendState(anv_device_to_handle(device),
- device->meta_state.shared.cb_state);
- anv_DestroyDynamicDepthStencilState(anv_device_to_handle(device),
- device->meta_state.shared.ds_state);
-}
+++ /dev/null
-/*
- * 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 <assert.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "private.h"
-
-// Shader functions
-
-VkResult anv_CreateShaderModule(
- VkDevice _device,
- const VkShaderModuleCreateInfo* pCreateInfo,
- VkShaderModule* pShaderModule)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_shader_module *module;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
- assert(pCreateInfo->flags == 0);
-
- module = anv_device_alloc(device, sizeof(*module) + pCreateInfo->codeSize, 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (module == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- module->size = pCreateInfo->codeSize;
- memcpy(module->data, pCreateInfo->pCode, module->size);
-
- *pShaderModule = anv_shader_module_to_handle(module);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyShaderModule(
- VkDevice _device,
- VkShaderModule _module)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_shader_module, module, _module);
-
- anv_device_free(device, module);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_CreateShader(
- VkDevice _device,
- const VkShaderCreateInfo* pCreateInfo,
- VkShader* pShader)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_shader_module, module, pCreateInfo->module);
- struct anv_shader *shader;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_CREATE_INFO);
- assert(pCreateInfo->flags == 0);
-
- size_t name_len = strlen(pCreateInfo->pName);
-
- if (strcmp(pCreateInfo->pName, "main") != 0) {
- anv_finishme("Multiple shaders per module not really supported");
- }
-
- shader = anv_device_alloc(device, sizeof(*shader) + name_len + 1, 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (shader == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- shader->module = module;
- memcpy(shader->entrypoint, pCreateInfo->pName, name_len + 1);
-
- *pShader = anv_shader_to_handle(shader);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyShader(
- VkDevice _device,
- VkShader _shader)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_shader, shader, _shader);
-
- anv_device_free(device, shader);
-
- return VK_SUCCESS;
-}
-
-
-VkResult anv_CreatePipelineCache(
- VkDevice device,
- const VkPipelineCacheCreateInfo* pCreateInfo,
- VkPipelineCache* pPipelineCache)
-{
- pPipelineCache->handle = 1;
-
- stub_return(VK_SUCCESS);
-}
-
-VkResult anv_DestroyPipelineCache(
- VkDevice _device,
- VkPipelineCache _cache)
-{
- /* VkPipelineCache is a dummy object. */
- return VK_SUCCESS;
-}
-
-size_t anv_GetPipelineCacheSize(
- VkDevice device,
- VkPipelineCache pipelineCache)
-{
- stub_return(0);
-}
-
-VkResult anv_GetPipelineCacheData(
- VkDevice device,
- VkPipelineCache pipelineCache,
- void* pData)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-VkResult anv_MergePipelineCaches(
- VkDevice device,
- VkPipelineCache destCache,
- uint32_t srcCacheCount,
- const VkPipelineCache* pSrcCaches)
-{
- stub_return(VK_UNSUPPORTED);
-}
-
-// Pipeline functions
-
-static void
-emit_vertex_input(struct anv_pipeline *pipeline,
- const VkPipelineVertexInputStateCreateInfo *info)
-{
- const uint32_t num_dwords = 1 + info->attributeCount * 2;
- uint32_t *p;
- bool instancing_enable[32];
-
- pipeline->vb_used = 0;
- for (uint32_t i = 0; i < info->bindingCount; i++) {
- const VkVertexInputBindingDescription *desc =
- &info->pVertexBindingDescriptions[i];
-
- pipeline->vb_used |= 1 << desc->binding;
- pipeline->binding_stride[desc->binding] = desc->strideInBytes;
-
- /* Step rate is programmed per vertex element (attribute), not
- * binding. Set up a map of which bindings step per instance, for
- * reference by vertex element setup. */
- switch (desc->stepRate) {
- default:
- case VK_VERTEX_INPUT_STEP_RATE_VERTEX:
- instancing_enable[desc->binding] = false;
- break;
- case VK_VERTEX_INPUT_STEP_RATE_INSTANCE:
- instancing_enable[desc->binding] = true;
- break;
- }
- }
-
- p = anv_batch_emitn(&pipeline->batch, num_dwords,
- GEN8_3DSTATE_VERTEX_ELEMENTS);
-
- for (uint32_t i = 0; i < info->attributeCount; i++) {
- const VkVertexInputAttributeDescription *desc =
- &info->pVertexAttributeDescriptions[i];
- const struct anv_format *format = anv_format_for_vk_format(desc->format);
-
- struct GEN8_VERTEX_ELEMENT_STATE element = {
- .VertexBufferIndex = desc->binding,
- .Valid = true,
- .SourceElementFormat = format->surface_format,
- .EdgeFlagEnable = false,
- .SourceElementOffset = desc->offsetInBytes,
- .Component0Control = VFCOMP_STORE_SRC,
- .Component1Control = format->num_channels >= 2 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
- .Component2Control = format->num_channels >= 3 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
- .Component3Control = format->num_channels >= 4 ? VFCOMP_STORE_SRC : VFCOMP_STORE_1_FP
- };
- GEN8_VERTEX_ELEMENT_STATE_pack(NULL, &p[1 + i * 2], &element);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_INSTANCING,
- .InstancingEnable = instancing_enable[desc->binding],
- .VertexElementIndex = i,
- /* Vulkan so far doesn't have an instance divisor, so
- * this is always 1 (ignored if not instancing). */
- .InstanceDataStepRate = 1);
- }
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_SGVS,
- .VertexIDEnable = pipeline->vs_prog_data.uses_vertexid,
- .VertexIDComponentNumber = 2,
- .VertexIDElementOffset = info->bindingCount,
- .InstanceIDEnable = pipeline->vs_prog_data.uses_instanceid,
- .InstanceIDComponentNumber = 3,
- .InstanceIDElementOffset = info->bindingCount);
-}
-
-static void
-emit_ia_state(struct anv_pipeline *pipeline,
- const VkPipelineInputAssemblyStateCreateInfo *info,
- const struct anv_pipeline_create_info *extra)
-{
- static const uint32_t vk_to_gen_primitive_type[] = {
- [VK_PRIMITIVE_TOPOLOGY_POINT_LIST] = _3DPRIM_POINTLIST,
- [VK_PRIMITIVE_TOPOLOGY_LINE_LIST] = _3DPRIM_LINELIST,
- [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP] = _3DPRIM_LINESTRIP,
- [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST] = _3DPRIM_TRILIST,
- [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP] = _3DPRIM_TRISTRIP,
- [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN] = _3DPRIM_TRIFAN,
- [VK_PRIMITIVE_TOPOLOGY_LINE_LIST_ADJ] = _3DPRIM_LINELIST_ADJ,
- [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_ADJ] = _3DPRIM_LINESTRIP_ADJ,
- [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_ADJ] = _3DPRIM_TRILIST_ADJ,
- [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_ADJ] = _3DPRIM_TRISTRIP_ADJ,
- [VK_PRIMITIVE_TOPOLOGY_PATCH] = _3DPRIM_PATCHLIST_1
- };
- uint32_t topology = vk_to_gen_primitive_type[info->topology];
-
- if (extra && extra->use_rectlist)
- topology = _3DPRIM_RECTLIST;
-
- struct GEN8_3DSTATE_VF vf = {
- GEN8_3DSTATE_VF_header,
- .IndexedDrawCutIndexEnable = info->primitiveRestartEnable,
- };
- GEN8_3DSTATE_VF_pack(NULL, pipeline->state_vf, &vf);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_TOPOLOGY,
- .PrimitiveTopologyType = topology);
-}
-
-static void
-emit_rs_state(struct anv_pipeline *pipeline,
- const VkPipelineRasterStateCreateInfo *info,
- const struct anv_pipeline_create_info *extra)
-{
- static const uint32_t vk_to_gen_cullmode[] = {
- [VK_CULL_MODE_NONE] = CULLMODE_NONE,
- [VK_CULL_MODE_FRONT] = CULLMODE_FRONT,
- [VK_CULL_MODE_BACK] = CULLMODE_BACK,
- [VK_CULL_MODE_FRONT_AND_BACK] = CULLMODE_BOTH
- };
-
- static const uint32_t vk_to_gen_fillmode[] = {
- [VK_FILL_MODE_POINTS] = RASTER_POINT,
- [VK_FILL_MODE_WIREFRAME] = RASTER_WIREFRAME,
- [VK_FILL_MODE_SOLID] = RASTER_SOLID
- };
-
- static const uint32_t vk_to_gen_front_face[] = {
- [VK_FRONT_FACE_CCW] = CounterClockwise,
- [VK_FRONT_FACE_CW] = Clockwise
- };
-
- struct GEN8_3DSTATE_SF sf = {
- GEN8_3DSTATE_SF_header,
- .ViewportTransformEnable = !(extra && extra->disable_viewport),
- .TriangleStripListProvokingVertexSelect = 0,
- .LineStripListProvokingVertexSelect = 0,
- .TriangleFanProvokingVertexSelect = 0,
- .PointWidthSource = pipeline->writes_point_size ? Vertex : State,
- .PointWidth = 1.0,
- };
-
- /* FINISHME: VkBool32 rasterizerDiscardEnable; */
-
- GEN8_3DSTATE_SF_pack(NULL, pipeline->state_sf, &sf);
-
- struct GEN8_3DSTATE_RASTER raster = {
- GEN8_3DSTATE_RASTER_header,
- .FrontWinding = vk_to_gen_front_face[info->frontFace],
- .CullMode = vk_to_gen_cullmode[info->cullMode],
- .FrontFaceFillMode = vk_to_gen_fillmode[info->fillMode],
- .BackFaceFillMode = vk_to_gen_fillmode[info->fillMode],
- .ScissorRectangleEnable = !(extra && extra->disable_scissor),
- .ViewportZClipTestEnable = info->depthClipEnable
- };
-
- GEN8_3DSTATE_RASTER_pack(NULL, pipeline->state_raster, &raster);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE,
- .ForceVertexURBEntryReadLength = false,
- .ForceVertexURBEntryReadOffset = false,
- .PointSpriteTextureCoordinateOrigin = UPPERLEFT,
- .NumberofSFOutputAttributes =
- pipeline->wm_prog_data.num_varying_inputs);
-
-}
-
-static void
-emit_cb_state(struct anv_pipeline *pipeline,
- const VkPipelineColorBlendStateCreateInfo *info)
-{
- struct anv_device *device = pipeline->device;
-
- static const uint32_t vk_to_gen_logic_op[] = {
- [VK_LOGIC_OP_COPY] = LOGICOP_COPY,
- [VK_LOGIC_OP_CLEAR] = LOGICOP_CLEAR,
- [VK_LOGIC_OP_AND] = LOGICOP_AND,
- [VK_LOGIC_OP_AND_REVERSE] = LOGICOP_AND_REVERSE,
- [VK_LOGIC_OP_AND_INVERTED] = LOGICOP_AND_INVERTED,
- [VK_LOGIC_OP_NOOP] = LOGICOP_NOOP,
- [VK_LOGIC_OP_XOR] = LOGICOP_XOR,
- [VK_LOGIC_OP_OR] = LOGICOP_OR,
- [VK_LOGIC_OP_NOR] = LOGICOP_NOR,
- [VK_LOGIC_OP_EQUIV] = LOGICOP_EQUIV,
- [VK_LOGIC_OP_INVERT] = LOGICOP_INVERT,
- [VK_LOGIC_OP_OR_REVERSE] = LOGICOP_OR_REVERSE,
- [VK_LOGIC_OP_COPY_INVERTED] = LOGICOP_COPY_INVERTED,
- [VK_LOGIC_OP_OR_INVERTED] = LOGICOP_OR_INVERTED,
- [VK_LOGIC_OP_NAND] = LOGICOP_NAND,
- [VK_LOGIC_OP_SET] = LOGICOP_SET,
- };
-
- static const uint32_t vk_to_gen_blend[] = {
- [VK_BLEND_ZERO] = BLENDFACTOR_ZERO,
- [VK_BLEND_ONE] = BLENDFACTOR_ONE,
- [VK_BLEND_SRC_COLOR] = BLENDFACTOR_SRC_COLOR,
- [VK_BLEND_ONE_MINUS_SRC_COLOR] = BLENDFACTOR_INV_SRC_COLOR,
- [VK_BLEND_DEST_COLOR] = BLENDFACTOR_DST_COLOR,
- [VK_BLEND_ONE_MINUS_DEST_COLOR] = BLENDFACTOR_INV_DST_COLOR,
- [VK_BLEND_SRC_ALPHA] = BLENDFACTOR_SRC_ALPHA,
- [VK_BLEND_ONE_MINUS_SRC_ALPHA] = BLENDFACTOR_INV_SRC_ALPHA,
- [VK_BLEND_DEST_ALPHA] = BLENDFACTOR_DST_ALPHA,
- [VK_BLEND_ONE_MINUS_DEST_ALPHA] = BLENDFACTOR_INV_DST_ALPHA,
- [VK_BLEND_CONSTANT_COLOR] = BLENDFACTOR_CONST_COLOR,
- [VK_BLEND_ONE_MINUS_CONSTANT_COLOR] = BLENDFACTOR_INV_CONST_COLOR,
- [VK_BLEND_CONSTANT_ALPHA] = BLENDFACTOR_CONST_ALPHA,
- [VK_BLEND_ONE_MINUS_CONSTANT_ALPHA] = BLENDFACTOR_INV_CONST_ALPHA,
- [VK_BLEND_SRC_ALPHA_SATURATE] = BLENDFACTOR_SRC_ALPHA_SATURATE,
- [VK_BLEND_SRC1_COLOR] = BLENDFACTOR_SRC1_COLOR,
- [VK_BLEND_ONE_MINUS_SRC1_COLOR] = BLENDFACTOR_INV_SRC1_COLOR,
- [VK_BLEND_SRC1_ALPHA] = BLENDFACTOR_SRC1_ALPHA,
- [VK_BLEND_ONE_MINUS_SRC1_ALPHA] = BLENDFACTOR_INV_SRC1_ALPHA,
- };
-
- static const uint32_t vk_to_gen_blend_op[] = {
- [VK_BLEND_OP_ADD] = BLENDFUNCTION_ADD,
- [VK_BLEND_OP_SUBTRACT] = BLENDFUNCTION_SUBTRACT,
- [VK_BLEND_OP_REVERSE_SUBTRACT] = BLENDFUNCTION_REVERSE_SUBTRACT,
- [VK_BLEND_OP_MIN] = BLENDFUNCTION_MIN,
- [VK_BLEND_OP_MAX] = BLENDFUNCTION_MAX,
- };
-
- uint32_t num_dwords = 1 + info->attachmentCount * 2;
- pipeline->blend_state =
- anv_state_pool_alloc(&device->dynamic_state_pool, num_dwords * 4, 64);
-
- struct GEN8_BLEND_STATE blend_state = {
- .AlphaToCoverageEnable = info->alphaToCoverageEnable,
- };
-
- uint32_t *state = pipeline->blend_state.map;
- GEN8_BLEND_STATE_pack(NULL, state, &blend_state);
-
- for (uint32_t i = 0; i < info->attachmentCount; i++) {
- const VkPipelineColorBlendAttachmentState *a = &info->pAttachments[i];
-
- struct GEN8_BLEND_STATE_ENTRY entry = {
- .LogicOpEnable = info->logicOpEnable,
- .LogicOpFunction = vk_to_gen_logic_op[info->logicOp],
- .ColorBufferBlendEnable = a->blendEnable,
- .PreBlendSourceOnlyClampEnable = false,
- .PreBlendColorClampEnable = false,
- .PostBlendColorClampEnable = false,
- .SourceBlendFactor = vk_to_gen_blend[a->srcBlendColor],
- .DestinationBlendFactor = vk_to_gen_blend[a->destBlendColor],
- .ColorBlendFunction = vk_to_gen_blend_op[a->blendOpColor],
- .SourceAlphaBlendFactor = vk_to_gen_blend[a->srcBlendAlpha],
- .DestinationAlphaBlendFactor = vk_to_gen_blend[a->destBlendAlpha],
- .AlphaBlendFunction = vk_to_gen_blend_op[a->blendOpAlpha],
- .WriteDisableAlpha = !(a->channelWriteMask & VK_CHANNEL_A_BIT),
- .WriteDisableRed = !(a->channelWriteMask & VK_CHANNEL_R_BIT),
- .WriteDisableGreen = !(a->channelWriteMask & VK_CHANNEL_G_BIT),
- .WriteDisableBlue = !(a->channelWriteMask & VK_CHANNEL_B_BIT),
- };
-
- GEN8_BLEND_STATE_ENTRY_pack(NULL, state + i * 2 + 1, &entry);
- }
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_BLEND_STATE_POINTERS,
- .BlendStatePointer = pipeline->blend_state.offset,
- .BlendStatePointerValid = true);
-}
-
-static const uint32_t vk_to_gen_compare_op[] = {
- [VK_COMPARE_OP_NEVER] = COMPAREFUNCTION_NEVER,
- [VK_COMPARE_OP_LESS] = COMPAREFUNCTION_LESS,
- [VK_COMPARE_OP_EQUAL] = COMPAREFUNCTION_EQUAL,
- [VK_COMPARE_OP_LESS_EQUAL] = COMPAREFUNCTION_LEQUAL,
- [VK_COMPARE_OP_GREATER] = COMPAREFUNCTION_GREATER,
- [VK_COMPARE_OP_NOT_EQUAL] = COMPAREFUNCTION_NOTEQUAL,
- [VK_COMPARE_OP_GREATER_EQUAL] = COMPAREFUNCTION_GEQUAL,
- [VK_COMPARE_OP_ALWAYS] = COMPAREFUNCTION_ALWAYS,
-};
-
-static const uint32_t vk_to_gen_stencil_op[] = {
- [VK_STENCIL_OP_KEEP] = 0,
- [VK_STENCIL_OP_ZERO] = 0,
- [VK_STENCIL_OP_REPLACE] = 0,
- [VK_STENCIL_OP_INC_CLAMP] = 0,
- [VK_STENCIL_OP_DEC_CLAMP] = 0,
- [VK_STENCIL_OP_INVERT] = 0,
- [VK_STENCIL_OP_INC_WRAP] = 0,
- [VK_STENCIL_OP_DEC_WRAP] = 0
-};
-
-static void
-emit_ds_state(struct anv_pipeline *pipeline,
- const VkPipelineDepthStencilStateCreateInfo *info)
-{
- if (info == NULL) {
- /* We're going to OR this together with the dynamic state. We need
- * to make sure it's initialized to something useful.
- */
- memset(pipeline->state_wm_depth_stencil, 0,
- sizeof(pipeline->state_wm_depth_stencil));
- return;
- }
-
- /* VkBool32 depthBoundsEnable; // optional (depth_bounds_test) */
-
- struct GEN8_3DSTATE_WM_DEPTH_STENCIL wm_depth_stencil = {
- .DepthTestEnable = info->depthTestEnable,
- .DepthBufferWriteEnable = info->depthWriteEnable,
- .DepthTestFunction = vk_to_gen_compare_op[info->depthCompareOp],
- .DoubleSidedStencilEnable = true,
-
- .StencilTestEnable = info->stencilTestEnable,
- .StencilFailOp = vk_to_gen_stencil_op[info->front.stencilFailOp],
- .StencilPassDepthPassOp = vk_to_gen_stencil_op[info->front.stencilPassOp],
- .StencilPassDepthFailOp = vk_to_gen_stencil_op[info->front.stencilDepthFailOp],
- .StencilTestFunction = vk_to_gen_compare_op[info->front.stencilCompareOp],
- .BackfaceStencilFailOp = vk_to_gen_stencil_op[info->back.stencilFailOp],
- .BackfaceStencilPassDepthPassOp = vk_to_gen_stencil_op[info->back.stencilPassOp],
- .BackfaceStencilPassDepthFailOp =vk_to_gen_stencil_op[info->back.stencilDepthFailOp],
- .BackfaceStencilTestFunction = vk_to_gen_compare_op[info->back.stencilCompareOp],
- };
-
- GEN8_3DSTATE_WM_DEPTH_STENCIL_pack(NULL, pipeline->state_wm_depth_stencil, &wm_depth_stencil);
-}
-
-VkResult
-anv_pipeline_create(
- VkDevice _device,
- const VkGraphicsPipelineCreateInfo* pCreateInfo,
- const struct anv_pipeline_create_info * extra,
- VkPipeline* pPipeline)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_pipeline *pipeline;
- VkResult result;
- uint32_t offset, length;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
-
- pipeline = anv_device_alloc(device, sizeof(*pipeline), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (pipeline == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- pipeline->device = device;
- pipeline->layout = anv_pipeline_layout_from_handle(pCreateInfo->layout);
- memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
-
- result = anv_reloc_list_init(&pipeline->batch.relocs, device);
- if (result != VK_SUCCESS) {
- anv_device_free(device, pipeline);
- return result;
- }
- pipeline->batch.next = pipeline->batch.start = pipeline->batch_data;
- pipeline->batch.end = pipeline->batch.start + sizeof(pipeline->batch_data);
-
- anv_state_stream_init(&pipeline->program_stream,
- &device->instruction_block_pool);
-
- for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
- pipeline->shaders[pCreateInfo->pStages[i].stage] =
- anv_shader_from_handle(pCreateInfo->pStages[i].shader);
- }
-
- if (pCreateInfo->pTessellationState)
- anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO");
- if (pCreateInfo->pViewportState)
- anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO");
- if (pCreateInfo->pMultisampleState)
- anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO");
-
- pipeline->use_repclear = extra && extra->use_repclear;
-
- anv_compiler_run(device->compiler, pipeline);
-
- /* FIXME: The compiler dead-codes FS inputs when we don't have a VS, so we
- * hard code this to num_attributes - 2. This is because the attributes
- * include VUE header and position, which aren't counted as varying
- * inputs. */
- if (pipeline->vs_simd8 == NO_KERNEL) {
- pipeline->wm_prog_data.num_varying_inputs =
- pCreateInfo->pVertexInputState->attributeCount - 2;
- }
-
- assert(pCreateInfo->pVertexInputState);
- emit_vertex_input(pipeline, pCreateInfo->pVertexInputState);
- assert(pCreateInfo->pInputAssemblyState);
- emit_ia_state(pipeline, pCreateInfo->pInputAssemblyState, extra);
- assert(pCreateInfo->pRasterState);
- emit_rs_state(pipeline, pCreateInfo->pRasterState, extra);
- emit_ds_state(pipeline, pCreateInfo->pDepthStencilState);
- emit_cb_state(pipeline, pCreateInfo->pColorBlendState);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_STATISTICS,
- .StatisticsEnable = true);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_HS, .Enable = false);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_TE, .TEEnable = false);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_DS, .FunctionEnable = false);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_STREAMOUT, .SOFunctionEnable = false);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_VS,
- .ConstantBufferOffset = 0,
- .ConstantBufferSize = 4);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_GS,
- .ConstantBufferOffset = 4,
- .ConstantBufferSize = 4);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_PS,
- .ConstantBufferOffset = 8,
- .ConstantBufferSize = 4);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_WM_CHROMAKEY,
- .ChromaKeyKillEnable = false);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE_SWIZ);
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_AA_LINE_PARAMETERS);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_CLIP,
- .ClipEnable = true,
- .ViewportXYClipTestEnable = !(extra && extra->disable_viewport),
- .MinimumPointWidth = 0.125,
- .MaximumPointWidth = 255.875);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_WM,
- .StatisticsEnable = true,
- .LineEndCapAntialiasingRegionWidth = _05pixels,
- .LineAntialiasingRegionWidth = _10pixels,
- .EarlyDepthStencilControl = NORMAL,
- .ForceThreadDispatchEnable = NORMAL,
- .PointRasterizationRule = RASTRULE_UPPER_RIGHT,
- .BarycentricInterpolationMode =
- pipeline->wm_prog_data.barycentric_interp_modes);
-
- uint32_t samples = 1;
- uint32_t log2_samples = __builtin_ffs(samples) - 1;
- bool enable_sampling = samples > 1 ? true : false;
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_MULTISAMPLE,
- .PixelPositionOffsetEnable = enable_sampling,
- .PixelLocation = CENTER,
- .NumberofMultisamples = log2_samples);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SAMPLE_MASK,
- .SampleMask = 0xffff);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_VS,
- .VSURBStartingAddress = pipeline->urb.vs_start,
- .VSURBEntryAllocationSize = pipeline->urb.vs_size - 1,
- .VSNumberofURBEntries = pipeline->urb.nr_vs_entries);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_GS,
- .GSURBStartingAddress = pipeline->urb.gs_start,
- .GSURBEntryAllocationSize = pipeline->urb.gs_size - 1,
- .GSNumberofURBEntries = pipeline->urb.nr_gs_entries);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_HS,
- .HSURBStartingAddress = pipeline->urb.vs_start,
- .HSURBEntryAllocationSize = 0,
- .HSNumberofURBEntries = 0);
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_DS,
- .DSURBStartingAddress = pipeline->urb.vs_start,
- .DSURBEntryAllocationSize = 0,
- .DSNumberofURBEntries = 0);
-
- const struct brw_gs_prog_data *gs_prog_data = &pipeline->gs_prog_data;
- offset = 1;
- length = (gs_prog_data->base.vue_map.num_slots + 1) / 2 - offset;
-
- if (pipeline->gs_vec4 == NO_KERNEL)
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_GS, .Enable = false);
- else
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_GS,
- .SingleProgramFlow = false,
- .KernelStartPointer = pipeline->gs_vec4,
- .VectorMaskEnable = Vmask,
- .SamplerCount = 0,
- .BindingTableEntryCount = 0,
- .ExpectedVertexCount = pipeline->gs_vertex_count,
-
- .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_GEOMETRY],
- .PerThreadScratchSpace = ffs(gs_prog_data->base.base.total_scratch / 2048),
-
- .OutputVertexSize = gs_prog_data->output_vertex_size_hwords * 2 - 1,
- .OutputTopology = gs_prog_data->output_topology,
- .VertexURBEntryReadLength = gs_prog_data->base.urb_read_length,
- .DispatchGRFStartRegisterForURBData =
- gs_prog_data->base.base.dispatch_grf_start_reg,
-
- .MaximumNumberofThreads = device->info.max_gs_threads,
- .ControlDataHeaderSize = gs_prog_data->control_data_header_size_hwords,
- //pipeline->gs_prog_data.dispatch_mode |
- .StatisticsEnable = true,
- .IncludePrimitiveID = gs_prog_data->include_primitive_id,
- .ReorderMode = TRAILING,
- .Enable = true,
-
- .ControlDataFormat = gs_prog_data->control_data_format,
-
- /* FIXME: mesa sets this based on ctx->Transform.ClipPlanesEnabled:
- * UserClipDistanceClipTestEnableBitmask_3DSTATE_GS(v)
- * UserClipDistanceCullTestEnableBitmask(v)
- */
-
- .VertexURBEntryOutputReadOffset = offset,
- .VertexURBEntryOutputLength = length);
-
- const struct brw_vue_prog_data *vue_prog_data = &pipeline->vs_prog_data.base;
- /* Skip the VUE header and position slots */
- offset = 1;
- length = (vue_prog_data->vue_map.num_slots + 1) / 2 - offset;
-
- if (pipeline->vs_simd8 == NO_KERNEL || (extra && extra->disable_vs))
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
- .FunctionEnable = false,
- .VertexURBEntryOutputReadOffset = 1,
- /* Even if VS is disabled, SBE still gets the amount of
- * vertex data to read from this field. We use attribute
- * count - 1, as we don't count the VUE header here. */
- .VertexURBEntryOutputLength =
- DIV_ROUND_UP(pCreateInfo->pVertexInputState->attributeCount - 1, 2));
- else
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
- .KernelStartPointer = pipeline->vs_simd8,
- .SingleVertexDispatch = Multiple,
- .VectorMaskEnable = Dmask,
- .SamplerCount = 0,
- .BindingTableEntryCount =
- vue_prog_data->base.binding_table.size_bytes / 4,
- .ThreadDispatchPriority = Normal,
- .FloatingPointMode = IEEE754,
- .IllegalOpcodeExceptionEnable = false,
- .AccessesUAV = false,
- .SoftwareExceptionEnable = false,
-
- .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_VERTEX],
- .PerThreadScratchSpace = ffs(vue_prog_data->base.total_scratch / 2048),
-
- .DispatchGRFStartRegisterForURBData =
- vue_prog_data->base.dispatch_grf_start_reg,
- .VertexURBEntryReadLength = vue_prog_data->urb_read_length,
- .VertexURBEntryReadOffset = 0,
-
- .MaximumNumberofThreads = device->info.max_vs_threads - 1,
- .StatisticsEnable = false,
- .SIMD8DispatchEnable = true,
- .VertexCacheDisable = false,
- .FunctionEnable = true,
-
- .VertexURBEntryOutputReadOffset = offset,
- .VertexURBEntryOutputLength = length,
- .UserClipDistanceClipTestEnableBitmask = 0,
- .UserClipDistanceCullTestEnableBitmask = 0);
-
- const struct brw_wm_prog_data *wm_prog_data = &pipeline->wm_prog_data;
- uint32_t ksp0, ksp2, grf_start0, grf_start2;
-
- ksp2 = 0;
- grf_start2 = 0;
- if (pipeline->ps_simd8 != NO_KERNEL) {
- ksp0 = pipeline->ps_simd8;
- grf_start0 = wm_prog_data->base.dispatch_grf_start_reg;
- if (pipeline->ps_simd16 != NO_KERNEL) {
- ksp2 = pipeline->ps_simd16;
- grf_start2 = wm_prog_data->dispatch_grf_start_reg_16;
- }
- } else if (pipeline->ps_simd16 != NO_KERNEL) {
- ksp0 = pipeline->ps_simd16;
- grf_start0 = wm_prog_data->dispatch_grf_start_reg_16;
- } else {
- unreachable("no ps shader");
- }
-
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PS,
- .KernelStartPointer0 = ksp0,
-
- .SingleProgramFlow = false,
- .VectorMaskEnable = true,
- .SamplerCount = 1,
-
- .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
- .PerThreadScratchSpace = ffs(wm_prog_data->base.total_scratch / 2048),
-
- .MaximumNumberofThreadsPerPSD = 64 - 2,
- .PositionXYOffsetSelect = wm_prog_data->uses_pos_offset ?
- POSOFFSET_SAMPLE: POSOFFSET_NONE,
- .PushConstantEnable = wm_prog_data->base.nr_params > 0,
- ._8PixelDispatchEnable = pipeline->ps_simd8 != NO_KERNEL,
- ._16PixelDispatchEnable = pipeline->ps_simd16 != NO_KERNEL,
- ._32PixelDispatchEnable = false,
-
- .DispatchGRFStartRegisterForConstantSetupData0 = grf_start0,
- .DispatchGRFStartRegisterForConstantSetupData1 = 0,
- .DispatchGRFStartRegisterForConstantSetupData2 = grf_start2,
-
- .KernelStartPointer1 = 0,
- .KernelStartPointer2 = ksp2);
-
- bool per_sample_ps = false;
- anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PS_EXTRA,
- .PixelShaderValid = true,
- .PixelShaderKillsPixel = wm_prog_data->uses_kill,
- .PixelShaderComputedDepthMode = wm_prog_data->computed_depth_mode,
- .AttributeEnable = wm_prog_data->num_varying_inputs > 0,
- .oMaskPresenttoRenderTarget = wm_prog_data->uses_omask,
- .PixelShaderIsPerSample = per_sample_ps);
-
- *pPipeline = anv_pipeline_to_handle(pipeline);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyPipeline(
- VkDevice _device,
- VkPipeline _pipeline)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_pipeline, pipeline, _pipeline);
-
- anv_compiler_free(pipeline);
- anv_reloc_list_finish(&pipeline->batch.relocs, pipeline->device);
- anv_state_stream_finish(&pipeline->program_stream);
- anv_state_pool_free(&device->dynamic_state_pool, pipeline->blend_state);
- anv_device_free(pipeline->device, pipeline);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_CreateGraphicsPipelines(
- VkDevice _device,
- VkPipelineCache pipelineCache,
- uint32_t count,
- const VkGraphicsPipelineCreateInfo* pCreateInfos,
- VkPipeline* pPipelines)
-{
- VkResult result = VK_SUCCESS;
-
- unsigned i = 0;
- for (; i < count; i++) {
- result = anv_pipeline_create(_device, &pCreateInfos[i],
- NULL, &pPipelines[i]);
- if (result != VK_SUCCESS) {
- for (unsigned j = 0; j < i; j++) {
- anv_DestroyPipeline(_device, pPipelines[j]);
- }
-
- return result;
- }
- }
-
- return VK_SUCCESS;
-}
-
-static VkResult anv_compute_pipeline_create(
- VkDevice _device,
- const VkComputePipelineCreateInfo* pCreateInfo,
- VkPipeline* pPipeline)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_pipeline *pipeline;
- VkResult result;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO);
-
- pipeline = anv_device_alloc(device, sizeof(*pipeline), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (pipeline == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- pipeline->device = device;
- pipeline->layout = anv_pipeline_layout_from_handle(pCreateInfo->layout);
-
- result = anv_reloc_list_init(&pipeline->batch.relocs, device);
- if (result != VK_SUCCESS) {
- anv_device_free(device, pipeline);
- return result;
- }
- pipeline->batch.next = pipeline->batch.start = pipeline->batch_data;
- pipeline->batch.end = pipeline->batch.start + sizeof(pipeline->batch_data);
-
- anv_state_stream_init(&pipeline->program_stream,
- &device->instruction_block_pool);
-
- memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
-
- pipeline->shaders[VK_SHADER_STAGE_COMPUTE] =
- anv_shader_from_handle(pCreateInfo->cs.shader);
-
- pipeline->use_repclear = false;
-
- anv_compiler_run(device->compiler, pipeline);
-
- const struct brw_cs_prog_data *cs_prog_data = &pipeline->cs_prog_data;
-
- anv_batch_emit(&pipeline->batch, GEN8_MEDIA_VFE_STATE,
- .ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
- .PerThreadScratchSpace = ffs(cs_prog_data->base.total_scratch / 2048),
- .ScratchSpaceBasePointerHigh = 0,
- .StackSize = 0,
-
- .MaximumNumberofThreads = device->info.max_cs_threads - 1,
- .NumberofURBEntries = 2,
- .ResetGatewayTimer = true,
- .BypassGatewayControl = true,
- .URBEntryAllocationSize = 2,
- .CURBEAllocationSize = 0);
-
- struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
- uint32_t group_size = prog_data->local_size[0] *
- prog_data->local_size[1] * prog_data->local_size[2];
- pipeline->cs_thread_width_max = DIV_ROUND_UP(group_size, prog_data->simd_size);
- uint32_t remainder = group_size & (prog_data->simd_size - 1);
-
- if (remainder > 0)
- pipeline->cs_right_mask = ~0u >> (32 - remainder);
- else
- pipeline->cs_right_mask = ~0u >> (32 - prog_data->simd_size);
-
-
- *pPipeline = anv_pipeline_to_handle(pipeline);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_CreateComputePipelines(
- VkDevice _device,
- VkPipelineCache pipelineCache,
- uint32_t count,
- const VkComputePipelineCreateInfo* pCreateInfos,
- VkPipeline* pPipelines)
-{
- VkResult result = VK_SUCCESS;
-
- unsigned i = 0;
- for (; i < count; i++) {
- result = anv_compute_pipeline_create(_device, &pCreateInfos[i],
- &pPipelines[i]);
- if (result != VK_SUCCESS) {
- for (unsigned j = 0; j < i; j++) {
- anv_DestroyPipeline(_device, pPipelines[j]);
- }
-
- return result;
- }
- }
-
- return VK_SUCCESS;
-}
-
-// Pipeline layout functions
-
-VkResult anv_CreatePipelineLayout(
- VkDevice _device,
- const VkPipelineLayoutCreateInfo* pCreateInfo,
- VkPipelineLayout* pPipelineLayout)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_pipeline_layout *layout;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
-
- layout = anv_device_alloc(device, sizeof(*layout), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (layout == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- layout->num_sets = pCreateInfo->descriptorSetCount;
-
- uint32_t surface_start[VK_SHADER_STAGE_NUM] = { 0, };
- uint32_t sampler_start[VK_SHADER_STAGE_NUM] = { 0, };
-
- for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
- layout->stage[s].surface_count = 0;
- layout->stage[s].sampler_count = 0;
- }
-
- for (uint32_t i = 0; i < pCreateInfo->descriptorSetCount; i++) {
- ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout,
- pCreateInfo->pSetLayouts[i]);
-
- layout->set[i].layout = set_layout;
- for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
- layout->set[i].surface_start[s] = surface_start[s];
- surface_start[s] += set_layout->stage[s].surface_count;
- layout->set[i].sampler_start[s] = sampler_start[s];
- sampler_start[s] += set_layout->stage[s].sampler_count;
-
- layout->stage[s].surface_count += set_layout->stage[s].surface_count;
- layout->stage[s].sampler_count += set_layout->stage[s].sampler_count;
- }
- }
-
- *pPipelineLayout = anv_pipeline_layout_to_handle(layout);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_DestroyPipelineLayout(
- VkDevice _device,
- VkPipelineLayout _pipelineLayout)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_pipeline_layout, pipeline_layout, _pipelineLayout);
-
- anv_device_free(device, pipeline_layout);
-
- return VK_SUCCESS;
-}
+++ /dev/null
-/*
- * 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.
- */
-
-#pragma once
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <pthread.h>
-#include <assert.h>
-#include <i915_drm.h>
-
-#ifdef HAVE_VALGRIND
-#include <valgrind.h>
-#include <memcheck.h>
-#define VG(x) x
-#define __gen_validate_value(x) VALGRIND_CHECK_MEM_IS_DEFINED(&(x), sizeof(x))
-#else
-#define VG(x)
-#endif
-
-#include "brw_device_info.h"
-#include "util/macros.h"
-
-#define VK_PROTOTYPES
-#include <vulkan/vulkan.h>
-#include <vulkan/vulkan_intel.h>
-#include <vulkan/vk_wsi_lunarg.h>
-
-#include "entrypoints.h"
-
-#include "brw_context.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define anv_noreturn __attribute__((__noreturn__))
-#define anv_printflike(a, b) __attribute__((__format__(__printf__, a, b)))
-
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-
-static inline uint32_t
-align_u32(uint32_t v, uint32_t a)
-{
- return (v + a - 1) & ~(a - 1);
-}
-
-static inline int32_t
-align_i32(int32_t v, int32_t a)
-{
- return (v + a - 1) & ~(a - 1);
-}
-
-/** Alignment must be a power of 2. */
-static inline bool
-anv_is_aligned(uintmax_t n, uintmax_t a)
-{
- assert(a == (a & -a));
- return (n & (a - 1)) == 0;
-}
-
-static inline uint32_t
-anv_minify(uint32_t n, uint32_t levels)
-{
- if (unlikely(n == 0))
- return 0;
- else
- return MAX(n >> levels, 1);
-}
-
-static inline bool
-anv_clear_mask(uint32_t *inout_mask, uint32_t clear_mask)
-{
- if (*inout_mask & clear_mask) {
- *inout_mask &= ~clear_mask;
- return true;
- } else {
- return false;
- }
-}
-
-#define for_each_bit(b, dword) \
- for (uint32_t __dword = (dword); \
- (b) = __builtin_ffs(__dword) - 1, __dword; \
- __dword &= ~(1 << (b)))
-
-/* Define no kernel as 1, since that's an illegal offset for a kernel */
-#define NO_KERNEL 1
-
-struct anv_common {
- VkStructureType sType;
- const void* pNext;
-};
-
-/* Whenever we generate an error, pass it through this function. Useful for
- * debugging, where we can break on it. Only call at error site, not when
- * propagating errors. Might be useful to plug in a stack trace here.
- */
-
-static inline VkResult
-vk_error(VkResult error)
-{
-#ifdef DEBUG
- fprintf(stderr, "vk_error: %x\n", error);
-#endif
-
- return error;
-}
-
-void __anv_finishme(const char *file, int line, const char *format, ...)
- anv_printflike(3, 4);
-void anv_loge(const char *format, ...) anv_printflike(1, 2);
-void anv_loge_v(const char *format, va_list va);
-
-/**
- * Print a FINISHME message, including its source location.
- */
-#define anv_finishme(format, ...) \
- __anv_finishme(__FILE__, __LINE__, format, ##__VA_ARGS__);
-
-/* A non-fatal assert. Useful for debugging. */
-#ifdef DEBUG
-#define anv_assert(x) ({ \
- if (unlikely(!(x))) \
- fprintf(stderr, "%s:%d ASSERT: %s\n", __FILE__, __LINE__, #x); \
-})
-#else
-#define anv_assert(x)
-#endif
-
-void anv_abortf(const char *format, ...) anv_noreturn anv_printflike(1, 2);
-void anv_abortfv(const char *format, va_list va) anv_noreturn;
-
-#define stub_return(v) \
- do { \
- anv_finishme("stub %s", __func__); \
- return (v); \
- } while (0)
-
-#define stub() \
- do { \
- anv_finishme("stub %s", __func__); \
- return; \
- } while (0)
-
-/**
- * A dynamically growable, circular buffer. Elements are added at head and
- * removed from tail. head and tail are free-running uint32_t indices and we
- * only compute the modulo with size when accessing the array. This way,
- * number of bytes in the queue is always head - tail, even in case of
- * wraparound.
- */
-
-struct anv_vector {
- uint32_t head;
- uint32_t tail;
- uint32_t element_size;
- uint32_t size;
- void *data;
-};
-
-int anv_vector_init(struct anv_vector *queue, uint32_t element_size, uint32_t size);
-void *anv_vector_add(struct anv_vector *queue);
-void *anv_vector_remove(struct anv_vector *queue);
-
-static inline int
-anv_vector_length(struct anv_vector *queue)
-{
- return (queue->head - queue->tail) / queue->element_size;
-}
-
-static inline void
-anv_vector_finish(struct anv_vector *queue)
-{
- free(queue->data);
-}
-
-#define anv_vector_foreach(elem, queue) \
- static_assert(__builtin_types_compatible_p(__typeof__(queue), struct anv_vector *), ""); \
- for (uint32_t __anv_vector_offset = (queue)->tail; \
- elem = (queue)->data + (__anv_vector_offset & ((queue)->size - 1)), __anv_vector_offset < (queue)->head; \
- __anv_vector_offset += (queue)->element_size)
-
-struct anv_bo {
- int gem_handle;
- uint32_t index;
- uint64_t offset;
- uint64_t size;
-
- /* This field is here for the benefit of the aub dumper. It can (and for
- * userptr bos it must) be set to the cpu map of the buffer. Destroying
- * the bo won't clean up the mmap, it's still the responsibility of the bo
- * user to do that. */
- void *map;
-};
-
-/* Represents a lock-free linked list of "free" things. This is used by
- * both the block pool and the state pools. Unfortunately, in order to
- * solve the ABA problem, we can't use a single uint32_t head.
- */
-union anv_free_list {
- struct {
- uint32_t offset;
-
- /* A simple count that is incremented every time the head changes. */
- uint32_t count;
- };
- uint64_t u64;
-};
-
-#define ANV_FREE_LIST_EMPTY ((union anv_free_list) { { 1, 0 } })
-
-struct anv_block_pool {
- struct anv_device *device;
-
- struct anv_bo bo;
- void *map;
- int fd;
- uint32_t size;
-
- /**
- * Array of mmaps and gem handles owned by the block pool, reclaimed when
- * the block pool is destroyed.
- */
- struct anv_vector mmap_cleanups;
-
- uint32_t block_size;
-
- uint32_t next_block;
- union anv_free_list free_list;
-};
-
-struct anv_block_state {
- union {
- struct {
- uint32_t next;
- uint32_t end;
- };
- uint64_t u64;
- };
-};
-
-struct anv_state {
- uint32_t offset;
- uint32_t alloc_size;
- void *map;
-};
-
-struct anv_fixed_size_state_pool {
- size_t state_size;
- union anv_free_list free_list;
- struct anv_block_state block;
-};
-
-#define ANV_MIN_STATE_SIZE_LOG2 6
-#define ANV_MAX_STATE_SIZE_LOG2 10
-
-#define ANV_STATE_BUCKETS (ANV_MAX_STATE_SIZE_LOG2 - ANV_MIN_STATE_SIZE_LOG2)
-
-struct anv_state_pool {
- struct anv_block_pool *block_pool;
- struct anv_fixed_size_state_pool buckets[ANV_STATE_BUCKETS];
-};
-
-struct anv_state_stream {
- struct anv_block_pool *block_pool;
- uint32_t next;
- uint32_t current_block;
- uint32_t end;
-};
-
-void anv_block_pool_init(struct anv_block_pool *pool,
- struct anv_device *device, uint32_t block_size);
-void anv_block_pool_finish(struct anv_block_pool *pool);
-uint32_t anv_block_pool_alloc(struct anv_block_pool *pool);
-void anv_block_pool_free(struct anv_block_pool *pool, uint32_t offset);
-void anv_state_pool_init(struct anv_state_pool *pool,
- struct anv_block_pool *block_pool);
-struct anv_state anv_state_pool_alloc(struct anv_state_pool *pool,
- size_t state_size, size_t alignment);
-void anv_state_pool_free(struct anv_state_pool *pool, struct anv_state state);
-void anv_state_stream_init(struct anv_state_stream *stream,
- struct anv_block_pool *block_pool);
-void anv_state_stream_finish(struct anv_state_stream *stream);
-struct anv_state anv_state_stream_alloc(struct anv_state_stream *stream,
- uint32_t size, uint32_t alignment);
-
-/**
- * Implements a pool of re-usable BOs. The interface is identical to that
- * of block_pool except that each block is its own BO.
- */
-struct anv_bo_pool {
- struct anv_device *device;
-
- uint32_t bo_size;
-
- void *free_list;
-};
-
-void anv_bo_pool_init(struct anv_bo_pool *pool,
- struct anv_device *device, uint32_t block_size);
-void anv_bo_pool_finish(struct anv_bo_pool *pool);
-VkResult anv_bo_pool_alloc(struct anv_bo_pool *pool, struct anv_bo *bo);
-void anv_bo_pool_free(struct anv_bo_pool *pool, const struct anv_bo *bo);
-
-struct anv_physical_device {
- struct anv_instance * instance;
- uint32_t chipset_id;
- bool no_hw;
- const char * path;
- const char * name;
- const struct brw_device_info * info;
- int fd;
-};
-
-struct anv_instance {
- void * pAllocUserData;
- PFN_vkAllocFunction pfnAlloc;
- PFN_vkFreeFunction pfnFree;
- uint32_t apiVersion;
- uint32_t physicalDeviceCount;
- struct anv_physical_device physicalDevice;
-};
-
-struct anv_meta_state {
- struct {
- VkPipeline pipeline;
- } clear;
-
- struct {
- VkPipeline pipeline;
- VkPipelineLayout pipeline_layout;
- VkDescriptorSetLayout ds_layout;
- } blit;
-
- struct {
- VkDynamicRasterState rs_state;
- VkDynamicColorBlendState cb_state;
- VkDynamicDepthStencilState ds_state;
- } shared;
-};
-
-struct anv_queue {
- struct anv_device * device;
-
- struct anv_state_pool * pool;
-
- /**
- * Serial number of the most recently completed batch executed on the
- * engine.
- */
- struct anv_state completed_serial;
-
- /**
- * The next batch submitted to the engine will be assigned this serial
- * number.
- */
- uint32_t next_serial;
-
- uint32_t last_collected_serial;
-};
-
-struct anv_device {
- struct anv_instance * instance;
- uint32_t chipset_id;
- struct brw_device_info info;
- int context_id;
- int fd;
- bool no_hw;
- bool dump_aub;
-
- struct anv_bo_pool batch_bo_pool;
-
- struct anv_block_pool dynamic_state_block_pool;
- struct anv_state_pool dynamic_state_pool;
-
- struct anv_block_pool instruction_block_pool;
- struct anv_block_pool surface_state_block_pool;
- struct anv_state_pool surface_state_pool;
-
- struct anv_meta_state meta_state;
-
- struct anv_state border_colors;
-
- struct anv_queue queue;
-
- struct anv_block_pool scratch_block_pool;
-
- struct anv_compiler * compiler;
- struct anv_aub_writer * aub_writer;
- pthread_mutex_t mutex;
-};
-
-void *
-anv_device_alloc(struct anv_device * device,
- size_t size,
- size_t alignment,
- VkSystemAllocType allocType);
-
-void
-anv_device_free(struct anv_device * device,
- void * mem);
-
-void* anv_gem_mmap(struct anv_device *device,
- uint32_t gem_handle, uint64_t offset, uint64_t size);
-void anv_gem_munmap(void *p, uint64_t size);
-uint32_t anv_gem_create(struct anv_device *device, size_t size);
-void anv_gem_close(struct anv_device *device, int gem_handle);
-int anv_gem_userptr(struct anv_device *device, void *mem, size_t size);
-int anv_gem_wait(struct anv_device *device, int gem_handle, int64_t *timeout_ns);
-int anv_gem_execbuffer(struct anv_device *device,
- struct drm_i915_gem_execbuffer2 *execbuf);
-int anv_gem_set_tiling(struct anv_device *device, int gem_handle,
- uint32_t stride, uint32_t tiling);
-int anv_gem_create_context(struct anv_device *device);
-int anv_gem_destroy_context(struct anv_device *device, int context);
-int anv_gem_get_param(int fd, uint32_t param);
-int anv_gem_get_aperture(struct anv_physical_device *physical_dev, uint64_t *size);
-int anv_gem_handle_to_fd(struct anv_device *device, int gem_handle);
-int anv_gem_fd_to_handle(struct anv_device *device, int fd);
-int anv_gem_userptr(struct anv_device *device, void *mem, size_t size);
-
-VkResult anv_bo_init_new(struct anv_bo *bo, struct anv_device *device, uint64_t size);
-
-struct anv_reloc_list {
- size_t num_relocs;
- size_t array_length;
- struct drm_i915_gem_relocation_entry * relocs;
- struct anv_bo ** reloc_bos;
-};
-
-VkResult anv_reloc_list_init(struct anv_reloc_list *list,
- struct anv_device *device);
-void anv_reloc_list_finish(struct anv_reloc_list *list,
- struct anv_device *device);
-
-uint64_t anv_reloc_list_add(struct anv_reloc_list *list,
- struct anv_device *device,
- uint32_t offset, struct anv_bo *target_bo,
- uint32_t delta);
-
-struct anv_batch_bo {
- struct anv_bo bo;
-
- /* Bytes actually consumed in this batch BO */
- size_t length;
-
- /* These offsets reference the per-batch reloc list */
- size_t first_reloc;
- size_t num_relocs;
-
- struct anv_batch_bo * prev_batch_bo;
-};
-
-struct anv_batch {
- struct anv_device * device;
-
- void * start;
- void * end;
- void * next;
-
- struct anv_reloc_list relocs;
-
- /* This callback is called (with the associated user data) in the event
- * that the batch runs out of space.
- */
- VkResult (*extend_cb)(struct anv_batch *, void *);
- void * user_data;
-};
-
-void *anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords);
-void anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other);
-uint64_t anv_batch_emit_reloc(struct anv_batch *batch,
- void *location, struct anv_bo *bo, uint32_t offset);
-
-struct anv_address {
- struct anv_bo *bo;
- uint32_t offset;
-};
-
-#define __gen_address_type struct anv_address
-#define __gen_user_data struct anv_batch
-
-static inline uint64_t
-__gen_combine_address(struct anv_batch *batch, void *location,
- const struct anv_address address, uint32_t delta)
-{
- if (address.bo == NULL) {
- return delta;
- } else {
- assert(batch->start <= location && location < batch->end);
-
- return anv_batch_emit_reloc(batch, location, address.bo, address.offset + delta);
- }
-}
-
-#include "gen7_pack.h"
-#include "gen75_pack.h"
-#undef GEN8_3DSTATE_MULTISAMPLE
-#include "gen8_pack.h"
-
-#define anv_batch_emit(batch, cmd, ...) do { \
- struct cmd __template = { \
- cmd ## _header, \
- __VA_ARGS__ \
- }; \
- void *__dst = anv_batch_emit_dwords(batch, cmd ## _length); \
- cmd ## _pack(batch, __dst, &__template); \
- } while (0)
-
-#define anv_batch_emitn(batch, n, cmd, ...) ({ \
- struct cmd __template = { \
- cmd ## _header, \
- .DwordLength = n - cmd ## _length_bias, \
- __VA_ARGS__ \
- }; \
- void *__dst = anv_batch_emit_dwords(batch, n); \
- cmd ## _pack(batch, __dst, &__template); \
- __dst; \
- })
-
-#define anv_batch_emit_merge(batch, dwords0, dwords1) \
- do { \
- uint32_t *dw; \
- \
- assert(ARRAY_SIZE(dwords0) == ARRAY_SIZE(dwords1)); \
- dw = anv_batch_emit_dwords((batch), ARRAY_SIZE(dwords0)); \
- for (uint32_t i = 0; i < ARRAY_SIZE(dwords0); i++) \
- dw[i] = (dwords0)[i] | (dwords1)[i]; \
- VG(VALGRIND_CHECK_MEM_IS_DEFINED(dw, ARRAY_SIZE(dwords0) * 4));\
- } while (0)
-
-#define GEN8_MOCS { \
- .MemoryTypeLLCeLLCCacheabilityControl = WB, \
- .TargetCache = L3DefertoPATforLLCeLLCselection, \
- .AgeforQUADLRU = 0 \
- }
-
-struct anv_device_memory {
- struct anv_bo bo;
- VkDeviceSize map_size;
- void * map;
-};
-
-struct anv_dynamic_vp_state {
- struct anv_state sf_clip_vp;
- struct anv_state cc_vp;
- struct anv_state scissor;
-};
-
-struct anv_dynamic_rs_state {
- uint32_t state_sf[GEN8_3DSTATE_SF_length];
- uint32_t state_raster[GEN8_3DSTATE_RASTER_length];
-};
-
-struct anv_dynamic_ds_state {
- uint32_t state_wm_depth_stencil[GEN8_3DSTATE_WM_DEPTH_STENCIL_length];
- uint32_t state_color_calc[GEN8_COLOR_CALC_STATE_length];
-};
-
-struct anv_dynamic_cb_state {
- uint32_t state_color_calc[GEN8_COLOR_CALC_STATE_length];
-
-};
-
-struct anv_descriptor_slot {
- int8_t dynamic_slot;
- uint8_t index;
-};
-
-struct anv_descriptor_set_layout {
- struct {
- uint32_t surface_count;
- struct anv_descriptor_slot *surface_start;
- uint32_t sampler_count;
- struct anv_descriptor_slot *sampler_start;
- } stage[VK_SHADER_STAGE_NUM];
-
- uint32_t count;
- uint32_t num_dynamic_buffers;
- uint32_t shader_stages;
- struct anv_descriptor_slot entries[0];
-};
-
-struct anv_descriptor {
- struct anv_sampler *sampler;
- struct anv_surface_view *view;
-};
-
-struct anv_descriptor_set {
- struct anv_descriptor descriptors[0];
-};
-
-VkResult
-anv_descriptor_set_create(struct anv_device *device,
- const struct anv_descriptor_set_layout *layout,
- struct anv_descriptor_set **out_set);
-
-void
-anv_descriptor_set_destroy(struct anv_device *device,
- struct anv_descriptor_set *set);
-
-#define MAX_VBS 32
-#define MAX_SETS 8
-#define MAX_RTS 8
-
-struct anv_pipeline_layout {
- struct {
- struct anv_descriptor_set_layout *layout;
- uint32_t surface_start[VK_SHADER_STAGE_NUM];
- uint32_t sampler_start[VK_SHADER_STAGE_NUM];
- } set[MAX_SETS];
-
- uint32_t num_sets;
-
- struct {
- uint32_t surface_count;
- uint32_t sampler_count;
- } stage[VK_SHADER_STAGE_NUM];
-};
-
-struct anv_buffer {
- struct anv_device * device;
- VkDeviceSize size;
-
- /* Set when bound */
- struct anv_bo * bo;
- VkDeviceSize offset;
-};
-
-#define ANV_CMD_BUFFER_PIPELINE_DIRTY (1 << 0)
-#define ANV_CMD_BUFFER_RS_DIRTY (1 << 2)
-#define ANV_CMD_BUFFER_DS_DIRTY (1 << 3)
-#define ANV_CMD_BUFFER_CB_DIRTY (1 << 4)
-#define ANV_CMD_BUFFER_VP_DIRTY (1 << 5)
-#define ANV_CMD_BUFFER_INDEX_BUFFER_DIRTY (1 << 6)
-
-struct anv_vertex_binding {
- struct anv_buffer * buffer;
- VkDeviceSize offset;
-};
-
-struct anv_descriptor_set_binding {
- struct anv_descriptor_set * set;
- uint32_t dynamic_offsets[128];
-};
-
-/** State required while building cmd buffer */
-struct anv_cmd_state {
- uint32_t current_pipeline;
- uint32_t vb_dirty;
- uint32_t dirty;
- uint32_t compute_dirty;
- uint32_t descriptors_dirty;
- uint32_t scratch_size;
- struct anv_pipeline * pipeline;
- struct anv_pipeline * compute_pipeline;
- struct anv_framebuffer * framebuffer;
- struct anv_render_pass * pass;
- struct anv_subpass * subpass;
- struct anv_dynamic_rs_state * rs_state;
- struct anv_dynamic_ds_state * ds_state;
- struct anv_dynamic_vp_state * vp_state;
- struct anv_dynamic_cb_state * cb_state;
- uint32_t state_vf[GEN8_3DSTATE_VF_length];
- struct anv_vertex_binding vertex_bindings[MAX_VBS];
- struct anv_descriptor_set_binding descriptors[MAX_SETS];
-};
-
-VkResult anv_cmd_state_init(struct anv_cmd_state *state);
-void anv_cmd_state_fini(struct anv_cmd_state *state);
-
-struct anv_cmd_buffer {
- struct anv_device * device;
-
- struct drm_i915_gem_execbuffer2 execbuf;
- struct drm_i915_gem_exec_object2 * exec2_objects;
- uint32_t exec2_bo_count;
- struct anv_bo ** exec2_bos;
- uint32_t exec2_array_length;
- bool need_reloc;
- uint32_t serial;
-
- struct anv_batch batch;
- struct anv_batch_bo * last_batch_bo;
- struct anv_batch_bo * surface_batch_bo;
- uint32_t surface_next;
- struct anv_reloc_list surface_relocs;
- struct anv_state_stream surface_state_stream;
- struct anv_state_stream dynamic_state_stream;
-
- struct anv_cmd_state state;
-};
-
-struct anv_state
-anv_cmd_buffer_alloc_surface_state(struct anv_cmd_buffer *cmd_buffer,
- uint32_t size, uint32_t alignment);
-struct anv_state
-anv_cmd_buffer_alloc_dynamic_state(struct anv_cmd_buffer *cmd_buffer,
- uint32_t size, uint32_t alignment);
-
-VkResult anv_cmd_buffer_new_surface_state_bo(struct anv_cmd_buffer *cmd_buffer);
-
-void anv_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer);
-
-void anv_cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
- struct anv_subpass *subpass);
-
-void anv_cmd_buffer_clear_attachments(struct anv_cmd_buffer *cmd_buffer,
- struct anv_render_pass *pass,
- const VkClearValue *clear_values);
-
-void anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer);
-void anv_aub_writer_destroy(struct anv_aub_writer *writer);
-
-struct anv_fence {
- struct anv_bo bo;
- struct drm_i915_gem_execbuffer2 execbuf;
- struct drm_i915_gem_exec_object2 exec2_objects[1];
- bool ready;
-};
-
-struct anv_shader_module {
- uint32_t size;
- char data[0];
-};
-
-struct anv_shader {
- struct anv_shader_module * module;
- char entrypoint[0];
-};
-
-struct anv_pipeline {
- struct anv_device * device;
- struct anv_batch batch;
- uint32_t batch_data[256];
- struct anv_shader * shaders[VK_SHADER_STAGE_NUM];
- struct anv_pipeline_layout * layout;
- bool use_repclear;
-
- struct brw_vs_prog_data vs_prog_data;
- struct brw_wm_prog_data wm_prog_data;
- struct brw_gs_prog_data gs_prog_data;
- struct brw_cs_prog_data cs_prog_data;
- bool writes_point_size;
- struct brw_stage_prog_data * prog_data[VK_SHADER_STAGE_NUM];
- uint32_t scratch_start[VK_SHADER_STAGE_NUM];
- uint32_t total_scratch;
- struct {
- uint32_t vs_start;
- uint32_t vs_size;
- uint32_t nr_vs_entries;
- uint32_t gs_start;
- uint32_t gs_size;
- uint32_t nr_gs_entries;
- } urb;
-
- uint32_t active_stages;
- struct anv_state_stream program_stream;
- struct anv_state blend_state;
- uint32_t vs_simd8;
- uint32_t ps_simd8;
- uint32_t ps_simd16;
- uint32_t gs_vec4;
- uint32_t gs_vertex_count;
- uint32_t cs_simd;
-
- uint32_t vb_used;
- uint32_t binding_stride[MAX_VBS];
-
- uint32_t state_sf[GEN8_3DSTATE_SF_length];
- uint32_t state_vf[GEN8_3DSTATE_VF_length];
- uint32_t state_raster[GEN8_3DSTATE_RASTER_length];
- uint32_t state_wm_depth_stencil[GEN8_3DSTATE_WM_DEPTH_STENCIL_length];
-
- uint32_t cs_thread_width_max;
- uint32_t cs_right_mask;
-};
-
-struct anv_pipeline_create_info {
- bool use_repclear;
- bool disable_viewport;
- bool disable_scissor;
- bool disable_vs;
- bool use_rectlist;
-};
-
-VkResult
-anv_pipeline_create(VkDevice device,
- const VkGraphicsPipelineCreateInfo *pCreateInfo,
- const struct anv_pipeline_create_info *extra,
- VkPipeline *pPipeline);
-
-struct anv_compiler *anv_compiler_create(struct anv_device *device);
-void anv_compiler_destroy(struct anv_compiler *compiler);
-int anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline);
-void anv_compiler_free(struct anv_pipeline *pipeline);
-
-struct anv_format {
- const char *name;
- uint16_t surface_format; /**< RENDER_SURFACE_STATE.SurfaceFormat */
- uint8_t cpp; /**< Bytes-per-pixel of anv_format::surface_format. */
- uint8_t num_channels;
- uint16_t depth_format; /**< 3DSTATE_DEPTH_BUFFER.SurfaceFormat */
- bool has_stencil;
-};
-
-const struct anv_format *
-anv_format_for_vk_format(VkFormat format);
-bool anv_is_vk_format_depth_or_stencil(VkFormat format);
-
-/**
- * A proxy for the color surfaces, depth surfaces, and stencil surfaces.
- */
-struct anv_surface {
- /**
- * Offset from VkImage's base address, as bound by vkBindImageMemory().
- */
- uint32_t offset;
-
- uint32_t stride; /**< RENDER_SURFACE_STATE.SurfacePitch */
- uint16_t qpitch; /**< RENDER_SURFACE_STATE.QPitch */
-
- /**
- * \name Alignment of miptree images, in units of pixels.
- *
- * These fields contain the real alignment values, not the values to be
- * given to the GPU. For example, if h_align is 4, then program the GPU
- * with HALIGN_4.
- * \{
- */
- uint8_t h_align; /**< RENDER_SURFACE_STATE.SurfaceHorizontalAlignment */
- uint8_t v_align; /**< RENDER_SURFACE_STATE.SurfaceVerticalAlignment */
- /** \} */
-
- uint8_t tile_mode; /**< RENDER_SURFACE_STATE.TileMode */
-};
-
-struct anv_image {
- VkImageType type;
- VkExtent3D extent;
- VkFormat format;
- uint32_t levels;
- uint32_t array_size;
-
- VkDeviceSize size;
- uint32_t alignment;
-
- /* Set when bound */
- struct anv_bo *bo;
- VkDeviceSize offset;
-
- struct anv_swap_chain *swap_chain;
-
- /** RENDER_SURFACE_STATE.SurfaceType */
- uint8_t surf_type;
-
- /** Primary surface is either color or depth. */
- struct anv_surface primary_surface;
-
- /** Stencil surface is optional. */
- struct anv_surface stencil_surface;
-};
-
-struct anv_surface_view {
- struct anv_state surface_state; /**< RENDER_SURFACE_STATE */
- struct anv_bo *bo;
- uint32_t offset; /**< VkBufferCreateInfo::offset */
- uint32_t range; /**< VkBufferCreateInfo::range */
- VkFormat format; /**< VkBufferCreateInfo::format */
-};
-
-struct anv_buffer_view {
- struct anv_surface_view view;
-};
-
-struct anv_image_view {
- struct anv_surface_view view;
- VkExtent3D extent;
-};
-
-enum anv_attachment_view_type {
- ANV_ATTACHMENT_VIEW_TYPE_COLOR,
- ANV_ATTACHMENT_VIEW_TYPE_DEPTH_STENCIL,
-};
-
-struct anv_attachment_view {
- enum anv_attachment_view_type attachment_type;
- VkExtent3D extent;
-};
-
-struct anv_color_attachment_view {
- struct anv_attachment_view base;
- struct anv_surface_view view;
-};
-
-struct anv_depth_stencil_view {
- struct anv_attachment_view base;
-
- struct anv_bo *bo;
-
- uint32_t depth_offset; /**< Offset into bo. */
- uint32_t depth_stride; /**< 3DSTATE_DEPTH_BUFFER.SurfacePitch */
- uint32_t depth_format; /**< 3DSTATE_DEPTH_BUFFER.SurfaceFormat */
- uint16_t depth_qpitch; /**< 3DSTATE_DEPTH_BUFFER.SurfaceQPitch */
-
- uint32_t stencil_offset; /**< Offset into bo. */
- uint32_t stencil_stride; /**< 3DSTATE_STENCIL_BUFFER.SurfacePitch */
- uint16_t stencil_qpitch; /**< 3DSTATE_STENCIL_BUFFER.SurfaceQPitch */
-};
-
-struct anv_image_create_info {
- const VkImageCreateInfo *vk_info;
- bool force_tile_mode;
- uint8_t tile_mode;
-};
-
-VkResult anv_image_create(VkDevice _device,
- const struct anv_image_create_info *info,
- VkImage *pImage);
-
-void anv_image_view_init(struct anv_image_view *view,
- struct anv_device *device,
- const VkImageViewCreateInfo* pCreateInfo,
- struct anv_cmd_buffer *cmd_buffer);
-
-void anv_color_attachment_view_init(struct anv_color_attachment_view *view,
- struct anv_device *device,
- const VkAttachmentViewCreateInfo* pCreateInfo,
- struct anv_cmd_buffer *cmd_buffer);
-void anv_fill_buffer_surface_state(void *state, VkFormat format,
- uint32_t offset, uint32_t range);
-
-void anv_surface_view_fini(struct anv_device *device,
- struct anv_surface_view *view);
-
-struct anv_sampler {
- uint32_t state[4];
-};
-
-struct anv_framebuffer {
- uint32_t width;
- uint32_t height;
- uint32_t layers;
-
- /* Viewport for clears */
- VkDynamicViewportState vp_state;
-
- uint32_t attachment_count;
- const struct anv_attachment_view * attachments[0];
-};
-
-struct anv_subpass {
- uint32_t input_count;
- uint32_t * input_attachments;
- uint32_t color_count;
- uint32_t * color_attachments;
- uint32_t * resolve_attachments;
- uint32_t depth_stencil_attachment;
-};
-
-struct anv_render_pass_attachment {
- VkFormat format;
- uint32_t samples;
- VkAttachmentLoadOp load_op;
- VkAttachmentLoadOp stencil_load_op;
-};
-
-struct anv_render_pass {
- uint32_t attachment_count;
- uint32_t subpass_count;
-
- struct anv_render_pass_attachment * attachments;
- struct anv_subpass subpasses[0];
-};
-
-void anv_device_init_meta(struct anv_device *device);
-void anv_device_finish_meta(struct anv_device *device);
-
-void *anv_lookup_entrypoint(const char *name);
-
-#define ANV_DEFINE_HANDLE_CASTS(__anv_type, __VkType) \
- \
- static inline struct __anv_type * \
- __anv_type ## _from_handle(__VkType _handle) \
- { \
- return (struct __anv_type *) _handle; \
- } \
- \
- static inline __VkType \
- __anv_type ## _to_handle(struct __anv_type *_obj) \
- { \
- return (__VkType) _obj; \
- }
-
-#define ANV_DEFINE_NONDISP_HANDLE_CASTS(__anv_type, __VkType) \
- \
- static inline struct __anv_type * \
- __anv_type ## _from_handle(__VkType _handle) \
- { \
- return (struct __anv_type *) _handle.handle; \
- } \
- \
- static inline __VkType \
- __anv_type ## _to_handle(struct __anv_type *_obj) \
- { \
- return (__VkType) { .handle = (uint64_t) _obj }; \
- }
-
-#define ANV_FROM_HANDLE(__anv_type, __name, __handle) \
- struct __anv_type *__name = __anv_type ## _from_handle(__handle)
-
-ANV_DEFINE_HANDLE_CASTS(anv_cmd_buffer, VkCmdBuffer)
-ANV_DEFINE_HANDLE_CASTS(anv_device, VkDevice)
-ANV_DEFINE_HANDLE_CASTS(anv_instance, VkInstance)
-ANV_DEFINE_HANDLE_CASTS(anv_physical_device, VkPhysicalDevice)
-ANV_DEFINE_HANDLE_CASTS(anv_queue, VkQueue)
-ANV_DEFINE_HANDLE_CASTS(anv_swap_chain, VkSwapChainWSI);
-
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_attachment_view, VkAttachmentView)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_buffer, VkBuffer)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_buffer_view, VkBufferView);
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_descriptor_set, VkDescriptorSet)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_descriptor_set_layout, VkDescriptorSetLayout)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_device_memory, VkDeviceMemory)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_dynamic_cb_state, VkDynamicColorBlendState)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_dynamic_ds_state, VkDynamicDepthStencilState)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_dynamic_rs_state, VkDynamicRasterState)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_dynamic_vp_state, VkDynamicViewportState)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_fence, VkFence)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_framebuffer, VkFramebuffer)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_image, VkImage)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_image_view, VkImageView);
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_pipeline, VkPipeline)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_pipeline_layout, VkPipelineLayout)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_query_pool, VkQueryPool)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_render_pass, VkRenderPass)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_sampler, VkSampler)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_shader, VkShader)
-ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_shader_module, VkShaderModule)
-
-#define ANV_DEFINE_STRUCT_CASTS(__anv_type, __VkType) \
- \
- static inline const __VkType * \
- __anv_type ## _to_ ## __VkType(const struct __anv_type *__anv_obj) \
- { \
- return (const __VkType *) __anv_obj; \
- }
-
-#define ANV_COMMON_TO_STRUCT(__VkType, __vk_name, __common_name) \
- const __VkType *__vk_name = anv_common_to_ ## __VkType(__common_name)
-
-ANV_DEFINE_STRUCT_CASTS(anv_common, VkMemoryBarrier)
-ANV_DEFINE_STRUCT_CASTS(anv_common, VkBufferMemoryBarrier)
-ANV_DEFINE_STRUCT_CASTS(anv_common, VkImageMemoryBarrier)
-
-#ifdef __cplusplus
-}
-#endif
+++ /dev/null
-/*
- * 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 <assert.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "private.h"
-
-struct anv_query_pool_slot {
- uint64_t begin;
- uint64_t end;
- uint64_t available;
-};
-
-struct anv_query_pool {
- VkQueryType type;
- uint32_t slots;
- struct anv_bo bo;
-};
-
-VkResult anv_CreateQueryPool(
- VkDevice _device,
- const VkQueryPoolCreateInfo* pCreateInfo,
- VkQueryPool* pQueryPool)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_query_pool *pool;
- VkResult result;
- size_t size;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO);
-
- switch (pCreateInfo->queryType) {
- case VK_QUERY_TYPE_OCCLUSION:
- break;
- case VK_QUERY_TYPE_PIPELINE_STATISTICS:
- return VK_UNSUPPORTED;
- default:
- unreachable("");
- }
-
- pool = anv_device_alloc(device, sizeof(*pool), 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (pool == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- size = pCreateInfo->slots * sizeof(struct anv_query_pool_slot);
- result = anv_bo_init_new(&pool->bo, device, size);
- if (result != VK_SUCCESS)
- goto fail;
-
- pool->bo.map = anv_gem_mmap(device, pool->bo.gem_handle, 0, size);
-
- *pQueryPool = anv_query_pool_to_handle(pool);
-
- return VK_SUCCESS;
-
- fail:
- anv_device_free(device, pool);
-
- return result;
-}
-
-VkResult anv_DestroyQueryPool(
- VkDevice _device,
- VkQueryPool _pool)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_query_pool, pool, _pool);
-
- anv_gem_munmap(pool->bo.map, pool->bo.size);
- anv_gem_close(device, pool->bo.gem_handle);
- anv_device_free(device, pool);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetQueryPoolResults(
- VkDevice _device,
- VkQueryPool queryPool,
- uint32_t startQuery,
- uint32_t queryCount,
- size_t* pDataSize,
- void* pData,
- VkQueryResultFlags flags)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
- struct anv_query_pool_slot *slot = pool->bo.map;
- int64_t timeout = INT64_MAX;
- uint32_t *dst32 = pData;
- uint64_t *dst64 = pData;
- uint64_t result;
- int ret;
-
- if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
- /* Where is the availabilty info supposed to go? */
- anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
- return VK_UNSUPPORTED;
- }
-
- assert(pool->type == VK_QUERY_TYPE_OCCLUSION);
-
- if (flags & VK_QUERY_RESULT_64_BIT)
- *pDataSize = queryCount * sizeof(uint64_t);
- else
- *pDataSize = queryCount * sizeof(uint32_t);
-
- if (pData == NULL)
- return VK_SUCCESS;
-
- if (flags & VK_QUERY_RESULT_WAIT_BIT) {
- ret = anv_gem_wait(device, pool->bo.gem_handle, &timeout);
- if (ret == -1)
- return vk_error(VK_ERROR_UNKNOWN);
- }
-
- for (uint32_t i = 0; i < queryCount; i++) {
- result = slot[startQuery + i].end - slot[startQuery + i].begin;
- if (flags & VK_QUERY_RESULT_64_BIT) {
- *dst64++ = result;
- } else {
- if (result > UINT32_MAX)
- result = UINT32_MAX;
- *dst32++ = result;
- }
- }
-
- return VK_SUCCESS;
-}
-
-static void
-anv_batch_emit_ps_depth_count(struct anv_batch *batch,
- struct anv_bo *bo, uint32_t offset)
-{
- anv_batch_emit(batch, GEN8_PIPE_CONTROL,
- .DestinationAddressType = DAT_PPGTT,
- .PostSyncOperation = WritePSDepthCount,
- .Address = { bo, offset }); /* FIXME: This is only lower 32 bits */
-}
-
-void anv_CmdBeginQuery(
- VkCmdBuffer cmdBuffer,
- VkQueryPool queryPool,
- uint32_t slot,
- VkQueryControlFlags flags)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
-
- switch (pool->type) {
- case VK_QUERY_TYPE_OCCLUSION:
- anv_batch_emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
- slot * sizeof(struct anv_query_pool_slot));
- break;
-
- case VK_QUERY_TYPE_PIPELINE_STATISTICS:
- default:
- unreachable("");
- }
-}
-
-void anv_CmdEndQuery(
- VkCmdBuffer cmdBuffer,
- VkQueryPool queryPool,
- uint32_t slot)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
-
- switch (pool->type) {
- case VK_QUERY_TYPE_OCCLUSION:
- anv_batch_emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
- slot * sizeof(struct anv_query_pool_slot) + 8);
- break;
-
- case VK_QUERY_TYPE_PIPELINE_STATISTICS:
- default:
- unreachable("");
- }
-}
-
-void anv_CmdResetQueryPool(
- VkCmdBuffer cmdBuffer,
- VkQueryPool queryPool,
- uint32_t startQuery,
- uint32_t queryCount)
-{
- stub();
-}
-
-#define TIMESTAMP 0x2358
-
-void anv_CmdWriteTimestamp(
- VkCmdBuffer cmdBuffer,
- VkTimestampType timestampType,
- VkBuffer destBuffer,
- VkDeviceSize destOffset)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_buffer, buffer, destBuffer);
- struct anv_bo *bo = buffer->bo;
-
- switch (timestampType) {
- case VK_TIMESTAMP_TYPE_TOP:
- anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
- .RegisterAddress = TIMESTAMP,
- .MemoryAddress = { bo, buffer->offset + destOffset });
- anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
- .RegisterAddress = TIMESTAMP + 4,
- .MemoryAddress = { bo, buffer->offset + destOffset + 4 });
- break;
-
- case VK_TIMESTAMP_TYPE_BOTTOM:
- anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
- .DestinationAddressType = DAT_PPGTT,
- .PostSyncOperation = WriteTimestamp,
- .Address = /* FIXME: This is only lower 32 bits */
- { bo, buffer->offset + destOffset });
- break;
-
- default:
- break;
- }
-}
-
-#define alu_opcode(v) __gen_field((v), 20, 31)
-#define alu_operand1(v) __gen_field((v), 10, 19)
-#define alu_operand2(v) __gen_field((v), 0, 9)
-#define alu(opcode, operand1, operand2) \
- alu_opcode(opcode) | alu_operand1(operand1) | alu_operand2(operand2)
-
-#define OPCODE_NOOP 0x000
-#define OPCODE_LOAD 0x080
-#define OPCODE_LOADINV 0x480
-#define OPCODE_LOAD0 0x081
-#define OPCODE_LOAD1 0x481
-#define OPCODE_ADD 0x100
-#define OPCODE_SUB 0x101
-#define OPCODE_AND 0x102
-#define OPCODE_OR 0x103
-#define OPCODE_XOR 0x104
-#define OPCODE_STORE 0x180
-#define OPCODE_STOREINV 0x580
-
-#define OPERAND_R0 0x00
-#define OPERAND_R1 0x01
-#define OPERAND_R2 0x02
-#define OPERAND_R3 0x03
-#define OPERAND_R4 0x04
-#define OPERAND_SRCA 0x20
-#define OPERAND_SRCB 0x21
-#define OPERAND_ACCU 0x31
-#define OPERAND_ZF 0x32
-#define OPERAND_CF 0x33
-
-#define CS_GPR(n) (0x2600 + (n) * 8)
-
-static void
-emit_load_alu_reg_u64(struct anv_batch *batch, uint32_t reg,
- struct anv_bo *bo, uint32_t offset)
-{
- anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
- .RegisterAddress = reg,
- .MemoryAddress = { bo, offset });
- anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
- .RegisterAddress = reg + 4,
- .MemoryAddress = { bo, offset + 4 });
-}
-
-void anv_CmdCopyQueryPoolResults(
- VkCmdBuffer cmdBuffer,
- VkQueryPool queryPool,
- uint32_t startQuery,
- uint32_t queryCount,
- VkBuffer destBuffer,
- VkDeviceSize destOffset,
- VkDeviceSize destStride,
- VkQueryResultFlags flags)
-{
- ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
- ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
- ANV_FROM_HANDLE(anv_buffer, buffer, destBuffer);
- uint32_t slot_offset, dst_offset;
-
- if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
- /* Where is the availabilty info supposed to go? */
- anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
- return;
- }
-
- assert(pool->type == VK_QUERY_TYPE_OCCLUSION);
-
- /* FIXME: If we're not waiting, should we just do this on the CPU? */
- if (flags & VK_QUERY_RESULT_WAIT_BIT)
- anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
- .CommandStreamerStallEnable = true,
- .StallAtPixelScoreboard = true);
-
- dst_offset = buffer->offset + destOffset;
- for (uint32_t i = 0; i < queryCount; i++) {
-
- slot_offset = (startQuery + i) * sizeof(struct anv_query_pool_slot);
-
- emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(0), &pool->bo, slot_offset);
- emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(1), &pool->bo, slot_offset + 8);
-
- /* FIXME: We need to clamp the result for 32 bit. */
-
- uint32_t *dw = anv_batch_emitn(&cmd_buffer->batch, 5, GEN8_MI_MATH);
- dw[1] = alu(OPCODE_LOAD, OPERAND_SRCA, OPERAND_R1);
- dw[2] = alu(OPCODE_LOAD, OPERAND_SRCB, OPERAND_R0);
- dw[3] = alu(OPCODE_SUB, 0, 0);
- dw[4] = alu(OPCODE_STORE, OPERAND_R2, OPERAND_ACCU);
-
- anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
- .RegisterAddress = CS_GPR(2),
- /* FIXME: This is only lower 32 bits */
- .MemoryAddress = { buffer->bo, dst_offset });
-
- if (flags & VK_QUERY_RESULT_64_BIT)
- anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
- .RegisterAddress = CS_GPR(2) + 4,
- /* FIXME: This is only lower 32 bits */
- .MemoryAddress = { buffer->bo, dst_offset + 4 });
-
- dst_offset += destStride;
- }
-}
+++ /dev/null
-/*
- * 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 <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-
-#include "private.h"
-
-/** Log an error message. */
-void anv_printflike(1, 2)
-anv_loge(const char *format, ...)
-{
- va_list va;
-
- va_start(va, format);
- anv_loge_v(format, va);
- va_end(va);
-}
-
-/** \see anv_loge() */
-void
-anv_loge_v(const char *format, va_list va)
-{
- fprintf(stderr, "vk: error: ");
- vfprintf(stderr, format, va);
- fprintf(stderr, "\n");
-}
-
-void anv_printflike(3, 4)
-__anv_finishme(const char *file, int line, const char *format, ...)
-{
- va_list ap;
- char buffer[256];
-
- va_start(ap, format);
- vsnprintf(buffer, sizeof(buffer), format, ap);
- va_end(ap);
-
- fprintf(stderr, "%s:%d: FINISHME: %s\n", file, line, buffer);
-}
-
-void anv_noreturn anv_printflike(1, 2)
-anv_abortf(const char *format, ...)
-{
- va_list va;
-
- va_start(va, format);
- anv_abortfv(format, va);
- va_end(va);
-}
-
-void anv_noreturn
-anv_abortfv(const char *format, va_list va)
-{
- fprintf(stderr, "vk: error: ");
- vfprintf(stderr, format, va);
- fprintf(stderr, "\n");
- abort();
-}
-
-int
-anv_vector_init(struct anv_vector *vector, uint32_t element_size, uint32_t size)
-{
- assert(is_power_of_two(size));
- assert(element_size < size && is_power_of_two(element_size));
-
- vector->head = 0;
- vector->tail = 0;
- vector->element_size = element_size;
- vector->size = size;
- vector->data = malloc(size);
-
- return vector->data != NULL;
-}
-
-void *
-anv_vector_add(struct anv_vector *vector)
-{
- uint32_t offset, size, split, tail;
- void *data;
-
- if (vector->head - vector->tail == vector->size) {
- size = vector->size * 2;
- data = malloc(size);
- if (data == NULL)
- return NULL;
- split = align_u32(vector->tail, vector->size);
- tail = vector->tail & (vector->size - 1);
- if (vector->head - split < vector->size) {
- memcpy(data + tail,
- vector->data + tail,
- split - vector->tail);
- memcpy(data + vector->size,
- vector->data, vector->head - split);
- } else {
- memcpy(data + tail,
- vector->data + tail,
- vector->head - vector->tail);
- }
- free(vector->data);
- vector->data = data;
- vector->size = size;
- }
-
- assert(vector->head - vector->tail < vector->size);
-
- offset = vector->head & (vector->size - 1);
- vector->head += vector->element_size;
-
- return vector->data + offset;
-}
-
-void *
-anv_vector_remove(struct anv_vector *vector)
-{
- uint32_t offset;
-
- if (vector->head == vector->tail)
- return NULL;
-
- assert(vector->head - vector->tail <= vector->size);
-
- offset = vector->tail & (vector->size - 1);
- vector->tail += vector->element_size;
-
- return vector->data + offset;
-}
+++ /dev/null
-# coding=utf-8
-#
-# 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.
-#
-
-import fileinput, re, sys
-
-# Each function typedef in the vulkan.h header is all on one line and matches
-# this regepx. We hope that won't change.
-
-p = re.compile('typedef ([^ ]*) *\(VKAPI \*PFN_vk([^(]*)\)(.*);')
-
-entrypoints = []
-
-# We generate a static hash table for entry point lookup
-# (vkGetProcAddress). We use a linear congruential generator for our hash
-# function and a power-of-two size table. The prime numbers are determined
-# experimentally.
-
-none = 0xffff
-hash_size = 256
-u32_mask = 2**32 - 1
-hash_mask = hash_size - 1
-
-prime_factor = 5024183
-prime_step = 19
-
-def hash(name):
- h = 0;
- for c in name:
- h = (h * prime_factor + ord(c)) & u32_mask
-
- return h
-
-opt_header = False
-opt_code = False
-
-if (sys.argv[1] == "header"):
- opt_header = True
- sys.argv.pop()
-elif (sys.argv[1] == "code"):
- opt_code = True
- sys.argv.pop()
-
-# Parse the entry points in the header
-
-i = 0
-for line in fileinput.input():
- m = p.match(line)
- if (m):
- if m.group(2) == 'VoidFunction':
- continue
- fullname = "vk" + m.group(2)
- h = hash(fullname)
- entrypoints.append((m.group(1), m.group(2), m.group(3), i, h))
- i = i + 1
-
-# For outputting entrypoints.h we generate a anv_EntryPoint() prototype
-# per entry point.
-
-if opt_header:
- for type, name, args, num, h in entrypoints:
- print "%s anv_%s%s;" % (type, name, args)
- print "%s anv_validate_%s%s;" % (type, name, args)
- exit()
-
-
-
-print """/*
- * 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.
- */
-
-/* This file generated from vk_gen.py, don't edit directly. */
-
-#include "private.h"
-
-struct anv_entrypoint {
- uint32_t name;
- uint32_t hash;
- void *function;
- void *validate;
-};
-
-/* We use a big string constant to avoid lots of reloctions from the entry
- * point table to lots of little strings. The entries in the entry point table
- * store the index into this big string.
- */
-
-static const char strings[] ="""
-
-offsets = []
-i = 0;
-for type, name, args, num, h in entrypoints:
- print " \"vk%s\\0\"" % name
- offsets.append(i)
- i += 2 + len(name) + 1
-print """ ;
-
-/* Weak aliases for all potential validate functions. These will resolve to
- * NULL if they're not defined, which lets the resolve_entrypoint() function
- * either pick a validate wrapper if available or just plug in the actual
- * entry point.
- */
-"""
-
-for type, name, args, num, h in entrypoints:
- print "%s anv_validate_%s%s __attribute__ ((weak));" % (type, name, args)
-
-# Now generate the table of all entry points and their validation functions
-
-print "\nstatic const struct anv_entrypoint entrypoints[] = {"
-for type, name, args, num, h in entrypoints:
- print " { %5d, 0x%08x, anv_%s, anv_validate_%s }," % (offsets[num], h, name, name)
-print "};\n"
-
-print """
-#ifdef DEBUG
-static bool enable_validate = true;
-#else
-static bool enable_validate = false;
-#endif
-
-/* We can't use symbols that need resolving (like, oh, getenv) in the resolve
- * function. This means that we have to determine whether or not to use the
- * validation layer sometime before that. The constructor function attribute asks
- * the dynamic linker to invoke determine_validate() at dlopen() time which
- * works.
- */
-static void __attribute__ ((constructor))
-determine_validate(void)
-{
- const char *s = getenv("ANV_VALIDATE");
-
- if (s)
- enable_validate = atoi(s);
-}
-
-static void * __attribute__ ((noinline))
-resolve_entrypoint(uint32_t index)
-{
- if (enable_validate && entrypoints[index].validate)
- return entrypoints[index].validate;
-
- return entrypoints[index].function;
-}
-"""
-
-# Now output ifuncs and their resolve helpers for all entry points. The
-# resolve helper calls resolve_entrypoint() with the entry point index, which
-# lets the resolver look it up in the table.
-
-for type, name, args, num, h in entrypoints:
- print "static void *resolve_%s(void) { return resolve_entrypoint(%d); }" % (name, num)
- print "%s vk%s%s\n __attribute__ ((ifunc (\"resolve_%s\"), visibility (\"default\")));\n" % (type, name, args, name)
-
-
-# Now generate the hash table used for entry point look up. This is a
-# uint16_t table of entry point indices. We use 0xffff to indicate an entry
-# in the hash table is empty.
-
-map = [none for f in xrange(hash_size)]
-collisions = [0 for f in xrange(10)]
-for type, name, args, num, h in entrypoints:
- level = 0
- while map[h & hash_mask] != none:
- h = h + prime_step
- level = level + 1
- if level > 9:
- collisions[9] += 1
- else:
- collisions[level] += 1
- map[h & hash_mask] = num
-
-print "/* Hash table stats:"
-print " * size %d entries" % hash_size
-print " * collisions entries"
-for i in xrange(10):
- if (i == 9):
- plus = "+"
- else:
- plus = " "
-
- print " * %2d%s %4d" % (i, plus, collisions[i])
-print " */\n"
-
-print "#define none 0x%04x\n" % none
-
-print "static const uint16_t map[] = {"
-for i in xrange(0, hash_size, 8):
- print " ",
- for j in xrange(i, i + 8):
- if map[j] & 0xffff == 0xffff:
- print " none,",
- else:
- print "0x%04x," % (map[j] & 0xffff),
- print
-
-print "};"
-
-# Finally we generate the hash table lookup function. The hash function and
-# linear probing algorithm matches the hash table generated above.
-
-print """
-void *
-anv_lookup_entrypoint(const char *name)
-{
- static const uint32_t prime_factor = %d;
- static const uint32_t prime_step = %d;
- const struct anv_entrypoint *e;
- uint32_t hash, h, i;
- const char *p;
-
- hash = 0;
- for (p = name; *p; p++)
- hash = hash * prime_factor + *p;
-
- h = hash;
- do {
- i = map[h & %d];
- if (i == none)
- return NULL;
- e = &entrypoints[i];
- h += prime_step;
- } while (e->hash != hash);
-
- if (strcmp(name, strings + e->name) != 0)
- return NULL;
-
- return resolve_entrypoint(i);
-}
-""" % (prime_factor, prime_step, hash_mask)
+++ /dev/null
-/*
- * 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 "private.h"
-
-#include <xcb/xcb.h>
-#include <xcb/dri3.h>
-#include <xcb/present.h>
-
-static const VkFormat formats[] = {
- VK_FORMAT_B5G6R5_UNORM,
- VK_FORMAT_B8G8R8A8_UNORM,
- VK_FORMAT_B8G8R8A8_SRGB,
-};
-
-VkResult anv_GetDisplayInfoWSI(
- VkDisplayWSI display,
- VkDisplayInfoTypeWSI infoType,
- size_t* pDataSize,
- void* pData)
-{
- VkDisplayFormatPropertiesWSI *properties = pData;
- size_t size;
-
- if (pDataSize == NULL)
- return VK_ERROR_INVALID_POINTER;
-
- switch (infoType) {
- case VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI:
- size = sizeof(properties[0]) * ARRAY_SIZE(formats);
-
- if (pData == NULL) {
- *pDataSize = size;
- return VK_SUCCESS;
- }
-
- if (*pDataSize < size)
- return vk_error(VK_ERROR_INVALID_VALUE);
-
- *pDataSize = size;
-
- for (uint32_t i = 0; i < ARRAY_SIZE(formats); i++)
- properties[i].swapChainFormat = formats[i];
-
- return VK_SUCCESS;
-
- default:
- return VK_UNSUPPORTED;
- }
-}
-
-struct anv_swap_chain {
- struct anv_device * device;
- xcb_connection_t * conn;
- xcb_window_t window;
- xcb_gc_t gc;
- VkExtent2D extent;
- uint32_t count;
- struct {
- struct anv_image * image;
- struct anv_device_memory * memory;
- xcb_pixmap_t pixmap;
- } images[0];
-};
-
-VkResult anv_CreateSwapChainWSI(
- VkDevice _device,
- const VkSwapChainCreateInfoWSI* pCreateInfo,
- VkSwapChainWSI* pSwapChain)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
-
- struct anv_swap_chain *chain;
- xcb_void_cookie_t cookie;
- VkResult result;
- size_t size;
- int ret;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI);
-
- size = sizeof(*chain) + pCreateInfo->imageCount * sizeof(chain->images[0]);
- chain = anv_device_alloc(device, size, 8,
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (chain == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- chain->device = device;
- chain->conn = (xcb_connection_t *) pCreateInfo->pNativeWindowSystemHandle;
- chain->window = (xcb_window_t) (uintptr_t) pCreateInfo->pNativeWindowHandle;
- chain->count = pCreateInfo->imageCount;
- chain->extent = pCreateInfo->imageExtent;
-
- for (uint32_t i = 0; i < chain->count; i++) {
- VkDeviceMemory memory_h;
- VkImage image_h;
- struct anv_image *image;
- struct anv_surface *surface;
- struct anv_device_memory *memory;
-
- anv_image_create(_device,
- &(struct anv_image_create_info) {
- .force_tile_mode = true,
- .tile_mode = XMAJOR,
- .vk_info =
- &(VkImageCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
- .imageType = VK_IMAGE_TYPE_2D,
- .format = pCreateInfo->imageFormat,
- .extent = {
- .width = pCreateInfo->imageExtent.width,
- .height = pCreateInfo->imageExtent.height,
- .depth = 1
- },
- .mipLevels = 1,
- .arraySize = 1,
- .samples = 1,
- /* FIXME: Need a way to use X tiling to allow scanout */
- .tiling = VK_IMAGE_TILING_OPTIMAL,
- .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
- .flags = 0,
- }},
- &image_h);
-
- image = anv_image_from_handle(image_h);
- surface = &image->primary_surface;
-
- anv_AllocMemory(_device,
- &(VkMemoryAllocInfo) {
- .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
- .allocationSize = image->size,
- .memoryTypeIndex = 0,
- },
- &memory_h);
-
- memory = anv_device_memory_from_handle(memory_h);
-
- anv_BindImageMemory(VK_NULL_HANDLE, anv_image_to_handle(image),
- memory_h, 0);
-
- ret = anv_gem_set_tiling(device, memory->bo.gem_handle,
- surface->stride, I915_TILING_X);
- if (ret) {
- result = vk_error(VK_ERROR_UNKNOWN);
- goto fail;
- }
-
- int fd = anv_gem_handle_to_fd(device, memory->bo.gem_handle);
- if (fd == -1) {
- result = vk_error(VK_ERROR_UNKNOWN);
- goto fail;
- }
-
- uint32_t bpp = 32;
- uint32_t depth = 24;
- xcb_pixmap_t pixmap = xcb_generate_id(chain->conn);
-
- cookie =
- xcb_dri3_pixmap_from_buffer_checked(chain->conn,
- pixmap,
- chain->window,
- image->size,
- pCreateInfo->imageExtent.width,
- pCreateInfo->imageExtent.height,
- surface->stride,
- depth, bpp, fd);
-
- chain->images[i].image = image;
- chain->images[i].memory = memory;
- chain->images[i].pixmap = pixmap;
- image->swap_chain = chain;
-
- xcb_discard_reply(chain->conn, cookie.sequence);
- }
-
- chain->gc = xcb_generate_id(chain->conn);
- if (!chain->gc) {
- result = vk_error(VK_ERROR_UNKNOWN);
- goto fail;
- }
-
- cookie = xcb_create_gc(chain->conn,
- chain->gc,
- chain->window,
- XCB_GC_GRAPHICS_EXPOSURES,
- (uint32_t []) { 0 });
- xcb_discard_reply(chain->conn, cookie.sequence);
-
- *pSwapChain = anv_swap_chain_to_handle(chain);
-
- return VK_SUCCESS;
-
- fail:
- return result;
-}
-
-VkResult anv_DestroySwapChainWSI(
- VkSwapChainWSI _chain)
-{
- ANV_FROM_HANDLE(anv_swap_chain, chain, _chain);
-
- anv_device_free(chain->device, chain);
-
- return VK_SUCCESS;
-}
-
-VkResult anv_GetSwapChainInfoWSI(
- VkSwapChainWSI _chain,
- VkSwapChainInfoTypeWSI infoType,
- size_t* pDataSize,
- void* pData)
-{
- ANV_FROM_HANDLE(anv_swap_chain, chain, _chain);
-
- VkSwapChainImageInfoWSI *images;
- size_t size;
-
- switch (infoType) {
- case VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI:
- size = sizeof(*images) * chain->count;
- if (pData && *pDataSize < size)
- return VK_ERROR_INVALID_VALUE;
-
- *pDataSize = size;
- if (!pData)
- return VK_SUCCESS;
-
- images = pData;
- for (uint32_t i = 0; i < chain->count; i++) {
- images[i].image = anv_image_to_handle(chain->images[i].image);
- images[i].memory = anv_device_memory_to_handle(chain->images[i].memory);
- }
-
- return VK_SUCCESS;
-
- default:
- return VK_UNSUPPORTED;
- }
-}
-
-VkResult anv_QueuePresentWSI(
- VkQueue queue_,
- const VkPresentInfoWSI* pPresentInfo)
-{
- ANV_FROM_HANDLE(anv_image, image, pPresentInfo->image);
-
- struct anv_swap_chain *chain = image->swap_chain;
- xcb_void_cookie_t cookie;
- xcb_pixmap_t pixmap;
-
- assert(pPresentInfo->sType == VK_STRUCTURE_TYPE_PRESENT_INFO_WSI);
-
- if (chain == NULL)
- return vk_error(VK_ERROR_INVALID_VALUE);
-
- pixmap = XCB_NONE;
- for (uint32_t i = 0; i < chain->count; i++) {
- if (image == chain->images[i].image) {
- pixmap = chain->images[i].pixmap;
- break;
- }
- }
-
- if (pixmap == XCB_NONE)
- return vk_error(VK_ERROR_INVALID_VALUE);
-
- cookie = xcb_copy_area(chain->conn,
- pixmap,
- chain->window,
- chain->gc,
- 0, 0,
- 0, 0,
- chain->extent.width,
- chain->extent.height);
- xcb_discard_reply(chain->conn, cookie.sequence);
-
- xcb_flush(chain->conn);
-
- return VK_SUCCESS;
-}