turnip: Add driver skeleton (v2)
meson files have been updated, autotools and android still need updating. Only build tested. v2 (chadv): - Rebase onto master. - Fix build breakage in Python scripts. - Drop the WSI code. The internal WSI apis have changed recently, and will likely change again before the driver goes upstream. To avoid unnecessary rebase work, let's drop the WSI code and re-add it when we're ready to really use WSI. (olv, after rebase) do not enable freedreno by default on ARM
This commit is contained in:
parent
d086d16b81
commit
26380b3a9f
|
@ -203,6 +203,7 @@ endif
|
|||
|
||||
with_intel_vk = _vulkan_drivers.contains('intel')
|
||||
with_amd_vk = _vulkan_drivers.contains('amd')
|
||||
with_freedreno_vk = _vulkan_drivers.contains('freedreno')
|
||||
with_any_vk = _vulkan_drivers.length() != 0 and _vulkan_drivers != ['']
|
||||
|
||||
if with_dri_swrast and (with_gallium_softpipe or with_gallium_swr)
|
||||
|
|
|
@ -152,7 +152,7 @@ option(
|
|||
'vulkan-drivers',
|
||||
type : 'array',
|
||||
value : ['auto'],
|
||||
choices : ['', 'auto', 'amd', 'intel'],
|
||||
choices : ['', 'auto', 'amd', 'freedreno', 'intel'],
|
||||
description : 'List of vulkan drivers to build. If this is set to auto all drivers applicable to the target OS/architecture will be built'
|
||||
)
|
||||
option(
|
||||
|
|
|
@ -22,3 +22,7 @@ inc_freedreno = include_directories(['.', './registers'])
|
|||
|
||||
subdir('drm')
|
||||
subdir('ir3')
|
||||
|
||||
if with_freedreno_vk
|
||||
subdir('vulkan')
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
# Copyright © 2018 Advanced Micro Devices, Inc.
|
||||
# Copyright © 2018 Mauro Rossi issor.oruam@gmail.com
|
||||
|
||||
# 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.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# get VULKAN_FILES and VULKAN_GENERATED_FILES
|
||||
include $(LOCAL_PATH)/Makefile.sources
|
||||
|
||||
# The gallium includes are for the util/u_math.h include from main/macros.h
|
||||
|
||||
TU_COMMON_INCLUDES := \
|
||||
$(MESA_TOP)/include \
|
||||
$(MESA_TOP)/src/ \
|
||||
$(MESA_TOP)/src/vulkan/wsi \
|
||||
$(MESA_TOP)/src/vulkan/util \
|
||||
$(MESA_TOP)/src/amd \
|
||||
$(MESA_TOP)/src/amd/common \
|
||||
$(MESA_TOP)/src/compiler \
|
||||
$(MESA_TOP)/src/mapi \
|
||||
$(MESA_TOP)/src/mesa \
|
||||
$(MESA_TOP)/src/mesa/drivers/dri/common \
|
||||
$(MESA_TOP)/src/gallium/auxiliary \
|
||||
$(MESA_TOP)/src/gallium/include \
|
||||
frameworks/native/vulkan/include
|
||||
|
||||
TU_SHARED_LIBRARIES := libdrm_amdgpu
|
||||
|
||||
ifeq ($(filter $(MESA_ANDROID_MAJOR_VERSION), 4 5 6 7),)
|
||||
TU_SHARED_LIBRARIES += libnativewindow
|
||||
endif
|
||||
|
||||
#
|
||||
# libmesa_tu_common
|
||||
#
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := libmesa_tu_common
|
||||
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
|
||||
|
||||
intermediates := $(call local-generated-sources-dir)
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
$(VULKAN_FILES)
|
||||
|
||||
LOCAL_CFLAGS += -DFORCE_BUILD_AMDGPU # instructs LLVM to declare LLVMInitializeAMDGPU* functions
|
||||
|
||||
$(call mesa-build-with-llvm)
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(TU_COMMON_INCLUDES) \
|
||||
$(call generated-sources-dir-for,STATIC_LIBRARIES,libmesa_amd_common,,) \
|
||||
$(call generated-sources-dir-for,STATIC_LIBRARIES,libmesa_nir,,)/nir \
|
||||
$(call generated-sources-dir-for,STATIC_LIBRARIES,libmesa_tu_common,,) \
|
||||
$(call generated-sources-dir-for,STATIC_LIBRARIES,libmesa_vulkan_util,,)/util
|
||||
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := \
|
||||
libmesa_vulkan_util
|
||||
|
||||
LOCAL_GENERATED_SOURCES += $(intermediates)/tu_entrypoints.c
|
||||
LOCAL_GENERATED_SOURCES += $(intermediates)/tu_entrypoints.h
|
||||
LOCAL_GENERATED_SOURCES += $(intermediates)/tu_extensions.c
|
||||
LOCAL_GENERATED_SOURCES += $(intermediates)/tu_extensions.h
|
||||
LOCAL_GENERATED_SOURCES += $(intermediates)/vk_format_table.c
|
||||
|
||||
TU_ENTRYPOINTS_SCRIPT := $(MESA_TOP)/src/amd/vulkan/tu_entrypoints_gen.py
|
||||
TU_EXTENSIONS_SCRIPT := $(MESA_TOP)/src/amd/vulkan/tu_extensions.py
|
||||
VK_FORMAT_TABLE_SCRIPT := $(MESA_TOP)/src/amd/vulkan/vk_format_table.py
|
||||
VK_FORMAT_PARSE_SCRIPT := $(MESA_TOP)/src/amd/vulkan/vk_format_parse.py
|
||||
|
||||
vulkan_api_xml = $(MESA_TOP)/src/vulkan/registry/vk.xml
|
||||
vk_format_layout_csv = $(MESA_TOP)/src/amd/vulkan/vk_format_layout.csv
|
||||
|
||||
$(intermediates)/tu_entrypoints.c: $(TU_ENTRYPOINTS_SCRIPT) \
|
||||
$(TU_EXTENSIONS_SCRIPT) \
|
||||
$(vulkan_api_xml)
|
||||
@mkdir -p $(dir $@)
|
||||
$(MESA_PYTHON2) $(TU_ENTRYPOINTS_SCRIPT) \
|
||||
--xml $(vulkan_api_xml) \
|
||||
--outdir $(dir $@)
|
||||
|
||||
$(intermediates)/tu_entrypoints.h: $(intermediates)/tu_entrypoints.c
|
||||
|
||||
$(intermediates)/tu_extensions.c: $(TU_EXTENSIONS_SCRIPT) $(vulkan_api_xml)
|
||||
@mkdir -p $(dir $@)
|
||||
$(MESA_PYTHON2) $(TU_EXTENSIONS_SCRIPT) \
|
||||
--xml $(vulkan_api_xml) \
|
||||
--out-c $@ \
|
||||
--out-h $(addsuffix .h,$(basename $@))
|
||||
|
||||
$(intermediates)/tu_extensions.h: $(intermediates)/tu_extensions.c
|
||||
|
||||
$(intermediates)/vk_format_table.c: $(VK_FORMAT_TABLE_SCRIPT) \
|
||||
$(VK_FORMAT_PARSE_SCRIPT) \
|
||||
$(vk_format_layout_csv)
|
||||
@mkdir -p $(dir $@)
|
||||
$(MESA_PYTHON2) $(VK_FORMAT_TABLE_SCRIPT) $(vk_format_layout_csv) > $@
|
||||
|
||||
LOCAL_SHARED_LIBRARIES += $(TU_SHARED_LIBRARIES)
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := \
|
||||
$(MESA_TOP)/src/amd/vulkan \
|
||||
$(intermediates)
|
||||
|
||||
include $(MESA_COMMON_MK)
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
#
|
||||
# libvulkan_radeon
|
||||
#
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := vulkan.tu
|
||||
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
|
||||
LOCAL_PROPRIETARY_MODULE := true
|
||||
LOCAL_MODULE_RELATIVE_PATH := hw
|
||||
|
||||
LOCAL_LDFLAGS += -Wl,--build-id=sha1
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
$(VULKAN_ANDROID_FILES)
|
||||
|
||||
LOCAL_CFLAGS += -DFORCE_BUILD_AMDGPU # instructs LLVM to declare LLVMInitializeAMDGPU* functions
|
||||
|
||||
$(call mesa-build-with-llvm)
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(TU_COMMON_INCLUDES) \
|
||||
$(call generated-sources-dir-for,STATIC_LIBRARIES,libmesa_tu_common,,)
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := \
|
||||
$(MESA_TOP)/src/amd/vulkan \
|
||||
$(intermediates)
|
||||
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := \
|
||||
libmesa_util \
|
||||
libmesa_nir \
|
||||
libmesa_glsl \
|
||||
libmesa_compiler \
|
||||
libmesa_amdgpu_addrlib \
|
||||
libmesa_amd_common \
|
||||
libmesa_tu_common
|
||||
|
||||
LOCAL_SHARED_LIBRARIES += $(TU_SHARED_LIBRARIES) libz libsync liblog
|
||||
|
||||
include $(MESA_COMMON_MK)
|
||||
include $(BUILD_SHARED_LIBRARY)
|
|
@ -0,0 +1,200 @@
|
|||
# Copyright © 2016 Red Hat
|
||||
#
|
||||
# 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 Makefile.sources
|
||||
|
||||
noinst_HEADERS = \
|
||||
$(top_srcdir)/include/vulkan/vk_platform.h \
|
||||
$(top_srcdir)/include/vulkan/vulkan_core.h \
|
||||
$(top_srcdir)/include/vulkan/vulkan_wayland.h \
|
||||
$(top_srcdir)/include/vulkan/vulkan_xcb.h \
|
||||
$(top_srcdir)/include/vulkan/vulkan_xlib.h \
|
||||
$(top_srcdir)/include/vulkan/vulkan.h
|
||||
|
||||
lib_LTLIBRARIES = libvulkan_radeon.la
|
||||
|
||||
# The gallium includes are for the util/u_math.h include from main/macros.h
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_builddir)/src \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/vulkan/wsi \
|
||||
-I$(top_builddir)/src/vulkan/util \
|
||||
-I$(top_srcdir)/src/vulkan/util \
|
||||
-I$(top_srcdir)/src/amd \
|
||||
-I$(top_srcdir)/src/amd/common \
|
||||
-I$(top_builddir)/src/compiler \
|
||||
-I$(top_builddir)/src/compiler/nir \
|
||||
-I$(top_srcdir)/src/compiler \
|
||||
-I$(top_srcdir)/src/mapi \
|
||||
-I$(top_srcdir)/src/mesa \
|
||||
-I$(top_srcdir)/src/mesa/drivers/dri/common \
|
||||
-I$(top_srcdir)/src/gallium/auxiliary \
|
||||
-I$(top_srcdir)/src/gallium/include \
|
||||
$(AMDGPU_CFLAGS) \
|
||||
$(VALGRIND_CFLAGS) \
|
||||
$(DEFINES)
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(VISIBILITY_CFLAGS) \
|
||||
$(PTHREAD_CFLAGS) \
|
||||
$(LLVM_CFLAGS)
|
||||
|
||||
AM_CXXFLAGS = \
|
||||
$(VISIBILITY_CXXFLAGS) \
|
||||
$(LLVM_CXXFLAGS)
|
||||
|
||||
VULKAN_SOURCES = \
|
||||
$(VULKAN_GENERATED_FILES) \
|
||||
$(VULKAN_FILES)
|
||||
|
||||
VULKAN_LIB_DEPS = \
|
||||
libvulkan_common.la \
|
||||
$(top_builddir)/src/vulkan/libvulkan_util.la \
|
||||
$(top_builddir)/src/vulkan/libvulkan_wsi.la \
|
||||
$(top_builddir)/src/amd/common/libamd_common.la \
|
||||
$(top_builddir)/src/amd/addrlib/libamdgpu_addrlib.la \
|
||||
$(top_builddir)/src/compiler/nir/libnir.la \
|
||||
$(top_builddir)/src/util/libmesautil.la \
|
||||
$(LLVM_LIBS) \
|
||||
$(LIBELF_LIBS) \
|
||||
$(PTHREAD_LIBS) \
|
||||
$(AMDGPU_LIBS) \
|
||||
$(LIBDRM_LIBS) \
|
||||
$(PTHREAD_LIBS) \
|
||||
$(DLOPEN_LIBS) \
|
||||
-lm
|
||||
|
||||
if HAVE_PLATFORM_DRM
|
||||
AM_CPPFLAGS += \
|
||||
-DVK_USE_PLATFORM_DISPLAY_KHR
|
||||
|
||||
VULKAN_SOURCES += $(VULKAN_WSI_DISPLAY_FILES)
|
||||
endif
|
||||
|
||||
if HAVE_XLIB_LEASE
|
||||
AM_CPPFLAGS += \
|
||||
-DVK_USE_PLATFORM_XLIB_XRANDR_EXT \
|
||||
$(XCB_RANDR_CFLAGS) \
|
||||
$(XLIB_RANDR_CFLAGS)
|
||||
|
||||
VULKAN_LIB_DEPS += $(XCB_RANDR_LIBS)
|
||||
endif
|
||||
|
||||
if HAVE_PLATFORM_X11
|
||||
AM_CPPFLAGS += \
|
||||
$(XCB_DRI3_CFLAGS) \
|
||||
-DVK_USE_PLATFORM_XCB_KHR \
|
||||
-DVK_USE_PLATFORM_XLIB_KHR
|
||||
|
||||
VULKAN_SOURCES += $(VULKAN_WSI_X11_FILES)
|
||||
|
||||
VULKAN_LIB_DEPS += $(XCB_DRI3_LIBS)
|
||||
endif
|
||||
|
||||
|
||||
if HAVE_PLATFORM_WAYLAND
|
||||
AM_CPPFLAGS += \
|
||||
$(WAYLAND_CLIENT_CFLAGS) \
|
||||
-DVK_USE_PLATFORM_WAYLAND_KHR
|
||||
|
||||
VULKAN_SOURCES += $(VULKAN_WSI_WAYLAND_FILES)
|
||||
|
||||
VULKAN_LIB_DEPS += \
|
||||
$(WAYLAND_CLIENT_LIBS)
|
||||
endif
|
||||
|
||||
if HAVE_PLATFORM_ANDROID
|
||||
AM_CPPFLAGS += $(ANDROID_CPPFLAGS)
|
||||
AM_CFLAGS += $(ANDROID_CFLAGS)
|
||||
VULKAN_LIB_DEPS += $(ANDROID_LIBS)
|
||||
VULKAN_SOURCES += $(VULKAN_ANDROID_FILES)
|
||||
endif
|
||||
|
||||
noinst_LTLIBRARIES = libvulkan_common.la
|
||||
libvulkan_common_la_SOURCES = $(VULKAN_SOURCES)
|
||||
|
||||
nodist_EXTRA_libvulkan_radeon_la_SOURCES = dummy.cpp
|
||||
libvulkan_radeon_la_SOURCES = $(VULKAN_GEM_FILES)
|
||||
|
||||
vulkan_api_xml = $(top_srcdir)/src/vulkan/registry/vk.xml
|
||||
|
||||
tu_entrypoints.c: tu_entrypoints_gen.py tu_extensions.py $(vulkan_api_xml)
|
||||
$(MKDIR_GEN)
|
||||
$(AM_V_GEN)$(PYTHON2) $(srcdir)/tu_entrypoints_gen.py \
|
||||
--xml $(vulkan_api_xml) \
|
||||
--outdir $(builddir)
|
||||
tu_entrypoints.h: tu_entrypoints.c
|
||||
|
||||
tu_extensions.c: tu_extensions.py \
|
||||
$(vulkan_api_xml)
|
||||
$(MKDIR_GEN)
|
||||
$(AM_V_GEN)$(PYTHON2) $(srcdir)/tu_extensions.py \
|
||||
--xml $(vulkan_api_xml) \
|
||||
--out-c tu_extensions.c \
|
||||
--out-h tu_extensions.h
|
||||
tu_extensions.h: tu_extensions.c
|
||||
|
||||
vk_format_table.c: vk_format_table.py \
|
||||
vk_format_parse.py \
|
||||
vk_format_layout.csv
|
||||
$(PYTHON2) $(srcdir)/vk_format_table.py $(srcdir)/vk_format_layout.csv > $@
|
||||
|
||||
BUILT_SOURCES = $(VULKAN_GENERATED_FILES)
|
||||
CLEANFILES = $(BUILT_SOURCES) dev_icd.json radeon_icd.@host_cpu@.json
|
||||
EXTRA_DIST = \
|
||||
$(top_srcdir)/include/vulkan/vk_icd.h \
|
||||
tu_entrypoints_gen.py \
|
||||
tu_extensions.py \
|
||||
tu_icd.py \
|
||||
vk_format_layout.csv \
|
||||
vk_format_parse.py \
|
||||
vk_format_table.py \
|
||||
meson.build
|
||||
|
||||
libvulkan_radeon_la_LIBADD = $(VULKAN_LIB_DEPS)
|
||||
|
||||
libvulkan_radeon_la_LDFLAGS = \
|
||||
-shared \
|
||||
-module \
|
||||
-no-undefined \
|
||||
-avoid-version \
|
||||
$(BSYMBOLIC) \
|
||||
$(LLVM_LDFLAGS) \
|
||||
$(GC_SECTIONS) \
|
||||
$(LD_NO_UNDEFINED)
|
||||
|
||||
|
||||
icdconfdir = @VULKAN_ICD_INSTALL_DIR@
|
||||
icdconf_DATA = radeon_icd.@host_cpu@.json
|
||||
# The following is used for development purposes, by setting VK_ICD_FILENAMES.
|
||||
noinst_DATA = dev_icd.json
|
||||
|
||||
dev_icd.json : tu_extensions.py tu_icd.py
|
||||
$(AM_V_GEN)$(PYTHON2) $(srcdir)/tu_icd.py \
|
||||
--lib-path="${abs_top_builddir}/${LIB_DIR}" --out $@
|
||||
|
||||
radeon_icd.@host_cpu@.json : tu_extensions.py tu_icd.py
|
||||
$(AM_V_GEN)$(PYTHON2) $(srcdir)/tu_icd.py \
|
||||
--lib-path="${libdir}" --out $@
|
||||
|
||||
include $(top_srcdir)/install-lib-links.mk
|
|
@ -0,0 +1,93 @@
|
|||
# Copyright © 2016 Red Hat
|
||||
#
|
||||
# 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.
|
||||
|
||||
TU_WS_AMDGPU_FILES := \
|
||||
winsys/amdgpu/tu_amdgpu_bo.c \
|
||||
winsys/amdgpu/tu_amdgpu_bo.h \
|
||||
winsys/amdgpu/tu_amdgpu_cs.c \
|
||||
winsys/amdgpu/tu_amdgpu_cs.h \
|
||||
winsys/amdgpu/tu_amdgpu_surface.c \
|
||||
winsys/amdgpu/tu_amdgpu_surface.h \
|
||||
winsys/amdgpu/tu_amdgpu_winsys.c \
|
||||
winsys/amdgpu/tu_amdgpu_winsys.h \
|
||||
winsys/amdgpu/tu_amdgpu_winsys_public.h
|
||||
|
||||
VULKAN_FILES := \
|
||||
tu_cmd_buffer.c \
|
||||
tu_cs.h \
|
||||
tu_debug.c \
|
||||
tu_debug.h \
|
||||
tu_device.c \
|
||||
tu_descriptor_set.c \
|
||||
tu_descriptor_set.h \
|
||||
tu_formats.c \
|
||||
tu_image.c \
|
||||
tu_meta.c \
|
||||
tu_meta.h \
|
||||
tu_meta_blit.c \
|
||||
tu_meta_blit2d.c \
|
||||
tu_meta_buffer.c \
|
||||
tu_meta_bufimage.c \
|
||||
tu_meta_clear.c \
|
||||
tu_meta_copy.c \
|
||||
tu_meta_decompress.c \
|
||||
tu_meta_fast_clear.c \
|
||||
tu_meta_resolve.c \
|
||||
tu_meta_resolve_cs.c \
|
||||
tu_meta_resolve_fs.c \
|
||||
tu_nir_to_llvm.c \
|
||||
tu_llvm_helper.cpp \
|
||||
tu_pass.c \
|
||||
tu_pipeline.c \
|
||||
tu_pipeline_cache.c \
|
||||
tu_private.h \
|
||||
tu_radeon_winsys.h \
|
||||
tu_shader.c \
|
||||
tu_shader_info.c \
|
||||
tu_shader.h \
|
||||
tu_shader_helper.h \
|
||||
tu_query.c \
|
||||
tu_util.c \
|
||||
tu_util.h \
|
||||
tu_wsi.c \
|
||||
si_cmd_buffer.c \
|
||||
vk_format.h \
|
||||
$(TU_WS_AMDGPU_FILES)
|
||||
|
||||
VULKAN_ANDROID_FILES := \
|
||||
tu_android.c
|
||||
|
||||
VULKAN_WSI_WAYLAND_FILES := \
|
||||
tu_wsi_wayland.c
|
||||
|
||||
VULKAN_WSI_X11_FILES := \
|
||||
tu_wsi_x11.c
|
||||
|
||||
VULKAN_WSI_DISPLAY_FILES := \
|
||||
tu_wsi_display.c
|
||||
|
||||
VULKAN_GENERATED_FILES := \
|
||||
tu_entrypoints.c \
|
||||
tu_entrypoints.h \
|
||||
tu_extensions.c \
|
||||
tu_extensions.h \
|
||||
vk_format_table.c
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
# Copyright © 2017 Intel Corporation
|
||||
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
tu_entrypoints = custom_target(
|
||||
'tu_entrypoints.[ch]',
|
||||
input : ['tu_entrypoints_gen.py', vk_api_xml],
|
||||
output : ['tu_entrypoints.h', 'tu_entrypoints.c'],
|
||||
command : [
|
||||
prog_python, '@INPUT0@', '--xml', '@INPUT1@', '--outdir',
|
||||
meson.current_build_dir()
|
||||
],
|
||||
depend_files : files('tu_extensions.py'),
|
||||
)
|
||||
|
||||
tu_extensions_c = custom_target(
|
||||
'tu_extensions.c',
|
||||
input : ['tu_extensions.py', vk_api_xml],
|
||||
output : ['tu_extensions.c', 'tu_extensions.h'],
|
||||
command : [
|
||||
prog_python, '@INPUT0@', '--xml', '@INPUT1@', '--out-c', '@OUTPUT0@',
|
||||
'--out-h', '@OUTPUT1@'
|
||||
],
|
||||
)
|
||||
|
||||
vk_format_table_c = custom_target(
|
||||
'vk_format_table.c',
|
||||
input : ['vk_format_table.py', 'vk_format_layout.csv'],
|
||||
output : 'vk_format_table.c',
|
||||
command : [prog_python, '@INPUT@'],
|
||||
depend_files : files('vk_format_parse.py'),
|
||||
capture : true,
|
||||
)
|
||||
|
||||
libtu_files = files(
|
||||
'tu_cmd_buffer.c',
|
||||
'tu_device.c',
|
||||
'tu_descriptor_set.c',
|
||||
'tu_descriptor_set.h',
|
||||
'tu_formats.c',
|
||||
'tu_image.c',
|
||||
'tu_meta_blit.c',
|
||||
'tu_meta_buffer.c',
|
||||
'tu_meta_clear.c',
|
||||
'tu_meta_copy.c',
|
||||
'tu_meta_resolve.c',
|
||||
'tu_pass.c',
|
||||
'tu_pipeline.c',
|
||||
'tu_pipeline_cache.c',
|
||||
'tu_private.h',
|
||||
'tu_query.c',
|
||||
'tu_util.c',
|
||||
'tu_util.h',
|
||||
'vk_format.h',
|
||||
)
|
||||
|
||||
tu_deps = []
|
||||
tu_flags = []
|
||||
|
||||
libvulkan_freedreno = shared_library(
|
||||
'vulkan_freedreno',
|
||||
[libtu_files, tu_entrypoints, tu_extensions_c, vk_format_table_c],
|
||||
include_directories : [
|
||||
inc_common, inc_compiler, inc_vulkan_util,
|
||||
],
|
||||
link_with : [
|
||||
libvulkan_util,
|
||||
libmesa_util,
|
||||
],
|
||||
dependencies : [
|
||||
dep_dl,
|
||||
dep_elf,
|
||||
dep_libdrm,
|
||||
dep_llvm,
|
||||
dep_m,
|
||||
dep_thread,
|
||||
dep_valgrind,
|
||||
idep_nir,
|
||||
],
|
||||
c_args : [c_vis_args, no_override_init_args, tu_flags],
|
||||
link_args : [ld_args_bsymbolic, ld_args_gc_sections],
|
||||
install : true,
|
||||
)
|
||||
|
||||
freedreno_icd = custom_target(
|
||||
'freedreno_icd',
|
||||
input : 'tu_icd.py',
|
||||
output : 'freedreno_icd.@0@.json'.format(host_machine.cpu()),
|
||||
command : [
|
||||
prog_python, '@INPUT@',
|
||||
'--lib-path', join_paths(get_option('prefix'), get_option('libdir')),
|
||||
'--out', '@OUTPUT@',
|
||||
],
|
||||
depend_files : files('tu_extensions.py'),
|
||||
build_by_default : true,
|
||||
install_dir : with_vulkan_icd_dir,
|
||||
install : true,
|
||||
)
|
||||
|
||||
tu_dev_icd = custom_target(
|
||||
'tu_dev_icd',
|
||||
input : 'tu_icd.py',
|
||||
output : 'dev_icd.json',
|
||||
command : [
|
||||
prog_python, '@INPUT@', '--lib-path', meson.current_build_dir(),
|
||||
'--out', '@OUTPUT@'
|
||||
],
|
||||
depend_files : files('tu_extensions.py'),
|
||||
build_by_default : true,
|
||||
install : false,
|
||||
)
|
|
@ -0,0 +1,390 @@
|
|||
/*
|
||||
* Copyright © 2017, Google Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <hardware/gralloc.h>
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/hwvulkan.h>
|
||||
#include <libsync.h>
|
||||
#include <vulkan/vk_android_native_buffer.h>
|
||||
#include <vulkan/vk_icd.h>
|
||||
|
||||
#include "tu_private.h"
|
||||
|
||||
static int
|
||||
tu_hal_open(const struct hw_module_t *mod,
|
||||
const char *id,
|
||||
struct hw_device_t **dev);
|
||||
static int
|
||||
tu_hal_close(struct hw_device_t *dev);
|
||||
|
||||
static void UNUSED
|
||||
static_asserts(void)
|
||||
{
|
||||
STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC);
|
||||
}
|
||||
|
||||
PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {
|
||||
.common =
|
||||
{
|
||||
.tag = HARDWARE_MODULE_TAG,
|
||||
.module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
|
||||
.hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0),
|
||||
.id = HWVULKAN_HARDWARE_MODULE_ID,
|
||||
.name = "AMD Vulkan HAL",
|
||||
.author = "Google",
|
||||
.methods =
|
||||
&(hw_module_methods_t){
|
||||
.open = tu_hal_open,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/* If any bits in test_mask are set, then unset them and return true. */
|
||||
static inline bool
|
||||
unmask32(uint32_t *inout_mask, uint32_t test_mask)
|
||||
{
|
||||
uint32_t orig_mask = *inout_mask;
|
||||
*inout_mask &= ~test_mask;
|
||||
return *inout_mask != orig_mask;
|
||||
}
|
||||
|
||||
static int
|
||||
tu_hal_open(const struct hw_module_t *mod,
|
||||
const char *id,
|
||||
struct hw_device_t **dev)
|
||||
{
|
||||
assert(mod == &HAL_MODULE_INFO_SYM.common);
|
||||
assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
|
||||
|
||||
hwvulkan_device_t *hal_dev = malloc(sizeof(*hal_dev));
|
||||
if (!hal_dev)
|
||||
return -1;
|
||||
|
||||
*hal_dev = (hwvulkan_device_t){
|
||||
.common =
|
||||
{
|
||||
.tag = HARDWARE_DEVICE_TAG,
|
||||
.version = HWVULKAN_DEVICE_API_VERSION_0_1,
|
||||
.module = &HAL_MODULE_INFO_SYM.common,
|
||||
.close = tu_hal_close,
|
||||
},
|
||||
.EnumerateInstanceExtensionProperties =
|
||||
tu_EnumerateInstanceExtensionProperties,
|
||||
.CreateInstance = tu_CreateInstance,
|
||||
.GetInstanceProcAddr = tu_GetInstanceProcAddr,
|
||||
};
|
||||
|
||||
*dev = &hal_dev->common;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tu_hal_close(struct hw_device_t *dev)
|
||||
{
|
||||
/* hwvulkan.h claims that hw_device_t::close() is never called. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_image_from_gralloc(VkDevice device_h,
|
||||
const VkImageCreateInfo *base_info,
|
||||
const VkNativeBufferANDROID *gralloc_info,
|
||||
const VkAllocationCallbacks *alloc,
|
||||
VkImage *out_image_h)
|
||||
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, device_h);
|
||||
VkImage image_h = VK_NULL_HANDLE;
|
||||
struct tu_image *image = NULL;
|
||||
struct tu_bo *bo = NULL;
|
||||
VkResult result;
|
||||
|
||||
result = tu_image_create(
|
||||
device_h,
|
||||
&(struct tu_image_create_info){
|
||||
.vk_info = base_info, .scanout = true, .no_metadata_planes = true },
|
||||
alloc,
|
||||
&image_h);
|
||||
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
if (gralloc_info->handle->numFds != 1) {
|
||||
return vk_errorf(device->instance,
|
||||
VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR,
|
||||
"VkNativeBufferANDROID::handle::numFds is %d, "
|
||||
"expected 1",
|
||||
gralloc_info->handle->numFds);
|
||||
}
|
||||
|
||||
/* Do not close the gralloc handle's dma_buf. The lifetime of the dma_buf
|
||||
* must exceed that of the gralloc handle, and we do not own the gralloc
|
||||
* handle.
|
||||
*/
|
||||
int dma_buf = gralloc_info->handle->data[0];
|
||||
|
||||
image = tu_image_from_handle(image_h);
|
||||
|
||||
VkDeviceMemory memory_h;
|
||||
|
||||
const VkMemoryDedicatedAllocateInfoKHR ded_alloc = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
|
||||
.pNext = NULL,
|
||||
.buffer = VK_NULL_HANDLE,
|
||||
.image = image_h
|
||||
};
|
||||
|
||||
const VkImportMemoryFdInfoKHR import_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
|
||||
.pNext = &ded_alloc,
|
||||
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
|
||||
.fd = dup(dma_buf),
|
||||
};
|
||||
/* Find the first VRAM memory type, or GART for PRIME images. */
|
||||
int memory_type_index = -1;
|
||||
for (int i = 0;
|
||||
i < device->physical_device->memory_properties.memoryTypeCount;
|
||||
++i) {
|
||||
bool is_local =
|
||||
!!(device->physical_device->memory_properties.memoryTypes[i]
|
||||
.propertyFlags &
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
if (is_local) {
|
||||
memory_type_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* fallback */
|
||||
if (memory_type_index == -1)
|
||||
memory_type_index = 0;
|
||||
|
||||
result =
|
||||
tu_AllocateMemory(device_h,
|
||||
&(VkMemoryAllocateInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.pNext = &import_info,
|
||||
.allocationSize = image->size,
|
||||
.memoryTypeIndex = memory_type_index,
|
||||
},
|
||||
alloc,
|
||||
&memory_h);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail_create_image;
|
||||
|
||||
tu_BindImageMemory(device_h, image_h, memory_h, 0);
|
||||
|
||||
image->owned_memory = memory_h;
|
||||
/* Don't clobber the out-parameter until success is certain. */
|
||||
*out_image_h = image_h;
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
fail_create_image:
|
||||
fail_size:
|
||||
tu_DestroyImage(device_h, image_h, alloc);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_GetSwapchainGrallocUsageANDROID(VkDevice device_h,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags imageUsage,
|
||||
int *grallocUsage)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, device_h);
|
||||
struct tu_physical_device *phys_dev = device->physical_device;
|
||||
VkPhysicalDevice phys_dev_h = tu_physical_device_to_handle(phys_dev);
|
||||
VkResult result;
|
||||
|
||||
*grallocUsage = 0;
|
||||
|
||||
/* WARNING: Android Nougat's libvulkan.so hardcodes the VkImageUsageFlags
|
||||
* returned to applications via
|
||||
* VkSurfaceCapabilitiesKHR::supportedUsageFlags.
|
||||
* The relevant code in libvulkan/swapchain.cpp contains this fun comment:
|
||||
*
|
||||
* TODO(jessehall): I think these are right, but haven't thought hard
|
||||
* about it. Do we need to query the driver for support of any of
|
||||
* these?
|
||||
*
|
||||
* Any disagreement between this function and the hardcoded
|
||||
* VkSurfaceCapabilitiesKHR:supportedUsageFlags causes tests
|
||||
* dEQP-VK.wsi.android.swapchain.*.image_usage to fail.
|
||||
*/
|
||||
|
||||
const VkPhysicalDeviceImageFormatInfo2KHR image_format_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
|
||||
.format = format,
|
||||
.type = VK_IMAGE_TYPE_2D,
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||
.usage = imageUsage,
|
||||
};
|
||||
|
||||
VkImageFormatProperties2KHR image_format_props = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
|
||||
};
|
||||
|
||||
/* Check that requested format and usage are supported. */
|
||||
result = tu_GetPhysicalDeviceImageFormatProperties2(
|
||||
phys_dev_h, &image_format_info, &image_format_props);
|
||||
if (result != VK_SUCCESS) {
|
||||
return vk_errorf(device->instance,
|
||||
result,
|
||||
"tu_GetPhysicalDeviceImageFormatProperties2 failed "
|
||||
"inside %s",
|
||||
__func__);
|
||||
}
|
||||
|
||||
if (unmask32(&imageUsage,
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
|
||||
*grallocUsage |= GRALLOC_USAGE_HW_RENDER;
|
||||
|
||||
if (unmask32(&imageUsage,
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_STORAGE_BIT |
|
||||
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
|
||||
*grallocUsage |= GRALLOC_USAGE_HW_TEXTURE;
|
||||
|
||||
/* All VkImageUsageFlags not explicitly checked here are unsupported for
|
||||
* gralloc swapchains.
|
||||
*/
|
||||
if (imageUsage != 0) {
|
||||
return vk_errorf(device->instance,
|
||||
VK_ERROR_FORMAT_NOT_SUPPORTED,
|
||||
"unsupported VkImageUsageFlags(0x%x) for gralloc "
|
||||
"swapchain",
|
||||
imageUsage);
|
||||
}
|
||||
|
||||
/*
|
||||
* FINISHME: Advertise all display-supported formats. Mostly
|
||||
* DRM_FORMAT_ARGB2101010 and DRM_FORMAT_ABGR2101010, but need to check
|
||||
* what we need for 30-bit colors.
|
||||
*/
|
||||
if (format == VK_FORMAT_B8G8R8A8_UNORM ||
|
||||
format == VK_FORMAT_B5G6R5_UNORM_PACK16) {
|
||||
*grallocUsage |= GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER |
|
||||
GRALLOC_USAGE_EXTERNAL_DISP;
|
||||
}
|
||||
|
||||
if (*grallocUsage == 0)
|
||||
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_AcquireImageANDROID(VkDevice device,
|
||||
VkImage image_h,
|
||||
int nativeFenceFd,
|
||||
VkSemaphore semaphore,
|
||||
VkFence fence)
|
||||
{
|
||||
VkResult semaphore_result = VK_SUCCESS, fence_result = VK_SUCCESS;
|
||||
|
||||
if (semaphore != VK_NULL_HANDLE) {
|
||||
int semaphore_fd =
|
||||
nativeFenceFd >= 0 ? dup(nativeFenceFd) : nativeFenceFd;
|
||||
semaphore_result = tu_ImportSemaphoreFdKHR(
|
||||
device,
|
||||
&(VkImportSemaphoreFdInfoKHR){
|
||||
.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
|
||||
.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR,
|
||||
.fd = semaphore_fd,
|
||||
.semaphore = semaphore,
|
||||
});
|
||||
}
|
||||
|
||||
if (fence != VK_NULL_HANDLE) {
|
||||
int fence_fd = nativeFenceFd >= 0 ? dup(nativeFenceFd) : nativeFenceFd;
|
||||
fence_result = tu_ImportFenceFdKHR(
|
||||
device,
|
||||
&(VkImportFenceFdInfoKHR){
|
||||
.sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
|
||||
.flags = VK_FENCE_IMPORT_TEMPORARY_BIT_KHR,
|
||||
.fd = fence_fd,
|
||||
.fence = fence,
|
||||
});
|
||||
}
|
||||
|
||||
close(nativeFenceFd);
|
||||
|
||||
if (semaphore_result != VK_SUCCESS)
|
||||
return semaphore_result;
|
||||
return fence_result;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_QueueSignalReleaseImageANDROID(VkQueue _queue,
|
||||
uint32_t waitSemaphoreCount,
|
||||
const VkSemaphore *pWaitSemaphores,
|
||||
VkImage image,
|
||||
int *pNativeFenceFd)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_queue, queue, _queue);
|
||||
VkResult result = VK_SUCCESS;
|
||||
|
||||
if (waitSemaphoreCount == 0) {
|
||||
if (pNativeFenceFd)
|
||||
*pNativeFenceFd = -1;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
int fd = -1;
|
||||
|
||||
for (uint32_t i = 0; i < waitSemaphoreCount; ++i) {
|
||||
int tmp_fd;
|
||||
result = tu_GetSemaphoreFdKHR(
|
||||
tu_device_to_handle(queue->device),
|
||||
&(VkSemaphoreGetFdInfoKHR){
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
|
||||
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR,
|
||||
.semaphore = pWaitSemaphores[i],
|
||||
},
|
||||
&tmp_fd);
|
||||
if (result != VK_SUCCESS) {
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (fd < 0)
|
||||
fd = tmp_fd;
|
||||
else if (tmp_fd >= 0) {
|
||||
sync_accumulate("tu", &fd, tmp_fd);
|
||||
close(tmp_fd);
|
||||
}
|
||||
}
|
||||
|
||||
if (pNativeFenceFd) {
|
||||
*pNativeFenceFd = fd;
|
||||
} else if (fd >= 0) {
|
||||
close(fd);
|
||||
/* We still need to do the exports, to reset the semaphores, but
|
||||
* otherwise we don't wait on them. */
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,936 @@
|
|||
/*
|
||||
* Copyright © 2016 Red Hat.
|
||||
* Copyright © 2016 Bas Nieuwenhuizen
|
||||
*
|
||||
* based in part on anv driver which is:
|
||||
* 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 "tu_private.h"
|
||||
#include "vk_format.h"
|
||||
|
||||
const struct tu_dynamic_state default_dynamic_state = {
|
||||
.viewport =
|
||||
{
|
||||
.count = 0,
|
||||
},
|
||||
.scissor =
|
||||
{
|
||||
.count = 0,
|
||||
},
|
||||
.line_width = 1.0f,
|
||||
.depth_bias =
|
||||
{
|
||||
.bias = 0.0f,
|
||||
.clamp = 0.0f,
|
||||
.slope = 0.0f,
|
||||
},
|
||||
.blend_constants = { 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
.depth_bounds =
|
||||
{
|
||||
.min = 0.0f,
|
||||
.max = 1.0f,
|
||||
},
|
||||
.stencil_compare_mask =
|
||||
{
|
||||
.front = ~0u,
|
||||
.back = ~0u,
|
||||
},
|
||||
.stencil_write_mask =
|
||||
{
|
||||
.front = ~0u,
|
||||
.back = ~0u,
|
||||
},
|
||||
.stencil_reference =
|
||||
{
|
||||
.front = 0u,
|
||||
.back = 0u,
|
||||
},
|
||||
};
|
||||
|
||||
static void
|
||||
tu_bind_dynamic_state(struct tu_cmd_buffer *cmd_buffer,
|
||||
const struct tu_dynamic_state *src)
|
||||
{
|
||||
struct tu_dynamic_state *dest = &cmd_buffer->state.dynamic;
|
||||
uint32_t copy_mask = src->mask;
|
||||
uint32_t dest_mask = 0;
|
||||
|
||||
/* Make sure to copy the number of viewports/scissors because they can
|
||||
* only be specified at pipeline creation time.
|
||||
*/
|
||||
dest->viewport.count = src->viewport.count;
|
||||
dest->scissor.count = src->scissor.count;
|
||||
dest->discard_rectangle.count = src->discard_rectangle.count;
|
||||
|
||||
if (copy_mask & TU_DYNAMIC_VIEWPORT) {
|
||||
if (memcmp(&dest->viewport.viewports,
|
||||
&src->viewport.viewports,
|
||||
src->viewport.count * sizeof(VkViewport))) {
|
||||
typed_memcpy(dest->viewport.viewports,
|
||||
src->viewport.viewports,
|
||||
src->viewport.count);
|
||||
dest_mask |= TU_DYNAMIC_VIEWPORT;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_mask & TU_DYNAMIC_SCISSOR) {
|
||||
if (memcmp(&dest->scissor.scissors,
|
||||
&src->scissor.scissors,
|
||||
src->scissor.count * sizeof(VkRect2D))) {
|
||||
typed_memcpy(
|
||||
dest->scissor.scissors, src->scissor.scissors, src->scissor.count);
|
||||
dest_mask |= TU_DYNAMIC_SCISSOR;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_mask & TU_DYNAMIC_LINE_WIDTH) {
|
||||
if (dest->line_width != src->line_width) {
|
||||
dest->line_width = src->line_width;
|
||||
dest_mask |= TU_DYNAMIC_LINE_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_mask & TU_DYNAMIC_DEPTH_BIAS) {
|
||||
if (memcmp(
|
||||
&dest->depth_bias, &src->depth_bias, sizeof(src->depth_bias))) {
|
||||
dest->depth_bias = src->depth_bias;
|
||||
dest_mask |= TU_DYNAMIC_DEPTH_BIAS;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_mask & TU_DYNAMIC_BLEND_CONSTANTS) {
|
||||
if (memcmp(&dest->blend_constants,
|
||||
&src->blend_constants,
|
||||
sizeof(src->blend_constants))) {
|
||||
typed_memcpy(dest->blend_constants, src->blend_constants, 4);
|
||||
dest_mask |= TU_DYNAMIC_BLEND_CONSTANTS;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_mask & TU_DYNAMIC_DEPTH_BOUNDS) {
|
||||
if (memcmp(&dest->depth_bounds,
|
||||
&src->depth_bounds,
|
||||
sizeof(src->depth_bounds))) {
|
||||
dest->depth_bounds = src->depth_bounds;
|
||||
dest_mask |= TU_DYNAMIC_DEPTH_BOUNDS;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_mask & TU_DYNAMIC_STENCIL_COMPARE_MASK) {
|
||||
if (memcmp(&dest->stencil_compare_mask,
|
||||
&src->stencil_compare_mask,
|
||||
sizeof(src->stencil_compare_mask))) {
|
||||
dest->stencil_compare_mask = src->stencil_compare_mask;
|
||||
dest_mask |= TU_DYNAMIC_STENCIL_COMPARE_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_mask & TU_DYNAMIC_STENCIL_WRITE_MASK) {
|
||||
if (memcmp(&dest->stencil_write_mask,
|
||||
&src->stencil_write_mask,
|
||||
sizeof(src->stencil_write_mask))) {
|
||||
dest->stencil_write_mask = src->stencil_write_mask;
|
||||
dest_mask |= TU_DYNAMIC_STENCIL_WRITE_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_mask & TU_DYNAMIC_STENCIL_REFERENCE) {
|
||||
if (memcmp(&dest->stencil_reference,
|
||||
&src->stencil_reference,
|
||||
sizeof(src->stencil_reference))) {
|
||||
dest->stencil_reference = src->stencil_reference;
|
||||
dest_mask |= TU_DYNAMIC_STENCIL_REFERENCE;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_mask & TU_DYNAMIC_DISCARD_RECTANGLE) {
|
||||
if (memcmp(&dest->discard_rectangle.rectangles,
|
||||
&src->discard_rectangle.rectangles,
|
||||
src->discard_rectangle.count * sizeof(VkRect2D))) {
|
||||
typed_memcpy(dest->discard_rectangle.rectangles,
|
||||
src->discard_rectangle.rectangles,
|
||||
src->discard_rectangle.count);
|
||||
dest_mask |= TU_DYNAMIC_DISCARD_RECTANGLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VkResult
|
||||
tu_create_cmd_buffer(struct tu_device *device,
|
||||
struct tu_cmd_pool *pool,
|
||||
VkCommandBufferLevel level,
|
||||
VkCommandBuffer *pCommandBuffer)
|
||||
{
|
||||
struct tu_cmd_buffer *cmd_buffer;
|
||||
cmd_buffer = vk_zalloc(
|
||||
&pool->alloc, sizeof(*cmd_buffer), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (cmd_buffer == NULL)
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
cmd_buffer->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
|
||||
cmd_buffer->device = device;
|
||||
cmd_buffer->pool = pool;
|
||||
cmd_buffer->level = level;
|
||||
|
||||
if (pool) {
|
||||
list_addtail(&cmd_buffer->pool_link, &pool->cmd_buffers);
|
||||
cmd_buffer->queue_family_index = pool->queue_family_index;
|
||||
|
||||
} else {
|
||||
/* Init the pool_link so we can safely call list_del when we destroy
|
||||
* the command buffer
|
||||
*/
|
||||
list_inithead(&cmd_buffer->pool_link);
|
||||
cmd_buffer->queue_family_index = TU_QUEUE_GENERAL;
|
||||
}
|
||||
|
||||
*pCommandBuffer = tu_cmd_buffer_to_handle(cmd_buffer);
|
||||
|
||||
list_inithead(&cmd_buffer->upload.list);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
tu_cmd_buffer_destroy(struct tu_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
list_del(&cmd_buffer->pool_link);
|
||||
|
||||
for (unsigned i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; i++)
|
||||
free(cmd_buffer->descriptors[i].push_set.set.mapped_ptr);
|
||||
|
||||
vk_free(&cmd_buffer->pool->alloc, cmd_buffer);
|
||||
}
|
||||
|
||||
static VkResult
|
||||
tu_reset_cmd_buffer(struct tu_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
cmd_buffer->record_result = VK_SUCCESS;
|
||||
|
||||
for (unsigned i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; i++) {
|
||||
cmd_buffer->descriptors[i].dirty = 0;
|
||||
cmd_buffer->descriptors[i].valid = 0;
|
||||
cmd_buffer->descriptors[i].push_dirty = false;
|
||||
}
|
||||
|
||||
cmd_buffer->status = TU_CMD_BUFFER_STATUS_INITIAL;
|
||||
|
||||
return cmd_buffer->record_result;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_AllocateCommandBuffers(VkDevice _device,
|
||||
const VkCommandBufferAllocateInfo *pAllocateInfo,
|
||||
VkCommandBuffer *pCommandBuffers)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_cmd_pool, pool, pAllocateInfo->commandPool);
|
||||
|
||||
VkResult result = VK_SUCCESS;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < pAllocateInfo->commandBufferCount; i++) {
|
||||
|
||||
if (!list_empty(&pool->free_cmd_buffers)) {
|
||||
struct tu_cmd_buffer *cmd_buffer = list_first_entry(
|
||||
&pool->free_cmd_buffers, struct tu_cmd_buffer, pool_link);
|
||||
|
||||
list_del(&cmd_buffer->pool_link);
|
||||
list_addtail(&cmd_buffer->pool_link, &pool->cmd_buffers);
|
||||
|
||||
result = tu_reset_cmd_buffer(cmd_buffer);
|
||||
cmd_buffer->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
|
||||
cmd_buffer->level = pAllocateInfo->level;
|
||||
|
||||
pCommandBuffers[i] = tu_cmd_buffer_to_handle(cmd_buffer);
|
||||
} else {
|
||||
result = tu_create_cmd_buffer(
|
||||
device, pool, pAllocateInfo->level, &pCommandBuffers[i]);
|
||||
}
|
||||
if (result != VK_SUCCESS)
|
||||
break;
|
||||
}
|
||||
|
||||
if (result != VK_SUCCESS) {
|
||||
tu_FreeCommandBuffers(
|
||||
_device, pAllocateInfo->commandPool, i, pCommandBuffers);
|
||||
|
||||
/* From the Vulkan 1.0.66 spec:
|
||||
*
|
||||
* "vkAllocateCommandBuffers can be used to create multiple
|
||||
* command buffers. If the creation of any of those command
|
||||
* buffers fails, the implementation must destroy all
|
||||
* successfully created command buffer objects from this
|
||||
* command, set all entries of the pCommandBuffers array to
|
||||
* NULL and return the error."
|
||||
*/
|
||||
memset(pCommandBuffers,
|
||||
0,
|
||||
sizeof(*pCommandBuffers) * pAllocateInfo->commandBufferCount);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
tu_FreeCommandBuffers(VkDevice device,
|
||||
VkCommandPool commandPool,
|
||||
uint32_t commandBufferCount,
|
||||
const VkCommandBuffer *pCommandBuffers)
|
||||
{
|
||||
for (uint32_t i = 0; i < commandBufferCount; i++) {
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, pCommandBuffers[i]);
|
||||
|
||||
if (cmd_buffer) {
|
||||
if (cmd_buffer->pool) {
|
||||
list_del(&cmd_buffer->pool_link);
|
||||
list_addtail(&cmd_buffer->pool_link,
|
||||
&cmd_buffer->pool->free_cmd_buffers);
|
||||
} else
|
||||
tu_cmd_buffer_destroy(cmd_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_ResetCommandBuffer(VkCommandBuffer commandBuffer,
|
||||
VkCommandBufferResetFlags flags)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
return tu_reset_cmd_buffer(cmd_buffer);
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_BeginCommandBuffer(VkCommandBuffer commandBuffer,
|
||||
const VkCommandBufferBeginInfo *pBeginInfo)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
VkResult result = VK_SUCCESS;
|
||||
|
||||
if (cmd_buffer->status != TU_CMD_BUFFER_STATUS_INITIAL) {
|
||||
/* If the command buffer has already been resetted with
|
||||
* vkResetCommandBuffer, no need to do it again.
|
||||
*/
|
||||
result = tu_reset_cmd_buffer(cmd_buffer);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
|
||||
memset(&cmd_buffer->state, 0, sizeof(cmd_buffer->state));
|
||||
cmd_buffer->usage_flags = pBeginInfo->flags;
|
||||
|
||||
/* setup initial configuration into command buffer */
|
||||
if (cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
|
||||
switch (cmd_buffer->queue_family_index) {
|
||||
case TU_QUEUE_GENERAL:
|
||||
/* init */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cmd_buffer->status = TU_CMD_BUFFER_STATUS_RECORDING;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,
|
||||
uint32_t firstBinding,
|
||||
uint32_t bindingCount,
|
||||
const VkBuffer *pBuffers,
|
||||
const VkDeviceSize *pOffsets)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,
|
||||
VkBuffer buffer,
|
||||
VkDeviceSize offset,
|
||||
VkIndexType indexType)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
|
||||
VkPipelineBindPoint pipelineBindPoint,
|
||||
VkPipelineLayout _layout,
|
||||
uint32_t firstSet,
|
||||
uint32_t descriptorSetCount,
|
||||
const VkDescriptorSet *pDescriptorSets,
|
||||
uint32_t dynamicOffsetCount,
|
||||
const uint32_t *pDynamicOffsets)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdPushConstants(VkCommandBuffer commandBuffer,
|
||||
VkPipelineLayout layout,
|
||||
VkShaderStageFlags stageFlags,
|
||||
uint32_t offset,
|
||||
uint32_t size,
|
||||
const void *pValues)
|
||||
{
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_EndCommandBuffer(VkCommandBuffer commandBuffer)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
|
||||
cmd_buffer->status = TU_CMD_BUFFER_STATUS_EXECUTABLE;
|
||||
|
||||
return cmd_buffer->record_result;
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdBindPipeline(VkCommandBuffer commandBuffer,
|
||||
VkPipelineBindPoint pipelineBindPoint,
|
||||
VkPipeline _pipeline)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdSetViewport(VkCommandBuffer commandBuffer,
|
||||
uint32_t firstViewport,
|
||||
uint32_t viewportCount,
|
||||
const VkViewport *pViewports)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdSetScissor(VkCommandBuffer commandBuffer,
|
||||
uint32_t firstScissor,
|
||||
uint32_t scissorCount,
|
||||
const VkRect2D *pScissors)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdSetDepthBias(VkCommandBuffer commandBuffer,
|
||||
float depthBiasConstantFactor,
|
||||
float depthBiasClamp,
|
||||
float depthBiasSlopeFactor)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdSetBlendConstants(VkCommandBuffer commandBuffer,
|
||||
const float blendConstants[4])
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdSetDepthBounds(VkCommandBuffer commandBuffer,
|
||||
float minDepthBounds,
|
||||
float maxDepthBounds)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer,
|
||||
VkStencilFaceFlags faceMask,
|
||||
uint32_t compareMask)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer,
|
||||
VkStencilFaceFlags faceMask,
|
||||
uint32_t writeMask)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdSetStencilReference(VkCommandBuffer commandBuffer,
|
||||
VkStencilFaceFlags faceMask,
|
||||
uint32_t reference)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdExecuteCommands(VkCommandBuffer commandBuffer,
|
||||
uint32_t commandBufferCount,
|
||||
const VkCommandBuffer *pCmdBuffers)
|
||||
{
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_CreateCommandPool(VkDevice _device,
|
||||
const VkCommandPoolCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkCommandPool *pCmdPool)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
struct tu_cmd_pool *pool;
|
||||
|
||||
pool = vk_alloc2(&device->alloc,
|
||||
pAllocator,
|
||||
sizeof(*pool),
|
||||
8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (pool == NULL)
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
if (pAllocator)
|
||||
pool->alloc = *pAllocator;
|
||||
else
|
||||
pool->alloc = device->alloc;
|
||||
|
||||
list_inithead(&pool->cmd_buffers);
|
||||
list_inithead(&pool->free_cmd_buffers);
|
||||
|
||||
pool->queue_family_index = pCreateInfo->queueFamilyIndex;
|
||||
|
||||
*pCmdPool = tu_cmd_pool_to_handle(pool);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_DestroyCommandPool(VkDevice _device,
|
||||
VkCommandPool commandPool,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_cmd_pool, pool, commandPool);
|
||||
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(
|
||||
struct tu_cmd_buffer, cmd_buffer, &pool->cmd_buffers, pool_link)
|
||||
{
|
||||
tu_cmd_buffer_destroy(cmd_buffer);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(
|
||||
struct tu_cmd_buffer, cmd_buffer, &pool->free_cmd_buffers, pool_link)
|
||||
{
|
||||
tu_cmd_buffer_destroy(cmd_buffer);
|
||||
}
|
||||
|
||||
vk_free2(&device->alloc, pAllocator, pool);
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_ResetCommandPool(VkDevice device,
|
||||
VkCommandPool commandPool,
|
||||
VkCommandPoolResetFlags flags)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_pool, pool, commandPool);
|
||||
VkResult result;
|
||||
|
||||
list_for_each_entry(
|
||||
struct tu_cmd_buffer, cmd_buffer, &pool->cmd_buffers, pool_link)
|
||||
{
|
||||
result = tu_reset_cmd_buffer(cmd_buffer);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_TrimCommandPool(VkDevice device,
|
||||
VkCommandPool commandPool,
|
||||
VkCommandPoolTrimFlagsKHR flags)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_pool, pool, commandPool);
|
||||
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(
|
||||
struct tu_cmd_buffer, cmd_buffer, &pool->free_cmd_buffers, pool_link)
|
||||
{
|
||||
tu_cmd_buffer_destroy(cmd_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdBeginRenderPass(VkCommandBuffer commandBuffer,
|
||||
const VkRenderPassBeginInfo *pRenderPassBegin,
|
||||
VkSubpassContents contents)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer,
|
||||
const VkRenderPassBeginInfo *pRenderPassBeginInfo,
|
||||
const VkSubpassBeginInfoKHR *pSubpassBeginInfo)
|
||||
{
|
||||
tu_CmdBeginRenderPass(
|
||||
commandBuffer, pRenderPassBeginInfo, pSubpassBeginInfo->contents);
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdNextSubpass2KHR(VkCommandBuffer commandBuffer,
|
||||
const VkSubpassBeginInfoKHR *pSubpassBeginInfo,
|
||||
const VkSubpassEndInfoKHR *pSubpassEndInfo)
|
||||
{
|
||||
tu_CmdNextSubpass(commandBuffer, pSubpassBeginInfo->contents);
|
||||
}
|
||||
|
||||
struct tu_draw_info
|
||||
{
|
||||
/**
|
||||
* Number of vertices.
|
||||
*/
|
||||
uint32_t count;
|
||||
|
||||
/**
|
||||
* Index of the first vertex.
|
||||
*/
|
||||
int32_t vertex_offset;
|
||||
|
||||
/**
|
||||
* First instance id.
|
||||
*/
|
||||
uint32_t first_instance;
|
||||
|
||||
/**
|
||||
* Number of instances.
|
||||
*/
|
||||
uint32_t instance_count;
|
||||
|
||||
/**
|
||||
* First index (indexed draws only).
|
||||
*/
|
||||
uint32_t first_index;
|
||||
|
||||
/**
|
||||
* Whether it's an indexed draw.
|
||||
*/
|
||||
bool indexed;
|
||||
|
||||
/**
|
||||
* Indirect draw parameters resource.
|
||||
*/
|
||||
struct tu_buffer *indirect;
|
||||
uint64_t indirect_offset;
|
||||
uint32_t stride;
|
||||
|
||||
/**
|
||||
* Draw count parameters resource.
|
||||
*/
|
||||
struct tu_buffer *count_buffer;
|
||||
uint64_t count_buffer_offset;
|
||||
};
|
||||
|
||||
static void
|
||||
tu_draw(struct tu_cmd_buffer *cmd_buffer, const struct tu_draw_info *info)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdDraw(VkCommandBuffer commandBuffer,
|
||||
uint32_t vertexCount,
|
||||
uint32_t instanceCount,
|
||||
uint32_t firstVertex,
|
||||
uint32_t firstInstance)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
struct tu_draw_info info = {};
|
||||
|
||||
info.count = vertexCount;
|
||||
info.instance_count = instanceCount;
|
||||
info.first_instance = firstInstance;
|
||||
info.vertex_offset = firstVertex;
|
||||
|
||||
tu_draw(cmd_buffer, &info);
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdDrawIndexed(VkCommandBuffer commandBuffer,
|
||||
uint32_t indexCount,
|
||||
uint32_t instanceCount,
|
||||
uint32_t firstIndex,
|
||||
int32_t vertexOffset,
|
||||
uint32_t firstInstance)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
struct tu_draw_info info = {};
|
||||
|
||||
info.indexed = true;
|
||||
info.count = indexCount;
|
||||
info.instance_count = instanceCount;
|
||||
info.first_index = firstIndex;
|
||||
info.vertex_offset = vertexOffset;
|
||||
info.first_instance = firstInstance;
|
||||
|
||||
tu_draw(cmd_buffer, &info);
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdDrawIndirect(VkCommandBuffer commandBuffer,
|
||||
VkBuffer _buffer,
|
||||
VkDeviceSize offset,
|
||||
uint32_t drawCount,
|
||||
uint32_t stride)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
TU_FROM_HANDLE(tu_buffer, buffer, _buffer);
|
||||
struct tu_draw_info info = {};
|
||||
|
||||
info.count = drawCount;
|
||||
info.indirect = buffer;
|
||||
info.indirect_offset = offset;
|
||||
info.stride = stride;
|
||||
|
||||
tu_draw(cmd_buffer, &info);
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,
|
||||
VkBuffer _buffer,
|
||||
VkDeviceSize offset,
|
||||
uint32_t drawCount,
|
||||
uint32_t stride)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
TU_FROM_HANDLE(tu_buffer, buffer, _buffer);
|
||||
struct tu_draw_info info = {};
|
||||
|
||||
info.indexed = true;
|
||||
info.count = drawCount;
|
||||
info.indirect = buffer;
|
||||
info.indirect_offset = offset;
|
||||
info.stride = stride;
|
||||
|
||||
tu_draw(cmd_buffer, &info);
|
||||
}
|
||||
|
||||
struct tu_dispatch_info
|
||||
{
|
||||
/**
|
||||
* Determine the layout of the grid (in block units) to be used.
|
||||
*/
|
||||
uint32_t blocks[3];
|
||||
|
||||
/**
|
||||
* A starting offset for the grid. If unaligned is set, the offset
|
||||
* must still be aligned.
|
||||
*/
|
||||
uint32_t offsets[3];
|
||||
/**
|
||||
* Whether it's an unaligned compute dispatch.
|
||||
*/
|
||||
bool unaligned;
|
||||
|
||||
/**
|
||||
* Indirect compute parameters resource.
|
||||
*/
|
||||
struct tu_buffer *indirect;
|
||||
uint64_t indirect_offset;
|
||||
};
|
||||
|
||||
static void
|
||||
tu_dispatch(struct tu_cmd_buffer *cmd_buffer,
|
||||
const struct tu_dispatch_info *info)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdDispatchBase(VkCommandBuffer commandBuffer,
|
||||
uint32_t base_x,
|
||||
uint32_t base_y,
|
||||
uint32_t base_z,
|
||||
uint32_t x,
|
||||
uint32_t y,
|
||||
uint32_t z)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
struct tu_dispatch_info info = {};
|
||||
|
||||
info.blocks[0] = x;
|
||||
info.blocks[1] = y;
|
||||
info.blocks[2] = z;
|
||||
|
||||
info.offsets[0] = base_x;
|
||||
info.offsets[1] = base_y;
|
||||
info.offsets[2] = base_z;
|
||||
tu_dispatch(cmd_buffer, &info);
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdDispatch(VkCommandBuffer commandBuffer,
|
||||
uint32_t x,
|
||||
uint32_t y,
|
||||
uint32_t z)
|
||||
{
|
||||
tu_CmdDispatchBase(commandBuffer, 0, 0, 0, x, y, z);
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdDispatchIndirect(VkCommandBuffer commandBuffer,
|
||||
VkBuffer _buffer,
|
||||
VkDeviceSize offset)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
TU_FROM_HANDLE(tu_buffer, buffer, _buffer);
|
||||
struct tu_dispatch_info info = {};
|
||||
|
||||
info.indirect = buffer;
|
||||
info.indirect_offset = offset;
|
||||
|
||||
tu_dispatch(cmd_buffer, &info);
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdEndRenderPass(VkCommandBuffer commandBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdEndRenderPass2KHR(VkCommandBuffer commandBuffer,
|
||||
const VkSubpassEndInfoKHR *pSubpassEndInfo)
|
||||
{
|
||||
tu_CmdEndRenderPass(commandBuffer);
|
||||
}
|
||||
|
||||
struct tu_barrier_info
|
||||
{
|
||||
uint32_t eventCount;
|
||||
const VkEvent *pEvents;
|
||||
VkPipelineStageFlags srcStageMask;
|
||||
};
|
||||
|
||||
static void
|
||||
tu_barrier(struct tu_cmd_buffer *cmd_buffer,
|
||||
uint32_t memoryBarrierCount,
|
||||
const VkMemoryBarrier *pMemoryBarriers,
|
||||
uint32_t bufferMemoryBarrierCount,
|
||||
const VkBufferMemoryBarrier *pBufferMemoryBarriers,
|
||||
uint32_t imageMemoryBarrierCount,
|
||||
const VkImageMemoryBarrier *pImageMemoryBarriers,
|
||||
const struct tu_barrier_info *info)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdPipelineBarrier(VkCommandBuffer commandBuffer,
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags destStageMask,
|
||||
VkBool32 byRegion,
|
||||
uint32_t memoryBarrierCount,
|
||||
const VkMemoryBarrier *pMemoryBarriers,
|
||||
uint32_t bufferMemoryBarrierCount,
|
||||
const VkBufferMemoryBarrier *pBufferMemoryBarriers,
|
||||
uint32_t imageMemoryBarrierCount,
|
||||
const VkImageMemoryBarrier *pImageMemoryBarriers)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
struct tu_barrier_info info;
|
||||
|
||||
info.eventCount = 0;
|
||||
info.pEvents = NULL;
|
||||
info.srcStageMask = srcStageMask;
|
||||
|
||||
tu_barrier(cmd_buffer,
|
||||
memoryBarrierCount,
|
||||
pMemoryBarriers,
|
||||
bufferMemoryBarrierCount,
|
||||
pBufferMemoryBarriers,
|
||||
imageMemoryBarrierCount,
|
||||
pImageMemoryBarriers,
|
||||
&info);
|
||||
}
|
||||
|
||||
static void
|
||||
write_event(struct tu_cmd_buffer *cmd_buffer,
|
||||
struct tu_event *event,
|
||||
VkPipelineStageFlags stageMask,
|
||||
unsigned value)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdSetEvent(VkCommandBuffer commandBuffer,
|
||||
VkEvent _event,
|
||||
VkPipelineStageFlags stageMask)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
TU_FROM_HANDLE(tu_event, event, _event);
|
||||
|
||||
write_event(cmd_buffer, event, stageMask, 1);
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdResetEvent(VkCommandBuffer commandBuffer,
|
||||
VkEvent _event,
|
||||
VkPipelineStageFlags stageMask)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
TU_FROM_HANDLE(tu_event, event, _event);
|
||||
|
||||
write_event(cmd_buffer, event, stageMask, 0);
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdWaitEvents(VkCommandBuffer commandBuffer,
|
||||
uint32_t eventCount,
|
||||
const VkEvent *pEvents,
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask,
|
||||
uint32_t memoryBarrierCount,
|
||||
const VkMemoryBarrier *pMemoryBarriers,
|
||||
uint32_t bufferMemoryBarrierCount,
|
||||
const VkBufferMemoryBarrier *pBufferMemoryBarriers,
|
||||
uint32_t imageMemoryBarrierCount,
|
||||
const VkImageMemoryBarrier *pImageMemoryBarriers)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
struct tu_barrier_info info;
|
||||
|
||||
info.eventCount = eventCount;
|
||||
info.pEvents = pEvents;
|
||||
info.srcStageMask = 0;
|
||||
|
||||
tu_barrier(cmd_buffer,
|
||||
memoryBarrierCount,
|
||||
pMemoryBarriers,
|
||||
bufferMemoryBarrierCount,
|
||||
pBufferMemoryBarriers,
|
||||
imageMemoryBarrierCount,
|
||||
pImageMemoryBarriers,
|
||||
&info);
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask)
|
||||
{
|
||||
/* No-op */
|
||||
}
|
|
@ -0,0 +1,565 @@
|
|||
/*
|
||||
* Copyright © 2016 Red Hat.
|
||||
* Copyright © 2016 Bas Nieuwenhuizen
|
||||
*
|
||||
* 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 <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tu_private.h"
|
||||
#include "util/mesa-sha1.h"
|
||||
#include "vk_util.h"
|
||||
|
||||
static int
|
||||
binding_compare(const void *av, const void *bv)
|
||||
{
|
||||
const VkDescriptorSetLayoutBinding *a =
|
||||
(const VkDescriptorSetLayoutBinding *)av;
|
||||
const VkDescriptorSetLayoutBinding *b =
|
||||
(const VkDescriptorSetLayoutBinding *)bv;
|
||||
|
||||
return (a->binding < b->binding) ? -1 : (a->binding > b->binding) ? 1 : 0;
|
||||
}
|
||||
|
||||
static VkDescriptorSetLayoutBinding *
|
||||
create_sorted_bindings(const VkDescriptorSetLayoutBinding *bindings,
|
||||
unsigned count)
|
||||
{
|
||||
VkDescriptorSetLayoutBinding *sorted_bindings =
|
||||
malloc(count * sizeof(VkDescriptorSetLayoutBinding));
|
||||
if (!sorted_bindings)
|
||||
return NULL;
|
||||
|
||||
memcpy(
|
||||
sorted_bindings, bindings, count * sizeof(VkDescriptorSetLayoutBinding));
|
||||
|
||||
qsort(sorted_bindings,
|
||||
count,
|
||||
sizeof(VkDescriptorSetLayoutBinding),
|
||||
binding_compare);
|
||||
|
||||
return sorted_bindings;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_CreateDescriptorSetLayout(
|
||||
VkDevice _device,
|
||||
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkDescriptorSetLayout *pSetLayout)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
struct tu_descriptor_set_layout *set_layout;
|
||||
|
||||
assert(pCreateInfo->sType ==
|
||||
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
|
||||
const VkDescriptorSetLayoutBindingFlagsCreateInfoEXT *variable_flags =
|
||||
vk_find_struct_const(pCreateInfo->pNext,
|
||||
DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT);
|
||||
|
||||
uint32_t max_binding = 0;
|
||||
uint32_t immutable_sampler_count = 0;
|
||||
for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
|
||||
max_binding = MAX2(max_binding, pCreateInfo->pBindings[j].binding);
|
||||
if (pCreateInfo->pBindings[j].pImmutableSamplers)
|
||||
immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount;
|
||||
}
|
||||
|
||||
uint32_t samplers_offset =
|
||||
sizeof(struct tu_descriptor_set_layout) +
|
||||
(max_binding + 1) * sizeof(set_layout->binding[0]);
|
||||
size_t size =
|
||||
samplers_offset + immutable_sampler_count * 4 * sizeof(uint32_t);
|
||||
|
||||
set_layout = vk_alloc2(
|
||||
&device->alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (!set_layout)
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
set_layout->flags = pCreateInfo->flags;
|
||||
|
||||
/* We just allocate all the samplers at the end of the struct */
|
||||
uint32_t *samplers = (uint32_t *)&set_layout->binding[max_binding + 1];
|
||||
|
||||
VkDescriptorSetLayoutBinding *bindings =
|
||||
create_sorted_bindings(pCreateInfo->pBindings, pCreateInfo->bindingCount);
|
||||
if (!bindings) {
|
||||
vk_free2(&device->alloc, pAllocator, set_layout);
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
}
|
||||
|
||||
set_layout->binding_count = max_binding + 1;
|
||||
set_layout->shader_stages = 0;
|
||||
set_layout->dynamic_shader_stages = 0;
|
||||
set_layout->has_immutable_samplers = false;
|
||||
set_layout->size = 0;
|
||||
|
||||
memset(
|
||||
set_layout->binding, 0, size - sizeof(struct tu_descriptor_set_layout));
|
||||
|
||||
uint32_t buffer_count = 0;
|
||||
uint32_t dynamic_offset_count = 0;
|
||||
|
||||
for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
|
||||
const VkDescriptorSetLayoutBinding *binding = bindings + j;
|
||||
uint32_t b = binding->binding;
|
||||
uint32_t alignment;
|
||||
unsigned binding_buffer_count = 0;
|
||||
|
||||
switch (binding->descriptorType) {
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||
assert(!(pCreateInfo->flags &
|
||||
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
|
||||
set_layout->binding[b].dynamic_offset_count = 1;
|
||||
set_layout->dynamic_shader_stages |= binding->stageFlags;
|
||||
set_layout->binding[b].size = 0;
|
||||
binding_buffer_count = 1;
|
||||
alignment = 1;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
||||
set_layout->binding[b].size = 16;
|
||||
binding_buffer_count = 1;
|
||||
alignment = 16;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
||||
/* main descriptor + fmask descriptor */
|
||||
set_layout->binding[b].size = 64;
|
||||
binding_buffer_count = 1;
|
||||
alignment = 32;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||
/* main descriptor + fmask descriptor + sampler */
|
||||
set_layout->binding[b].size = 96;
|
||||
binding_buffer_count = 1;
|
||||
alignment = 32;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
||||
set_layout->binding[b].size = 16;
|
||||
alignment = 16;
|
||||
break;
|
||||
default:
|
||||
unreachable("unknown descriptor type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
set_layout->size = align(set_layout->size, alignment);
|
||||
set_layout->binding[b].type = binding->descriptorType;
|
||||
set_layout->binding[b].array_size = binding->descriptorCount;
|
||||
set_layout->binding[b].offset = set_layout->size;
|
||||
set_layout->binding[b].buffer_offset = buffer_count;
|
||||
set_layout->binding[b].dynamic_offset_offset = dynamic_offset_count;
|
||||
|
||||
if (variable_flags && binding->binding < variable_flags->bindingCount &&
|
||||
(variable_flags->pBindingFlags[binding->binding] &
|
||||
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT)) {
|
||||
assert(!binding->pImmutableSamplers); /* Terribly ill defined how many
|
||||
samplers are valid */
|
||||
assert(binding->binding == max_binding);
|
||||
|
||||
set_layout->has_variable_descriptors = true;
|
||||
}
|
||||
|
||||
if (binding->pImmutableSamplers) {
|
||||
set_layout->binding[b].immutable_samplers_offset = samplers_offset;
|
||||
set_layout->has_immutable_samplers = true;
|
||||
}
|
||||
|
||||
set_layout->size +=
|
||||
binding->descriptorCount * set_layout->binding[b].size;
|
||||
buffer_count += binding->descriptorCount * binding_buffer_count;
|
||||
dynamic_offset_count +=
|
||||
binding->descriptorCount * set_layout->binding[b].dynamic_offset_count;
|
||||
set_layout->shader_stages |= binding->stageFlags;
|
||||
}
|
||||
|
||||
free(bindings);
|
||||
|
||||
set_layout->buffer_count = buffer_count;
|
||||
set_layout->dynamic_offset_count = dynamic_offset_count;
|
||||
|
||||
*pSetLayout = tu_descriptor_set_layout_to_handle(set_layout);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_DestroyDescriptorSetLayout(VkDevice _device,
|
||||
VkDescriptorSetLayout _set_layout,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_descriptor_set_layout, set_layout, _set_layout);
|
||||
|
||||
if (!set_layout)
|
||||
return;
|
||||
|
||||
vk_free2(&device->alloc, pAllocator, set_layout);
|
||||
}
|
||||
|
||||
void
|
||||
tu_GetDescriptorSetLayoutSupport(
|
||||
VkDevice device,
|
||||
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
|
||||
VkDescriptorSetLayoutSupport *pSupport)
|
||||
{
|
||||
VkDescriptorSetLayoutBinding *bindings =
|
||||
create_sorted_bindings(pCreateInfo->pBindings, pCreateInfo->bindingCount);
|
||||
if (!bindings) {
|
||||
pSupport->supported = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const VkDescriptorSetLayoutBindingFlagsCreateInfoEXT *variable_flags =
|
||||
vk_find_struct_const(pCreateInfo->pNext,
|
||||
DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT);
|
||||
VkDescriptorSetVariableDescriptorCountLayoutSupportEXT *variable_count =
|
||||
vk_find_struct(
|
||||
(void *)pCreateInfo->pNext,
|
||||
DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT);
|
||||
if (variable_count) {
|
||||
variable_count->maxVariableDescriptorCount = 0;
|
||||
}
|
||||
|
||||
bool supported = true;
|
||||
uint64_t size = 0;
|
||||
for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
|
||||
const VkDescriptorSetLayoutBinding *binding = bindings + i;
|
||||
|
||||
uint64_t descriptor_size = 0;
|
||||
uint64_t descriptor_alignment = 1;
|
||||
switch (binding->descriptorType) {
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
||||
descriptor_size = 16;
|
||||
descriptor_alignment = 16;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
||||
descriptor_size = 64;
|
||||
descriptor_alignment = 32;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||
descriptor_size = 96;
|
||||
descriptor_alignment = 32;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
||||
descriptor_size = 16;
|
||||
descriptor_alignment = 16;
|
||||
break;
|
||||
default:
|
||||
unreachable("unknown descriptor type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (size && !align_u64(size, descriptor_alignment)) {
|
||||
supported = false;
|
||||
}
|
||||
size = align_u64(size, descriptor_alignment);
|
||||
|
||||
uint64_t max_count = UINT64_MAX;
|
||||
if (descriptor_size)
|
||||
max_count = (UINT64_MAX - size) / descriptor_size;
|
||||
|
||||
if (max_count < binding->descriptorCount) {
|
||||
supported = false;
|
||||
}
|
||||
if (variable_flags && binding->binding < variable_flags->bindingCount &&
|
||||
variable_count &&
|
||||
(variable_flags->pBindingFlags[binding->binding] &
|
||||
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT)) {
|
||||
variable_count->maxVariableDescriptorCount =
|
||||
MIN2(UINT32_MAX, max_count);
|
||||
}
|
||||
size += binding->descriptorCount * descriptor_size;
|
||||
}
|
||||
|
||||
free(bindings);
|
||||
|
||||
pSupport->supported = supported;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pipeline layouts. These have nothing to do with the pipeline. They are
|
||||
* just multiple descriptor set layouts pasted together.
|
||||
*/
|
||||
|
||||
VkResult
|
||||
tu_CreatePipelineLayout(VkDevice _device,
|
||||
const VkPipelineLayoutCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkPipelineLayout *pPipelineLayout)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
struct tu_pipeline_layout *layout;
|
||||
struct mesa_sha1 ctx;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
|
||||
|
||||
layout = vk_alloc2(&device->alloc,
|
||||
pAllocator,
|
||||
sizeof(*layout),
|
||||
8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (layout == NULL)
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
layout->num_sets = pCreateInfo->setLayoutCount;
|
||||
|
||||
unsigned dynamic_offset_count = 0;
|
||||
|
||||
_mesa_sha1_init(&ctx);
|
||||
for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) {
|
||||
TU_FROM_HANDLE(
|
||||
tu_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[set]);
|
||||
layout->set[set].layout = set_layout;
|
||||
|
||||
layout->set[set].dynamic_offset_start = dynamic_offset_count;
|
||||
for (uint32_t b = 0; b < set_layout->binding_count; b++) {
|
||||
dynamic_offset_count += set_layout->binding[b].array_size *
|
||||
set_layout->binding[b].dynamic_offset_count;
|
||||
if (set_layout->binding[b].immutable_samplers_offset)
|
||||
_mesa_sha1_update(
|
||||
&ctx,
|
||||
tu_immutable_samplers(set_layout, set_layout->binding + b),
|
||||
set_layout->binding[b].array_size * 4 * sizeof(uint32_t));
|
||||
}
|
||||
_mesa_sha1_update(&ctx,
|
||||
set_layout->binding,
|
||||
sizeof(set_layout->binding[0]) *
|
||||
set_layout->binding_count);
|
||||
}
|
||||
|
||||
layout->dynamic_offset_count = dynamic_offset_count;
|
||||
layout->push_constant_size = 0;
|
||||
|
||||
for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
|
||||
const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i;
|
||||
layout->push_constant_size =
|
||||
MAX2(layout->push_constant_size, range->offset + range->size);
|
||||
}
|
||||
|
||||
layout->push_constant_size = align(layout->push_constant_size, 16);
|
||||
_mesa_sha1_update(
|
||||
&ctx, &layout->push_constant_size, sizeof(layout->push_constant_size));
|
||||
_mesa_sha1_final(&ctx, layout->sha1);
|
||||
*pPipelineLayout = tu_pipeline_layout_to_handle(layout);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_DestroyPipelineLayout(VkDevice _device,
|
||||
VkPipelineLayout _pipelineLayout,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_pipeline_layout, pipeline_layout, _pipelineLayout);
|
||||
|
||||
if (!pipeline_layout)
|
||||
return;
|
||||
vk_free2(&device->alloc, pAllocator, pipeline_layout);
|
||||
}
|
||||
|
||||
#define EMPTY 1
|
||||
|
||||
VkResult
|
||||
tu_CreateDescriptorPool(VkDevice _device,
|
||||
const VkDescriptorPoolCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkDescriptorPool *pDescriptorPool)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
struct tu_descriptor_pool *pool;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_DestroyDescriptorPool(VkDevice _device,
|
||||
VkDescriptorPool _pool,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_ResetDescriptorPool(VkDevice _device,
|
||||
VkDescriptorPool descriptorPool,
|
||||
VkDescriptorPoolResetFlags flags)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_descriptor_pool, pool, descriptorPool);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_AllocateDescriptorSets(VkDevice _device,
|
||||
const VkDescriptorSetAllocateInfo *pAllocateInfo,
|
||||
VkDescriptorSet *pDescriptorSets)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_descriptor_pool, pool, pAllocateInfo->descriptorPool);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_FreeDescriptorSets(VkDevice _device,
|
||||
VkDescriptorPool descriptorPool,
|
||||
uint32_t count,
|
||||
const VkDescriptorSet *pDescriptorSets)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_descriptor_pool, pool, descriptorPool);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_update_descriptor_sets(struct tu_device *device,
|
||||
struct tu_cmd_buffer *cmd_buffer,
|
||||
VkDescriptorSet dstSetOverride,
|
||||
uint32_t descriptorWriteCount,
|
||||
const VkWriteDescriptorSet *pDescriptorWrites,
|
||||
uint32_t descriptorCopyCount,
|
||||
const VkCopyDescriptorSet *pDescriptorCopies)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_UpdateDescriptorSets(VkDevice _device,
|
||||
uint32_t descriptorWriteCount,
|
||||
const VkWriteDescriptorSet *pDescriptorWrites,
|
||||
uint32_t descriptorCopyCount,
|
||||
const VkCopyDescriptorSet *pDescriptorCopies)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
|
||||
tu_update_descriptor_sets(device,
|
||||
NULL,
|
||||
VK_NULL_HANDLE,
|
||||
descriptorWriteCount,
|
||||
pDescriptorWrites,
|
||||
descriptorCopyCount,
|
||||
pDescriptorCopies);
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_CreateDescriptorUpdateTemplate(
|
||||
VkDevice _device,
|
||||
const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkDescriptorUpdateTemplateKHR *pDescriptorUpdateTemplate)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(
|
||||
tu_descriptor_set_layout, set_layout, pCreateInfo->descriptorSetLayout);
|
||||
const uint32_t entry_count = pCreateInfo->descriptorUpdateEntryCount;
|
||||
const size_t size =
|
||||
sizeof(struct tu_descriptor_update_template) +
|
||||
sizeof(struct tu_descriptor_update_template_entry) * entry_count;
|
||||
struct tu_descriptor_update_template *templ;
|
||||
uint32_t i;
|
||||
|
||||
templ = vk_alloc2(
|
||||
&device->alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (!templ)
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
*pDescriptorUpdateTemplate = tu_descriptor_update_template_to_handle(templ);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_DestroyDescriptorUpdateTemplate(
|
||||
VkDevice _device,
|
||||
VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(
|
||||
tu_descriptor_update_template, templ, descriptorUpdateTemplate);
|
||||
|
||||
if (!templ)
|
||||
return;
|
||||
|
||||
vk_free2(&device->alloc, pAllocator, templ);
|
||||
}
|
||||
|
||||
void
|
||||
tu_update_descriptor_set_with_template(
|
||||
struct tu_device *device,
|
||||
struct tu_cmd_buffer *cmd_buffer,
|
||||
struct tu_descriptor_set *set,
|
||||
VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
|
||||
const void *pData)
|
||||
{
|
||||
TU_FROM_HANDLE(
|
||||
tu_descriptor_update_template, templ, descriptorUpdateTemplate);
|
||||
}
|
||||
|
||||
void
|
||||
tu_UpdateDescriptorSetWithTemplate(
|
||||
VkDevice _device,
|
||||
VkDescriptorSet descriptorSet,
|
||||
VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
|
||||
const void *pData)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_descriptor_set, set, descriptorSet);
|
||||
|
||||
tu_update_descriptor_set_with_template(
|
||||
device, NULL, set, descriptorUpdateTemplate, pData);
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_CreateSamplerYcbcrConversion(
|
||||
VkDevice device,
|
||||
const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkSamplerYcbcrConversion *pYcbcrConversion)
|
||||
{
|
||||
*pYcbcrConversion = VK_NULL_HANDLE;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_DestroySamplerYcbcrConversion(VkDevice device,
|
||||
VkSamplerYcbcrConversion ycbcrConversion,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright © 2016 Bas Nieuwenhuizen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TU_DESCRIPTOR_SET_H
|
||||
#define TU_DESCRIPTOR_SET_H
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#define MAX_SETS 32
|
||||
|
||||
struct tu_descriptor_set_binding_layout
|
||||
{
|
||||
VkDescriptorType type;
|
||||
|
||||
/* Number of array elements in this binding */
|
||||
uint32_t array_size;
|
||||
|
||||
uint32_t offset;
|
||||
uint32_t buffer_offset;
|
||||
uint16_t dynamic_offset_offset;
|
||||
|
||||
uint16_t dynamic_offset_count;
|
||||
/* redundant with the type, each for a single array element */
|
||||
uint32_t size;
|
||||
|
||||
/* Offset in the tu_descriptor_set_layout of the immutable samplers, or 0
|
||||
* if there are no immutable samplers. */
|
||||
uint32_t immutable_samplers_offset;
|
||||
};
|
||||
|
||||
struct tu_descriptor_set_layout
|
||||
{
|
||||
/* The create flags for this descriptor set layout */
|
||||
VkDescriptorSetLayoutCreateFlags flags;
|
||||
|
||||
/* Number of bindings in this descriptor set */
|
||||
uint32_t binding_count;
|
||||
|
||||
/* Total size of the descriptor set with room for all array entries */
|
||||
uint32_t size;
|
||||
|
||||
/* Shader stages affected by this descriptor set */
|
||||
uint16_t shader_stages;
|
||||
uint16_t dynamic_shader_stages;
|
||||
|
||||
/* Number of buffers in this descriptor set */
|
||||
uint32_t buffer_count;
|
||||
|
||||
/* Number of dynamic offsets used by this descriptor set */
|
||||
uint16_t dynamic_offset_count;
|
||||
|
||||
bool has_immutable_samplers;
|
||||
bool has_variable_descriptors;
|
||||
|
||||
/* Bindings in this descriptor set */
|
||||
struct tu_descriptor_set_binding_layout binding[0];
|
||||
};
|
||||
|
||||
struct tu_pipeline_layout
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct tu_descriptor_set_layout *layout;
|
||||
uint32_t size;
|
||||
uint32_t dynamic_offset_start;
|
||||
} set[MAX_SETS];
|
||||
|
||||
uint32_t num_sets;
|
||||
uint32_t push_constant_size;
|
||||
uint32_t dynamic_offset_count;
|
||||
|
||||
unsigned char sha1[20];
|
||||
};
|
||||
|
||||
static inline const uint32_t *
|
||||
tu_immutable_samplers(const struct tu_descriptor_set_layout *set,
|
||||
const struct tu_descriptor_set_binding_layout *binding)
|
||||
{
|
||||
return (const uint32_t *)((const char *)set +
|
||||
binding->immutable_samplers_offset);
|
||||
}
|
||||
#endif /* TU_DESCRIPTOR_SET_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,506 @@
|
|||
# coding=utf-8
|
||||
#
|
||||
# Copyright © 2015, 2017 Intel Corporation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
# to deal in the Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice (including the next
|
||||
# paragraph) shall be included in all copies or substantial portions of the
|
||||
# Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
# IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
import argparse
|
||||
import functools
|
||||
import math
|
||||
import os
|
||||
import xml.etree.cElementTree as et
|
||||
|
||||
from collections import OrderedDict, namedtuple
|
||||
from mako.template import Template
|
||||
|
||||
from tu_extensions import VkVersion, MAX_API_VERSION, EXTENSIONS
|
||||
|
||||
# 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.
|
||||
|
||||
# We currently don't use layers in tu, but keeping the ability for anv
|
||||
# anyways, so we can use it for device groups.
|
||||
LAYERS = [
|
||||
'tu'
|
||||
]
|
||||
|
||||
TEMPLATE_H = Template("""\
|
||||
/* This file generated from ${filename}, don't edit directly. */
|
||||
|
||||
struct tu_dispatch_table {
|
||||
union {
|
||||
void *entrypoints[${len(entrypoints)}];
|
||||
struct {
|
||||
% for e in entrypoints:
|
||||
% if e.guard is not None:
|
||||
#ifdef ${e.guard}
|
||||
PFN_${e.name} ${e.name};
|
||||
#else
|
||||
void *${e.name};
|
||||
# endif
|
||||
% else:
|
||||
PFN_${e.name} ${e.name};
|
||||
% endif
|
||||
% endfor
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
% for e in entrypoints:
|
||||
% if e.alias:
|
||||
<% continue %>
|
||||
% endif
|
||||
% if e.guard is not None:
|
||||
#ifdef ${e.guard}
|
||||
% endif
|
||||
% for layer in LAYERS:
|
||||
${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()});
|
||||
% endfor
|
||||
% if e.guard is not None:
|
||||
#endif // ${e.guard}
|
||||
% endif
|
||||
% endfor
|
||||
""", output_encoding='utf-8')
|
||||
|
||||
TEMPLATE_C = Template(u"""\
|
||||
/*
|
||||
* 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 ${filename}, don't edit directly. */
|
||||
|
||||
#include "tu_private.h"
|
||||
|
||||
struct string_map_entry {
|
||||
uint32_t name;
|
||||
uint32_t hash;
|
||||
uint32_t num;
|
||||
};
|
||||
|
||||
/* We use a big string constant to avoid lots of relocations 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[] =
|
||||
% for s in strmap.sorted_strings:
|
||||
"${s.string}\\0"
|
||||
% endfor
|
||||
;
|
||||
|
||||
static const struct string_map_entry string_map_entries[] = {
|
||||
% for s in strmap.sorted_strings:
|
||||
{ ${s.offset}, ${'{:0=#8x}'.format(s.hash)}, ${s.num} }, /* ${s.string} */
|
||||
% endfor
|
||||
};
|
||||
|
||||
/* Hash table stats:
|
||||
* size ${len(strmap.sorted_strings)} entries
|
||||
* collisions entries:
|
||||
% for i in range(10):
|
||||
* ${i}${'+' if i == 9 else ' '} ${strmap.collisions[i]}
|
||||
% endfor
|
||||
*/
|
||||
|
||||
#define none 0xffff
|
||||
static const uint16_t string_map[${strmap.hash_size}] = {
|
||||
% for e in strmap.mapping:
|
||||
${ '{:0=#6x}'.format(e) if e >= 0 else 'none' },
|
||||
% endfor
|
||||
};
|
||||
|
||||
/* Weak aliases for all potential implementations. These will resolve to
|
||||
* NULL if they're not defined, which lets the resolve_entrypoint() function
|
||||
* either pick the correct entry point.
|
||||
*/
|
||||
|
||||
% for layer in LAYERS:
|
||||
% for e in entrypoints:
|
||||
% if e.alias:
|
||||
<% continue %>
|
||||
% endif
|
||||
% if e.guard is not None:
|
||||
#ifdef ${e.guard}
|
||||
% endif
|
||||
${e.return_type} ${e.prefixed_name(layer)}(${e.decl_params()}) __attribute__ ((weak));
|
||||
% if e.guard is not None:
|
||||
#endif // ${e.guard}
|
||||
% endif
|
||||
% endfor
|
||||
|
||||
const struct tu_dispatch_table ${layer}_layer = {
|
||||
% for e in entrypoints:
|
||||
% if e.guard is not None:
|
||||
#ifdef ${e.guard}
|
||||
% endif
|
||||
.${e.name} = ${e.prefixed_name(layer)},
|
||||
% if e.guard is not None:
|
||||
#endif // ${e.guard}
|
||||
% endif
|
||||
% endfor
|
||||
};
|
||||
% endfor
|
||||
|
||||
static void * __attribute__ ((noinline))
|
||||
tu_resolve_entrypoint(uint32_t index)
|
||||
{
|
||||
return tu_layer.entrypoints[index];
|
||||
}
|
||||
|
||||
/** Return true if the core version or extension in which the given entrypoint
|
||||
* is defined is enabled.
|
||||
*
|
||||
* If instance is NULL, we only allow the 3 commands explicitly allowed by the vk
|
||||
* spec.
|
||||
*
|
||||
* If device is NULL, all device extensions are considered enabled.
|
||||
*/
|
||||
static bool
|
||||
tu_entrypoint_is_enabled(int index, uint32_t core_version,
|
||||
const struct tu_instance_extension_table *instance,
|
||||
const struct tu_device_extension_table *device)
|
||||
{
|
||||
switch (index) {
|
||||
% for e in entrypoints:
|
||||
case ${e.num}:
|
||||
% if not e.device_command:
|
||||
if (device) return false;
|
||||
% endif
|
||||
% if e.name == 'vkCreateInstance' or e.name == 'vkEnumerateInstanceExtensionProperties' or e.name == 'vkEnumerateInstanceLayerProperties' or e.name == 'vkEnumerateInstanceVersion':
|
||||
return !device;
|
||||
% elif e.core_version:
|
||||
return instance && ${e.core_version.c_vk_version()} <= core_version;
|
||||
% elif e.extensions:
|
||||
% for ext in e.extensions:
|
||||
% if ext.type == 'instance':
|
||||
if (instance && instance->${ext.name[3:]}) return true;
|
||||
% else:
|
||||
if (instance && (!device || device->${ext.name[3:]})) return true;
|
||||
% endif
|
||||
%endfor
|
||||
return false;
|
||||
% else:
|
||||
return instance;
|
||||
% endif
|
||||
% endfor
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
tu_lookup_entrypoint(const char *name)
|
||||
{
|
||||
static const uint32_t prime_factor = ${strmap.prime_factor};
|
||||
static const uint32_t prime_step = ${strmap.prime_step};
|
||||
const struct string_map_entry *e;
|
||||
uint32_t hash, h;
|
||||
uint16_t i;
|
||||
const char *p;
|
||||
|
||||
hash = 0;
|
||||
for (p = name; *p; p++)
|
||||
hash = hash * prime_factor + *p;
|
||||
|
||||
h = hash;
|
||||
while (1) {
|
||||
i = string_map[h & ${strmap.hash_mask}];
|
||||
if (i == none)
|
||||
return -1;
|
||||
e = &string_map_entries[i];
|
||||
if (e->hash == hash && strcmp(name, strings + e->name) == 0)
|
||||
return e->num;
|
||||
h += prime_step;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *
|
||||
tu_lookup_entrypoint_unchecked(const char *name)
|
||||
{
|
||||
int index = tu_lookup_entrypoint(name);
|
||||
if (index < 0)
|
||||
return NULL;
|
||||
return tu_resolve_entrypoint(index);
|
||||
}
|
||||
|
||||
void *
|
||||
tu_lookup_entrypoint_checked(const char *name,
|
||||
uint32_t core_version,
|
||||
const struct tu_instance_extension_table *instance,
|
||||
const struct tu_device_extension_table *device)
|
||||
{
|
||||
int index = tu_lookup_entrypoint(name);
|
||||
if (index < 0 || !tu_entrypoint_is_enabled(index, core_version, instance, device))
|
||||
return NULL;
|
||||
return tu_resolve_entrypoint(index);
|
||||
}""", output_encoding='utf-8')
|
||||
|
||||
U32_MASK = 2**32 - 1
|
||||
|
||||
PRIME_FACTOR = 5024183
|
||||
PRIME_STEP = 19
|
||||
|
||||
def round_to_pow2(x):
|
||||
return 2**int(math.ceil(math.log(x, 2)))
|
||||
|
||||
class StringIntMapEntry(object):
|
||||
def __init__(self, string, num):
|
||||
self.string = string
|
||||
self.num = num
|
||||
|
||||
# Calculate the same hash value that we will calculate in C.
|
||||
h = 0
|
||||
for c in string:
|
||||
h = ((h * PRIME_FACTOR) + ord(c)) & U32_MASK
|
||||
self.hash = h
|
||||
|
||||
self.offset = None
|
||||
|
||||
class StringIntMap(object):
|
||||
def __init__(self):
|
||||
self.baked = False
|
||||
self.strings = dict()
|
||||
|
||||
def add_string(self, string, num):
|
||||
assert not self.baked
|
||||
assert string not in self.strings
|
||||
assert num >= 0 and num < 2**31
|
||||
self.strings[string] = StringIntMapEntry(string, num)
|
||||
|
||||
def bake(self):
|
||||
self.sorted_strings = \
|
||||
sorted(self.strings.values(), key=lambda x: x.string)
|
||||
offset = 0
|
||||
for entry in self.sorted_strings:
|
||||
entry.offset = offset
|
||||
offset += len(entry.string) + 1
|
||||
|
||||
# Save off some values that we'll need in C
|
||||
self.hash_size = round_to_pow2(len(self.strings) * 1.25)
|
||||
self.hash_mask = self.hash_size - 1
|
||||
self.prime_factor = PRIME_FACTOR
|
||||
self.prime_step = PRIME_STEP
|
||||
|
||||
self.mapping = [-1] * self.hash_size
|
||||
self.collisions = [0] * 10
|
||||
for idx, s in enumerate(self.sorted_strings):
|
||||
level = 0
|
||||
h = s.hash
|
||||
while self.mapping[h & self.hash_mask] >= 0:
|
||||
h = h + PRIME_STEP
|
||||
level = level + 1
|
||||
self.collisions[min(level, 9)] += 1
|
||||
self.mapping[h & self.hash_mask] = idx
|
||||
|
||||
EntrypointParam = namedtuple('EntrypointParam', 'type name decl')
|
||||
|
||||
class EntrypointBase(object):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.alias = None
|
||||
self.guard = None
|
||||
self.enabled = False
|
||||
self.num = None
|
||||
# Extensions which require this entrypoint
|
||||
self.core_version = None
|
||||
self.extensions = []
|
||||
|
||||
class Entrypoint(EntrypointBase):
|
||||
def __init__(self, name, return_type, params, guard = None):
|
||||
super(Entrypoint, self).__init__(name)
|
||||
self.return_type = return_type
|
||||
self.params = params
|
||||
self.guard = guard
|
||||
self.device_command = len(params) > 0 and (params[0].type == 'VkDevice' or params[0].type == 'VkQueue' or params[0].type == 'VkCommandBuffer')
|
||||
|
||||
def prefixed_name(self, prefix):
|
||||
assert self.name.startswith('vk')
|
||||
return prefix + '_' + self.name[2:]
|
||||
|
||||
def decl_params(self):
|
||||
return ', '.join(p.decl for p in self.params)
|
||||
|
||||
def call_params(self):
|
||||
return ', '.join(p.name for p in self.params)
|
||||
|
||||
class EntrypointAlias(EntrypointBase):
|
||||
def __init__(self, name, entrypoint):
|
||||
super(EntrypointAlias, self).__init__(name)
|
||||
self.alias = entrypoint
|
||||
self.device_command = entrypoint.device_command
|
||||
|
||||
def prefixed_name(self, prefix):
|
||||
return self.alias.prefixed_name(prefix)
|
||||
|
||||
def get_entrypoints(doc, entrypoints_to_defines, start_index):
|
||||
"""Extract the entry points from the registry."""
|
||||
entrypoints = OrderedDict()
|
||||
|
||||
for command in doc.findall('./commands/command'):
|
||||
if 'alias' in command.attrib:
|
||||
alias = command.attrib['name']
|
||||
target = command.attrib['alias']
|
||||
entrypoints[alias] = EntrypointAlias(alias, entrypoints[target])
|
||||
else:
|
||||
name = command.find('./proto/name').text
|
||||
ret_type = command.find('./proto/type').text
|
||||
params = [EntrypointParam(
|
||||
type = p.find('./type').text,
|
||||
name = p.find('./name').text,
|
||||
decl = ''.join(p.itertext())
|
||||
) for p in command.findall('./param')]
|
||||
guard = entrypoints_to_defines.get(name)
|
||||
# They really need to be unique
|
||||
assert name not in entrypoints
|
||||
entrypoints[name] = Entrypoint(name, ret_type, params, guard)
|
||||
|
||||
for feature in doc.findall('./feature'):
|
||||
assert feature.attrib['api'] == 'vulkan'
|
||||
version = VkVersion(feature.attrib['number'])
|
||||
if version > MAX_API_VERSION:
|
||||
continue
|
||||
|
||||
for command in feature.findall('./require/command'):
|
||||
e = entrypoints[command.attrib['name']]
|
||||
e.enabled = True
|
||||
assert e.core_version is None
|
||||
e.core_version = version
|
||||
|
||||
supported_exts = dict((ext.name, ext) for ext in EXTENSIONS)
|
||||
for extension in doc.findall('.extensions/extension'):
|
||||
ext_name = extension.attrib['name']
|
||||
if ext_name not in supported_exts:
|
||||
continue
|
||||
|
||||
ext = supported_exts[ext_name]
|
||||
ext.type = extension.attrib['type']
|
||||
|
||||
for command in extension.findall('./require/command'):
|
||||
e = entrypoints[command.attrib['name']]
|
||||
e.enabled = True
|
||||
assert e.core_version is None
|
||||
e.extensions.append(ext)
|
||||
|
||||
# if the base command is not supported by the driver yet, don't alias aliases
|
||||
for e in entrypoints.values():
|
||||
if e.alias and not e.alias.enabled:
|
||||
e_clone = copy.deepcopy(e.alias)
|
||||
e_clone.enabled = True
|
||||
e_clone.name = e.name
|
||||
entrypoints[e.name] = e_clone
|
||||
|
||||
return [e for e in entrypoints.values() if e.enabled]
|
||||
|
||||
|
||||
def get_entrypoints_defines(doc):
|
||||
"""Maps entry points to extension defines."""
|
||||
entrypoints_to_defines = {}
|
||||
|
||||
for extension in doc.findall('./extensions/extension[@protect]'):
|
||||
define = extension.attrib['protect']
|
||||
|
||||
for entrypoint in extension.findall('./require/command'):
|
||||
fullname = entrypoint.attrib['name']
|
||||
entrypoints_to_defines[fullname] = define
|
||||
|
||||
for extension in doc.findall('./extensions/extension[@platform]'):
|
||||
platform = extension.attrib['platform']
|
||||
ext = '_KHR'
|
||||
if platform.upper() == 'XLIB_XRANDR':
|
||||
ext = '_EXT'
|
||||
define = 'VK_USE_PLATFORM_' + platform.upper() + ext
|
||||
|
||||
for entrypoint in extension.findall('./require/command'):
|
||||
fullname = entrypoint.attrib['name']
|
||||
entrypoints_to_defines[fullname] = define
|
||||
|
||||
return entrypoints_to_defines
|
||||
|
||||
|
||||
def gen_code(entrypoints):
|
||||
"""Generate the C code."""
|
||||
strmap = StringIntMap()
|
||||
for e in entrypoints:
|
||||
strmap.add_string(e.name, e.num)
|
||||
strmap.bake()
|
||||
|
||||
return TEMPLATE_C.render(entrypoints=entrypoints,
|
||||
LAYERS=LAYERS,
|
||||
strmap=strmap,
|
||||
filename=os.path.basename(__file__))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--outdir', help='Where to write the files.',
|
||||
required=True)
|
||||
parser.add_argument('--xml',
|
||||
help='Vulkan API XML file.',
|
||||
required=True,
|
||||
action='append',
|
||||
dest='xml_files')
|
||||
args = parser.parse_args()
|
||||
|
||||
entrypoints = []
|
||||
|
||||
for filename in args.xml_files:
|
||||
doc = et.parse(filename)
|
||||
entrypoints += get_entrypoints(doc, get_entrypoints_defines(doc),
|
||||
start_index=len(entrypoints))
|
||||
|
||||
for num, e in enumerate(entrypoints):
|
||||
e.num = num
|
||||
|
||||
# For outputting entrypoints.h we generate a tu_EntryPoint() prototype
|
||||
# per entry point.
|
||||
with open(os.path.join(args.outdir, 'tu_entrypoints.h'), 'wb') as f:
|
||||
f.write(TEMPLATE_H.render(entrypoints=entrypoints,
|
||||
LAYERS=LAYERS,
|
||||
filename=os.path.basename(__file__)))
|
||||
with open(os.path.join(args.outdir, 'tu_entrypoints.c'), 'wb') as f:
|
||||
f.write(gen_code(entrypoints))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -0,0 +1,275 @@
|
|||
COPYRIGHT = """\
|
||||
/*
|
||||
* Copyright 2017 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import copy
|
||||
import re
|
||||
import xml.etree.cElementTree as et
|
||||
|
||||
from mako.template import Template
|
||||
|
||||
MAX_API_VERSION = '1.1.82'
|
||||
|
||||
class Extension:
|
||||
def __init__(self, name, ext_version, enable):
|
||||
self.name = name
|
||||
self.ext_version = int(ext_version)
|
||||
if enable is True:
|
||||
self.enable = 'true';
|
||||
elif enable is False:
|
||||
self.enable = 'false';
|
||||
else:
|
||||
self.enable = enable;
|
||||
|
||||
# On Android, we disable all surface and swapchain extensions. Android's Vulkan
|
||||
# loader implements VK_KHR_surface and VK_KHR_swapchain, and applications
|
||||
# cannot access the driver's implementation. Moreoever, if the driver exposes
|
||||
# the those extension strings, then tests dEQP-VK.api.info.instance.extensions
|
||||
# and dEQP-VK.api.info.device fail due to the duplicated strings.
|
||||
EXTENSIONS = [
|
||||
Extension('VK_KHR_bind_memory2', 1, True),
|
||||
Extension('VK_KHR_create_renderpass2', 1, True),
|
||||
Extension('VK_KHR_dedicated_allocation', 1, True),
|
||||
Extension('VK_KHR_get_display_properties2', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'),
|
||||
Extension('VK_KHR_get_memory_requirements2', 1, True),
|
||||
Extension('VK_KHR_get_physical_device_properties2', 1, True),
|
||||
Extension('VK_KHR_get_surface_capabilities2', 1, 'TU_HAS_SURFACE'),
|
||||
Extension('VK_KHR_maintenance1', 1, True),
|
||||
Extension('VK_KHR_maintenance2', 1, True),
|
||||
Extension('VK_KHR_maintenance3', 1, True),
|
||||
Extension('VK_KHR_surface', 25, 'TU_HAS_SURFACE'),
|
||||
Extension('VK_KHR_swapchain', 68, 'TU_HAS_SURFACE'),
|
||||
Extension('VK_KHR_wayland_surface', 6, 'VK_USE_PLATFORM_WAYLAND_KHR'),
|
||||
Extension('VK_KHR_xcb_surface', 6, 'VK_USE_PLATFORM_XCB_KHR'),
|
||||
Extension('VK_KHR_xlib_surface', 6, 'VK_USE_PLATFORM_XLIB_KHR'),
|
||||
Extension('VK_KHR_display', 23, 'VK_USE_PLATFORM_DISPLAY_KHR'),
|
||||
Extension('VK_EXT_direct_mode_display', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'),
|
||||
Extension('VK_EXT_acquire_xlib_display', 1, 'VK_USE_PLATFORM_XLIB_XRANDR_EXT'),
|
||||
Extension('VK_EXT_display_surface_counter', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'),
|
||||
Extension('VK_EXT_display_control', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'),
|
||||
Extension('VK_EXT_debug_report', 9, True),
|
||||
]
|
||||
|
||||
class VkVersion:
|
||||
def __init__(self, string):
|
||||
split = string.split('.')
|
||||
self.major = int(split[0])
|
||||
self.minor = int(split[1])
|
||||
if len(split) > 2:
|
||||
assert len(split) == 3
|
||||
self.patch = int(split[2])
|
||||
else:
|
||||
self.patch = None
|
||||
|
||||
# Sanity check. The range bits are required by the definition of the
|
||||
# VK_MAKE_VERSION macro
|
||||
assert self.major < 1024 and self.minor < 1024
|
||||
assert self.patch is None or self.patch < 4096
|
||||
assert(str(self) == string)
|
||||
|
||||
def __str__(self):
|
||||
ver_list = [str(self.major), str(self.minor)]
|
||||
if self.patch is not None:
|
||||
ver_list.append(str(self.patch))
|
||||
return '.'.join(ver_list)
|
||||
|
||||
def c_vk_version(self):
|
||||
patch = self.patch if self.patch is not None else 0
|
||||
ver_list = [str(self.major), str(self.minor), str(patch)]
|
||||
return 'VK_MAKE_VERSION(' + ', '.join(ver_list) + ')'
|
||||
|
||||
def __int_ver(self):
|
||||
# This is just an expansion of VK_VERSION
|
||||
patch = self.patch if self.patch is not None else 0
|
||||
return (self.major << 22) | (self.minor << 12) | patch
|
||||
|
||||
def __gt__(self, other):
|
||||
# If only one of them has a patch version, "ignore" it by making
|
||||
# other's patch version match self.
|
||||
if (self.patch is None) != (other.patch is None):
|
||||
other = copy.copy(other)
|
||||
other.patch = self.patch
|
||||
|
||||
return self.__int_ver() > other.__int_ver()
|
||||
|
||||
MAX_API_VERSION = VkVersion(MAX_API_VERSION)
|
||||
|
||||
def _init_exts_from_xml(xml):
|
||||
""" Walk the Vulkan XML and fill out extra extension information. """
|
||||
|
||||
xml = et.parse(xml)
|
||||
|
||||
ext_name_map = {}
|
||||
for ext in EXTENSIONS:
|
||||
ext_name_map[ext.name] = ext
|
||||
|
||||
for ext_elem in xml.findall('.extensions/extension'):
|
||||
ext_name = ext_elem.attrib['name']
|
||||
if ext_name not in ext_name_map:
|
||||
continue
|
||||
|
||||
ext = ext_name_map[ext_name]
|
||||
ext.type = ext_elem.attrib['type']
|
||||
|
||||
_TEMPLATE_H = Template(COPYRIGHT + """
|
||||
#ifndef TU_EXTENSIONS_H
|
||||
#define TU_EXTENSIONS_H
|
||||
|
||||
enum {
|
||||
TU_INSTANCE_EXTENSION_COUNT = ${len(instance_extensions)},
|
||||
TU_DEVICE_EXTENSION_COUNT = ${len(device_extensions)},
|
||||
};
|
||||
|
||||
struct tu_instance_extension_table {
|
||||
union {
|
||||
bool extensions[TU_INSTANCE_EXTENSION_COUNT];
|
||||
struct {
|
||||
%for ext in instance_extensions:
|
||||
bool ${ext.name[3:]};
|
||||
%endfor
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct tu_device_extension_table {
|
||||
union {
|
||||
bool extensions[TU_DEVICE_EXTENSION_COUNT];
|
||||
struct {
|
||||
%for ext in device_extensions:
|
||||
bool ${ext.name[3:]};
|
||||
%endfor
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
extern const VkExtensionProperties tu_instance_extensions[TU_INSTANCE_EXTENSION_COUNT];
|
||||
extern const VkExtensionProperties tu_device_extensions[TU_DEVICE_EXTENSION_COUNT];
|
||||
extern const struct tu_instance_extension_table tu_supported_instance_extensions;
|
||||
|
||||
|
||||
struct tu_physical_device;
|
||||
|
||||
void tu_fill_device_extension_table(const struct tu_physical_device *device,
|
||||
struct tu_device_extension_table* table);
|
||||
#endif
|
||||
""")
|
||||
|
||||
_TEMPLATE_C = Template(COPYRIGHT + """
|
||||
#include "tu_private.h"
|
||||
|
||||
#include "vk_util.h"
|
||||
|
||||
/* Convert the VK_USE_PLATFORM_* defines to booleans */
|
||||
%for platform in ['ANDROID_KHR', 'WAYLAND_KHR', 'XCB_KHR', 'XLIB_KHR', 'DISPLAY_KHR', 'XLIB_XRANDR_EXT']:
|
||||
#ifdef VK_USE_PLATFORM_${platform}
|
||||
# undef VK_USE_PLATFORM_${platform}
|
||||
# define VK_USE_PLATFORM_${platform} true
|
||||
#else
|
||||
# define VK_USE_PLATFORM_${platform} false
|
||||
#endif
|
||||
%endfor
|
||||
|
||||
/* And ANDROID too */
|
||||
#ifdef ANDROID
|
||||
# undef ANDROID
|
||||
# define ANDROID true
|
||||
#else
|
||||
# define ANDROID false
|
||||
#endif
|
||||
|
||||
#define TU_HAS_SURFACE (VK_USE_PLATFORM_WAYLAND_KHR || \\
|
||||
VK_USE_PLATFORM_XCB_KHR || \\
|
||||
VK_USE_PLATFORM_XLIB_KHR || \\
|
||||
VK_USE_PLATFORM_DISPLAY_KHR)
|
||||
|
||||
|
||||
const VkExtensionProperties tu_instance_extensions[TU_INSTANCE_EXTENSION_COUNT] = {
|
||||
%for ext in instance_extensions:
|
||||
{"${ext.name}", ${ext.ext_version}},
|
||||
%endfor
|
||||
};
|
||||
|
||||
const VkExtensionProperties tu_device_extensions[TU_DEVICE_EXTENSION_COUNT] = {
|
||||
%for ext in device_extensions:
|
||||
{"${ext.name}", ${ext.ext_version}},
|
||||
%endfor
|
||||
};
|
||||
|
||||
const struct tu_instance_extension_table tu_supported_instance_extensions = {
|
||||
%for ext in instance_extensions:
|
||||
.${ext.name[3:]} = ${ext.enable},
|
||||
%endfor
|
||||
};
|
||||
|
||||
void tu_fill_device_extension_table(const struct tu_physical_device *device,
|
||||
struct tu_device_extension_table* table)
|
||||
{
|
||||
%for ext in device_extensions:
|
||||
table->${ext.name[3:]} = ${ext.enable};
|
||||
%endfor
|
||||
}
|
||||
|
||||
VkResult tu_EnumerateInstanceVersion(
|
||||
uint32_t* pApiVersion)
|
||||
{
|
||||
*pApiVersion = ${MAX_API_VERSION.c_vk_version()};
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
tu_physical_device_api_version(struct tu_physical_device *dev)
|
||||
{
|
||||
return VK_MAKE_VERSION(1, 1, 82);
|
||||
}
|
||||
""")
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--out-c', help='Output C file.', required=True)
|
||||
parser.add_argument('--out-h', help='Output H file.', required=True)
|
||||
parser.add_argument('--xml',
|
||||
help='Vulkan API XML file.',
|
||||
required=True,
|
||||
action='append',
|
||||
dest='xml_files')
|
||||
args = parser.parse_args()
|
||||
|
||||
for filename in args.xml_files:
|
||||
_init_exts_from_xml(filename)
|
||||
|
||||
for ext in EXTENSIONS:
|
||||
assert ext.type == 'instance' or ext.type == 'device'
|
||||
|
||||
template_env = {
|
||||
'MAX_API_VERSION': MAX_API_VERSION,
|
||||
'instance_extensions': [e for e in EXTENSIONS if e.type == 'instance'],
|
||||
'device_extensions': [e for e in EXTENSIONS if e.type == 'device'],
|
||||
}
|
||||
|
||||
with open(args.out_c, 'w') as f:
|
||||
f.write(_TEMPLATE_C.render(**template_env))
|
||||
with open(args.out_h, 'w') as f:
|
||||
f.write(_TEMPLATE_H.render(**template_env))
|
|
@ -0,0 +1,410 @@
|
|||
|
||||
/*
|
||||
* Copyright © 2016 Red Hat.
|
||||
* Copyright © 2016 Bas Nieuwenhuizen
|
||||
*
|
||||
* 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 "tu_private.h"
|
||||
|
||||
#include "vk_format.h"
|
||||
|
||||
#include "vk_util.h"
|
||||
|
||||
#include "util/format_r11g11b10f.h"
|
||||
#include "util/format_srgb.h"
|
||||
#include "util/u_half.h"
|
||||
|
||||
static void
|
||||
tu_physical_device_get_format_properties(
|
||||
struct tu_physical_device *physical_device,
|
||||
VkFormat format,
|
||||
VkFormatProperties *out_properties)
|
||||
{
|
||||
VkFormatFeatureFlags linear = 0, tiled = 0, buffer = 0;
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
if (!desc) {
|
||||
out_properties->linearTilingFeatures = linear;
|
||||
out_properties->optimalTilingFeatures = tiled;
|
||||
out_properties->bufferFeatures = buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
out_properties->linearTilingFeatures = linear;
|
||||
out_properties->optimalTilingFeatures = tiled;
|
||||
out_properties->bufferFeatures = buffer;
|
||||
}
|
||||
|
||||
void
|
||||
tu_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,
|
||||
VkFormat format,
|
||||
VkFormatProperties *pFormatProperties)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
|
||||
|
||||
tu_physical_device_get_format_properties(
|
||||
physical_device, format, pFormatProperties);
|
||||
}
|
||||
|
||||
void
|
||||
tu_GetPhysicalDeviceFormatProperties2(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkFormat format,
|
||||
VkFormatProperties2KHR *pFormatProperties)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
|
||||
|
||||
tu_physical_device_get_format_properties(
|
||||
physical_device, format, &pFormatProperties->formatProperties);
|
||||
}
|
||||
|
||||
static VkResult
|
||||
tu_get_image_format_properties(struct tu_physical_device *physical_device,
|
||||
const VkPhysicalDeviceImageFormatInfo2KHR *info,
|
||||
VkImageFormatProperties *pImageFormatProperties)
|
||||
|
||||
{
|
||||
VkFormatProperties format_props;
|
||||
VkFormatFeatureFlags format_feature_flags;
|
||||
VkExtent3D maxExtent;
|
||||
uint32_t maxMipLevels;
|
||||
uint32_t maxArraySize;
|
||||
VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
tu_physical_device_get_format_properties(
|
||||
physical_device, info->format, &format_props);
|
||||
if (info->tiling == VK_IMAGE_TILING_LINEAR) {
|
||||
format_feature_flags = format_props.linearTilingFeatures;
|
||||
} else if (info->tiling == VK_IMAGE_TILING_OPTIMAL) {
|
||||
format_feature_flags = format_props.optimalTilingFeatures;
|
||||
} else {
|
||||
unreachable("bad VkImageTiling");
|
||||
}
|
||||
|
||||
if (format_feature_flags == 0)
|
||||
goto unsupported;
|
||||
|
||||
if (info->type != VK_IMAGE_TYPE_2D &&
|
||||
vk_format_is_depth_or_stencil(info->format))
|
||||
goto unsupported;
|
||||
|
||||
switch (info->type) {
|
||||
default:
|
||||
unreachable("bad vkimage type\n");
|
||||
case VK_IMAGE_TYPE_1D:
|
||||
maxExtent.width = 16384;
|
||||
maxExtent.height = 1;
|
||||
maxExtent.depth = 1;
|
||||
maxMipLevels = 15; /* log2(maxWidth) + 1 */
|
||||
maxArraySize = 2048;
|
||||
break;
|
||||
case VK_IMAGE_TYPE_2D:
|
||||
maxExtent.width = 16384;
|
||||
maxExtent.height = 16384;
|
||||
maxExtent.depth = 1;
|
||||
maxMipLevels = 15; /* log2(maxWidth) + 1 */
|
||||
maxArraySize = 2048;
|
||||
break;
|
||||
case VK_IMAGE_TYPE_3D:
|
||||
maxExtent.width = 2048;
|
||||
maxExtent.height = 2048;
|
||||
maxExtent.depth = 2048;
|
||||
maxMipLevels = 12; /* log2(maxWidth) + 1 */
|
||||
maxArraySize = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
|
||||
info->type == VK_IMAGE_TYPE_2D &&
|
||||
(format_feature_flags &
|
||||
(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
|
||||
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
|
||||
!(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
|
||||
!(info->usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
|
||||
sampleCounts |=
|
||||
VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT | VK_SAMPLE_COUNT_8_BIT;
|
||||
}
|
||||
|
||||
if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
|
||||
if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
|
||||
goto unsupported;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
|
||||
if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
|
||||
goto unsupported;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
|
||||
if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
|
||||
goto unsupported;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
|
||||
if (!(format_feature_flags &
|
||||
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
|
||||
goto unsupported;
|
||||
}
|
||||
}
|
||||
|
||||
*pImageFormatProperties = (VkImageFormatProperties){
|
||||
.maxExtent = maxExtent,
|
||||
.maxMipLevels = maxMipLevels,
|
||||
.maxArrayLayers = maxArraySize,
|
||||
.sampleCounts = sampleCounts,
|
||||
|
||||
/* FINISHME: Accurately calculate
|
||||
* VkImageFormatProperties::maxResourceSize.
|
||||
*/
|
||||
.maxResourceSize = UINT32_MAX,
|
||||
};
|
||||
|
||||
return VK_SUCCESS;
|
||||
unsupported:
|
||||
*pImageFormatProperties = (VkImageFormatProperties){
|
||||
.maxExtent = { 0, 0, 0 },
|
||||
.maxMipLevels = 0,
|
||||
.maxArrayLayers = 0,
|
||||
.sampleCounts = 0,
|
||||
.maxResourceSize = 0,
|
||||
};
|
||||
|
||||
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_GetPhysicalDeviceImageFormatProperties(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkFormat format,
|
||||
VkImageType type,
|
||||
VkImageTiling tiling,
|
||||
VkImageUsageFlags usage,
|
||||
VkImageCreateFlags createFlags,
|
||||
VkImageFormatProperties *pImageFormatProperties)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
|
||||
|
||||
const VkPhysicalDeviceImageFormatInfo2KHR info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
|
||||
.pNext = NULL,
|
||||
.format = format,
|
||||
.type = type,
|
||||
.tiling = tiling,
|
||||
.usage = usage,
|
||||
.flags = createFlags,
|
||||
};
|
||||
|
||||
return tu_get_image_format_properties(
|
||||
physical_device, &info, pImageFormatProperties);
|
||||
}
|
||||
|
||||
static void
|
||||
get_external_image_format_properties(
|
||||
const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo,
|
||||
VkExternalMemoryHandleTypeFlagBitsKHR handleType,
|
||||
VkExternalMemoryPropertiesKHR *external_properties)
|
||||
{
|
||||
VkExternalMemoryFeatureFlagBitsKHR flags = 0;
|
||||
VkExternalMemoryHandleTypeFlagsKHR export_flags = 0;
|
||||
VkExternalMemoryHandleTypeFlagsKHR compat_flags = 0;
|
||||
switch (handleType) {
|
||||
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
|
||||
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
|
||||
switch (pImageFormatInfo->type) {
|
||||
case VK_IMAGE_TYPE_2D:
|
||||
flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR |
|
||||
VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR |
|
||||
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR;
|
||||
compat_flags = export_flags =
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR |
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
|
||||
flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR;
|
||||
compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
*external_properties = (VkExternalMemoryPropertiesKHR){
|
||||
.externalMemoryFeatures = flags,
|
||||
.exportFromImportedHandleTypes = export_flags,
|
||||
.compatibleHandleTypes = compat_flags,
|
||||
};
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_GetPhysicalDeviceImageFormatProperties2(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkPhysicalDeviceImageFormatInfo2KHR *base_info,
|
||||
VkImageFormatProperties2KHR *base_props)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
|
||||
const VkPhysicalDeviceExternalImageFormatInfoKHR *external_info = NULL;
|
||||
VkExternalImageFormatPropertiesKHR *external_props = NULL;
|
||||
VkResult result;
|
||||
|
||||
result = tu_get_image_format_properties(
|
||||
physical_device, base_info, &base_props->imageFormatProperties);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
/* Extract input structs */
|
||||
vk_foreach_struct_const(s, base_info->pNext)
|
||||
{
|
||||
switch (s->sType) {
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR:
|
||||
external_info = (const void *)s;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract output structs */
|
||||
vk_foreach_struct(s, base_props->pNext)
|
||||
{
|
||||
switch (s->sType) {
|
||||
case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR:
|
||||
external_props = (void *)s;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* From the Vulkan 1.0.42 spec:
|
||||
*
|
||||
* If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2KHR will
|
||||
* behave as if VkPhysicalDeviceExternalImageFormatInfoKHR was not
|
||||
* present and VkExternalImageFormatPropertiesKHR will be ignored.
|
||||
*/
|
||||
if (external_info && external_info->handleType != 0) {
|
||||
switch (external_info->handleType) {
|
||||
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
|
||||
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
|
||||
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
|
||||
get_external_image_format_properties(
|
||||
base_info,
|
||||
external_info->handleType,
|
||||
&external_props->externalMemoryProperties);
|
||||
break;
|
||||
default:
|
||||
/* From the Vulkan 1.0.42 spec:
|
||||
*
|
||||
* If handleType is not compatible with the [parameters]
|
||||
* specified
|
||||
* in VkPhysicalDeviceImageFormatInfo2KHR, then
|
||||
* vkGetPhysicalDeviceImageFormatProperties2KHR returns
|
||||
* VK_ERROR_FORMAT_NOT_SUPPORTED.
|
||||
*/
|
||||
result =
|
||||
vk_errorf(physical_device->instance,
|
||||
VK_ERROR_FORMAT_NOT_SUPPORTED,
|
||||
"unsupported VkExternalMemoryTypeFlagBitsKHR 0x%x",
|
||||
external_info->handleType);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
||||
fail:
|
||||
if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
|
||||
/* From the Vulkan 1.0.42 spec:
|
||||
*
|
||||
* If the combination of parameters to
|
||||
* vkGetPhysicalDeviceImageFormatProperties2KHR is not supported by
|
||||
* the implementation for use in vkCreateImage, then all members of
|
||||
* imageFormatProperties will be filled with zero.
|
||||
*/
|
||||
base_props->imageFormatProperties = (VkImageFormatProperties){ 0 };
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
tu_GetPhysicalDeviceSparseImageFormatProperties(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkFormat format,
|
||||
VkImageType type,
|
||||
uint32_t samples,
|
||||
VkImageUsageFlags usage,
|
||||
VkImageTiling tiling,
|
||||
uint32_t *pNumProperties,
|
||||
VkSparseImageFormatProperties *pProperties)
|
||||
{
|
||||
/* Sparse images are not yet supported. */
|
||||
*pNumProperties = 0;
|
||||
}
|
||||
|
||||
void
|
||||
tu_GetPhysicalDeviceSparseImageFormatProperties2(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkPhysicalDeviceSparseImageFormatInfo2KHR *pFormatInfo,
|
||||
uint32_t *pPropertyCount,
|
||||
VkSparseImageFormatProperties2KHR *pProperties)
|
||||
{
|
||||
/* Sparse images are not yet supported. */
|
||||
*pPropertyCount = 0;
|
||||
}
|
||||
|
||||
void
|
||||
tu_GetPhysicalDeviceExternalBufferProperties(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkPhysicalDeviceExternalBufferInfoKHR *pExternalBufferInfo,
|
||||
VkExternalBufferPropertiesKHR *pExternalBufferProperties)
|
||||
{
|
||||
VkExternalMemoryFeatureFlagBitsKHR flags = 0;
|
||||
VkExternalMemoryHandleTypeFlagsKHR export_flags = 0;
|
||||
VkExternalMemoryHandleTypeFlagsKHR compat_flags = 0;
|
||||
switch (pExternalBufferInfo->handleType) {
|
||||
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
|
||||
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
|
||||
flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR |
|
||||
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR;
|
||||
compat_flags = export_flags =
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR |
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
|
||||
break;
|
||||
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
|
||||
flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR;
|
||||
compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pExternalBufferProperties->externalMemoryProperties =
|
||||
(VkExternalMemoryPropertiesKHR){
|
||||
.externalMemoryFeatures = flags,
|
||||
.exportFromImportedHandleTypes = export_flags,
|
||||
.compatibleHandleTypes = compat_flags,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
# Copyright 2017 Intel Corporation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sub license, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice (including the
|
||||
# next paragraph) shall be included in all copies or substantial portions
|
||||
# of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import json
|
||||
import os.path
|
||||
|
||||
from tu_extensions import *
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--out', help='Output json file.', required=True)
|
||||
parser.add_argument('--lib-path', help='Path to libvulkan_freedreno.so')
|
||||
args = parser.parse_args()
|
||||
|
||||
path = 'libvulkan_freedreno.so'
|
||||
if args.lib_path:
|
||||
path = os.path.join(args.lib_path, path)
|
||||
|
||||
json_data = {
|
||||
'file_format_version': '1.0.0',
|
||||
'ICD': {
|
||||
'library_path': path,
|
||||
'api_version': str(MAX_API_VERSION),
|
||||
},
|
||||
}
|
||||
|
||||
with open(args.out, 'w') as f:
|
||||
json.dump(json_data, f, indent = 4, sort_keys=True, separators=(',', ': '))
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Copyright © 2016 Red Hat.
|
||||
* Copyright © 2016 Bas Nieuwenhuizen
|
||||
*
|
||||
* based in part on anv driver which is:
|
||||
* 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 "tu_private.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/u_atomic.h"
|
||||
#include "vk_format.h"
|
||||
#include "vk_util.h"
|
||||
|
||||
VkResult
|
||||
tu_image_create(VkDevice _device,
|
||||
const struct tu_image_create_info *create_info,
|
||||
const VkAllocationCallbacks *alloc,
|
||||
VkImage *pImage)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
|
||||
struct tu_image *image = NULL;
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
|
||||
|
||||
tu_assert(pCreateInfo->mipLevels > 0);
|
||||
tu_assert(pCreateInfo->arrayLayers > 0);
|
||||
tu_assert(pCreateInfo->samples > 0);
|
||||
tu_assert(pCreateInfo->extent.width > 0);
|
||||
tu_assert(pCreateInfo->extent.height > 0);
|
||||
tu_assert(pCreateInfo->extent.depth > 0);
|
||||
|
||||
image = vk_zalloc2(&device->alloc,
|
||||
alloc,
|
||||
sizeof(*image),
|
||||
8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (!image)
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
image->type = pCreateInfo->imageType;
|
||||
|
||||
image->vk_format = pCreateInfo->format;
|
||||
image->tiling = pCreateInfo->tiling;
|
||||
image->usage = pCreateInfo->usage;
|
||||
image->flags = pCreateInfo->flags;
|
||||
|
||||
image->exclusive = pCreateInfo->sharingMode == VK_SHARING_MODE_EXCLUSIVE;
|
||||
if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
|
||||
for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; ++i)
|
||||
if (pCreateInfo->pQueueFamilyIndices[i] ==
|
||||
VK_QUEUE_FAMILY_EXTERNAL_KHR)
|
||||
image->queue_family_mask |= (1u << TU_MAX_QUEUE_FAMILIES) - 1u;
|
||||
else
|
||||
image->queue_family_mask |= 1u
|
||||
<< pCreateInfo->pQueueFamilyIndices[i];
|
||||
}
|
||||
|
||||
image->shareable =
|
||||
vk_find_struct_const(pCreateInfo->pNext,
|
||||
EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR) != NULL;
|
||||
|
||||
*pImage = tu_image_to_handle(image);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_image_view_init(struct tu_image_view *iview,
|
||||
struct tu_device *device,
|
||||
const VkImageViewCreateInfo *pCreateInfo)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned
|
||||
tu_image_queue_family_mask(const struct tu_image *image,
|
||||
uint32_t family,
|
||||
uint32_t queue_family)
|
||||
{
|
||||
if (!image->exclusive)
|
||||
return image->queue_family_mask;
|
||||
if (family == VK_QUEUE_FAMILY_EXTERNAL_KHR)
|
||||
return (1u << TU_MAX_QUEUE_FAMILIES) - 1u;
|
||||
if (family == VK_QUEUE_FAMILY_IGNORED)
|
||||
return 1u << queue_family;
|
||||
return 1u << family;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_CreateImage(VkDevice device,
|
||||
const VkImageCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkImage *pImage)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
const VkNativeBufferANDROID *gralloc_info =
|
||||
vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
|
||||
|
||||
if (gralloc_info)
|
||||
return tu_image_from_gralloc(
|
||||
device, pCreateInfo, gralloc_info, pAllocator, pImage);
|
||||
#endif
|
||||
|
||||
return tu_image_create(device,
|
||||
&(struct tu_image_create_info) {
|
||||
.vk_info = pCreateInfo,
|
||||
.scanout = false,
|
||||
},
|
||||
pAllocator,
|
||||
pImage);
|
||||
}
|
||||
|
||||
void
|
||||
tu_DestroyImage(VkDevice _device,
|
||||
VkImage _image,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_image, image, _image);
|
||||
|
||||
if (!image)
|
||||
return;
|
||||
|
||||
if (image->owned_memory != VK_NULL_HANDLE)
|
||||
tu_FreeMemory(_device, image->owned_memory, pAllocator);
|
||||
|
||||
vk_free2(&device->alloc, pAllocator, image);
|
||||
}
|
||||
|
||||
void
|
||||
tu_GetImageSubresourceLayout(VkDevice _device,
|
||||
VkImage _image,
|
||||
const VkImageSubresource *pSubresource,
|
||||
VkSubresourceLayout *pLayout)
|
||||
{
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_CreateImageView(VkDevice _device,
|
||||
const VkImageViewCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkImageView *pView)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
struct tu_image_view *view;
|
||||
|
||||
view = vk_alloc2(&device->alloc,
|
||||
pAllocator,
|
||||
sizeof(*view),
|
||||
8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (view == NULL)
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
tu_image_view_init(view, device, pCreateInfo);
|
||||
|
||||
*pView = tu_image_view_to_handle(view);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_DestroyImageView(VkDevice _device,
|
||||
VkImageView _iview,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_image_view, iview, _iview);
|
||||
|
||||
if (!iview)
|
||||
return;
|
||||
vk_free2(&device->alloc, pAllocator, iview);
|
||||
}
|
||||
|
||||
void
|
||||
tu_buffer_view_init(struct tu_buffer_view *view,
|
||||
struct tu_device *device,
|
||||
const VkBufferViewCreateInfo *pCreateInfo)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_buffer, buffer, pCreateInfo->buffer);
|
||||
|
||||
view->range = pCreateInfo->range == VK_WHOLE_SIZE
|
||||
? buffer->size - pCreateInfo->offset
|
||||
: pCreateInfo->range;
|
||||
view->vk_format = pCreateInfo->format;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_CreateBufferView(VkDevice _device,
|
||||
const VkBufferViewCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkBufferView *pView)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
struct tu_buffer_view *view;
|
||||
|
||||
view = vk_alloc2(&device->alloc,
|
||||
pAllocator,
|
||||
sizeof(*view),
|
||||
8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (!view)
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
tu_buffer_view_init(view, device, pCreateInfo);
|
||||
|
||||
*pView = tu_buffer_view_to_handle(view);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_DestroyBufferView(VkDevice _device,
|
||||
VkBufferView bufferView,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_buffer_view, view, bufferView);
|
||||
|
||||
if (!view)
|
||||
return;
|
||||
|
||||
vk_free2(&device->alloc, pAllocator, view);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 "tu_private.h"
|
||||
#include "nir/nir_builder.h"
|
||||
|
||||
void
|
||||
tu_CmdBlitImage(VkCommandBuffer commandBuffer,
|
||||
VkImage srcImage,
|
||||
VkImageLayout srcImageLayout,
|
||||
VkImage destImage,
|
||||
VkImageLayout destImageLayout,
|
||||
uint32_t regionCount,
|
||||
const VkImageBlit *pRegions,
|
||||
VkFilter filter)
|
||||
|
||||
{
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#include "tu_private.h"
|
||||
|
||||
void
|
||||
tu_CmdFillBuffer(VkCommandBuffer commandBuffer,
|
||||
VkBuffer dstBuffer,
|
||||
VkDeviceSize dstOffset,
|
||||
VkDeviceSize fillSize,
|
||||
uint32_t data)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdCopyBuffer(VkCommandBuffer commandBuffer,
|
||||
VkBuffer srcBuffer,
|
||||
VkBuffer destBuffer,
|
||||
uint32_t regionCount,
|
||||
const VkBufferCopy *pRegions)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdUpdateBuffer(VkCommandBuffer commandBuffer,
|
||||
VkBuffer dstBuffer,
|
||||
VkDeviceSize dstOffset,
|
||||
VkDeviceSize dataSize,
|
||||
const void *pData)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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 "tu_private.h"
|
||||
|
||||
void
|
||||
tu_CmdClearColorImage(VkCommandBuffer commandBuffer,
|
||||
VkImage image_h,
|
||||
VkImageLayout imageLayout,
|
||||
const VkClearColorValue *pColor,
|
||||
uint32_t rangeCount,
|
||||
const VkImageSubresourceRange *pRanges)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer,
|
||||
VkImage image_h,
|
||||
VkImageLayout imageLayout,
|
||||
const VkClearDepthStencilValue *pDepthStencil,
|
||||
uint32_t rangeCount,
|
||||
const VkImageSubresourceRange *pRanges)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdClearAttachments(VkCommandBuffer commandBuffer,
|
||||
uint32_t attachmentCount,
|
||||
const VkClearAttachment *pAttachments,
|
||||
uint32_t rectCount,
|
||||
const VkClearRect *pRects)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright © 2016 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 "tu_private.h"
|
||||
|
||||
static void
|
||||
meta_copy_buffer_to_image(struct tu_cmd_buffer *cmd_buffer,
|
||||
struct tu_buffer *buffer,
|
||||
struct tu_image *image,
|
||||
VkImageLayout layout,
|
||||
uint32_t regionCount,
|
||||
const VkBufferImageCopy *pRegions)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdCopyBufferToImage(VkCommandBuffer commandBuffer,
|
||||
VkBuffer srcBuffer,
|
||||
VkImage destImage,
|
||||
VkImageLayout destImageLayout,
|
||||
uint32_t regionCount,
|
||||
const VkBufferImageCopy *pRegions)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
TU_FROM_HANDLE(tu_image, dest_image, destImage);
|
||||
TU_FROM_HANDLE(tu_buffer, src_buffer, srcBuffer);
|
||||
|
||||
meta_copy_buffer_to_image(cmd_buffer,
|
||||
src_buffer,
|
||||
dest_image,
|
||||
destImageLayout,
|
||||
regionCount,
|
||||
pRegions);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_copy_image_to_buffer(struct tu_cmd_buffer *cmd_buffer,
|
||||
struct tu_buffer *buffer,
|
||||
struct tu_image *image,
|
||||
VkImageLayout layout,
|
||||
uint32_t regionCount,
|
||||
const VkBufferImageCopy *pRegions)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdCopyImageToBuffer(VkCommandBuffer commandBuffer,
|
||||
VkImage srcImage,
|
||||
VkImageLayout srcImageLayout,
|
||||
VkBuffer destBuffer,
|
||||
uint32_t regionCount,
|
||||
const VkBufferImageCopy *pRegions)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
TU_FROM_HANDLE(tu_image, src_image, srcImage);
|
||||
TU_FROM_HANDLE(tu_buffer, dst_buffer, destBuffer);
|
||||
|
||||
meta_copy_image_to_buffer(
|
||||
cmd_buffer, dst_buffer, src_image, srcImageLayout, regionCount, pRegions);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_copy_image(struct tu_cmd_buffer *cmd_buffer,
|
||||
struct tu_image *src_image,
|
||||
VkImageLayout src_image_layout,
|
||||
struct tu_image *dest_image,
|
||||
VkImageLayout dest_image_layout,
|
||||
uint32_t regionCount,
|
||||
const VkImageCopy *pRegions)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdCopyImage(VkCommandBuffer commandBuffer,
|
||||
VkImage srcImage,
|
||||
VkImageLayout srcImageLayout,
|
||||
VkImage destImage,
|
||||
VkImageLayout destImageLayout,
|
||||
uint32_t regionCount,
|
||||
const VkImageCopy *pRegions)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
TU_FROM_HANDLE(tu_image, src_image, srcImage);
|
||||
TU_FROM_HANDLE(tu_image, dest_image, destImage);
|
||||
|
||||
meta_copy_image(cmd_buffer,
|
||||
src_image,
|
||||
srcImageLayout,
|
||||
dest_image,
|
||||
destImageLayout,
|
||||
regionCount,
|
||||
pRegions);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright © 2016 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 "tu_private.h"
|
||||
#include "nir/nir_builder.h"
|
||||
#include "vk_format.h"
|
||||
|
||||
void
|
||||
tu_CmdResolveImage(VkCommandBuffer cmd_buffer_h,
|
||||
VkImage src_image_h,
|
||||
VkImageLayout src_image_layout,
|
||||
VkImage dest_image_h,
|
||||
VkImageLayout dest_image_layout,
|
||||
uint32_t region_count,
|
||||
const VkImageResolve *regions)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,414 @@
|
|||
/*
|
||||
* Copyright © 2016 Red Hat.
|
||||
* Copyright © 2016 Bas Nieuwenhuizen
|
||||
*
|
||||
* based in part on anv driver which is:
|
||||
* 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 "tu_private.h"
|
||||
|
||||
#include "vk_util.h"
|
||||
|
||||
VkResult
|
||||
tu_CreateRenderPass(VkDevice _device,
|
||||
const VkRenderPassCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkRenderPass *pRenderPass)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
struct tu_render_pass *pass;
|
||||
size_t size;
|
||||
size_t attachments_offset;
|
||||
VkRenderPassMultiviewCreateInfoKHR *multiview_info = NULL;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
|
||||
|
||||
size = sizeof(*pass);
|
||||
size += pCreateInfo->subpassCount * sizeof(pass->subpasses[0]);
|
||||
attachments_offset = size;
|
||||
size += pCreateInfo->attachmentCount * sizeof(pass->attachments[0]);
|
||||
|
||||
pass = vk_alloc2(
|
||||
&device->alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (pass == NULL)
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
memset(pass, 0, size);
|
||||
pass->attachment_count = pCreateInfo->attachmentCount;
|
||||
pass->subpass_count = pCreateInfo->subpassCount;
|
||||
pass->attachments = (void *)pass + attachments_offset;
|
||||
|
||||
vk_foreach_struct(ext, pCreateInfo->pNext)
|
||||
{
|
||||
switch (ext->sType) {
|
||||
case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR:
|
||||
multiview_info = (VkRenderPassMultiviewCreateInfoKHR *)ext;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
|
||||
struct tu_render_pass_attachment *att = &pass->attachments[i];
|
||||
|
||||
att->format = pCreateInfo->pAttachments[i].format;
|
||||
att->samples = pCreateInfo->pAttachments[i].samples;
|
||||
att->load_op = pCreateInfo->pAttachments[i].loadOp;
|
||||
att->stencil_load_op = pCreateInfo->pAttachments[i].stencilLoadOp;
|
||||
att->initial_layout = pCreateInfo->pAttachments[i].initialLayout;
|
||||
att->final_layout = pCreateInfo->pAttachments[i].finalLayout;
|
||||
// att->store_op = pCreateInfo->pAttachments[i].storeOp;
|
||||
// att->stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
|
||||
}
|
||||
uint32_t subpass_attachment_count = 0;
|
||||
struct tu_subpass_attachment *p;
|
||||
for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
|
||||
const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i];
|
||||
|
||||
subpass_attachment_count +=
|
||||
desc->inputAttachmentCount + desc->colorAttachmentCount +
|
||||
(desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
|
||||
(desc->pDepthStencilAttachment != NULL);
|
||||
}
|
||||
|
||||
if (subpass_attachment_count) {
|
||||
pass->subpass_attachments = vk_alloc2(
|
||||
&device->alloc,
|
||||
pAllocator,
|
||||
subpass_attachment_count * sizeof(struct tu_subpass_attachment),
|
||||
8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (pass->subpass_attachments == NULL) {
|
||||
vk_free2(&device->alloc, pAllocator, pass);
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
}
|
||||
} else
|
||||
pass->subpass_attachments = NULL;
|
||||
|
||||
p = pass->subpass_attachments;
|
||||
for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
|
||||
const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i];
|
||||
uint32_t color_sample_count = 1, depth_sample_count = 1;
|
||||
struct tu_subpass *subpass = &pass->subpasses[i];
|
||||
|
||||
subpass->input_count = desc->inputAttachmentCount;
|
||||
subpass->color_count = desc->colorAttachmentCount;
|
||||
if (multiview_info)
|
||||
subpass->view_mask = multiview_info->pViewMasks[i];
|
||||
|
||||
if (desc->inputAttachmentCount > 0) {
|
||||
subpass->input_attachments = p;
|
||||
p += desc->inputAttachmentCount;
|
||||
|
||||
for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) {
|
||||
subpass->input_attachments[j] = (struct tu_subpass_attachment){
|
||||
.attachment = desc->pInputAttachments[j].attachment,
|
||||
.layout = desc->pInputAttachments[j].layout,
|
||||
};
|
||||
if (desc->pInputAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
|
||||
pass->attachments[desc->pInputAttachments[j].attachment]
|
||||
.view_mask |= subpass->view_mask;
|
||||
}
|
||||
}
|
||||
|
||||
if (desc->colorAttachmentCount > 0) {
|
||||
subpass->color_attachments = p;
|
||||
p += desc->colorAttachmentCount;
|
||||
|
||||
for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
|
||||
subpass->color_attachments[j] = (struct tu_subpass_attachment){
|
||||
.attachment = desc->pColorAttachments[j].attachment,
|
||||
.layout = desc->pColorAttachments[j].layout,
|
||||
};
|
||||
if (desc->pColorAttachments[j].attachment != VK_ATTACHMENT_UNUSED) {
|
||||
pass->attachments[desc->pColorAttachments[j].attachment]
|
||||
.view_mask |= subpass->view_mask;
|
||||
color_sample_count =
|
||||
pCreateInfo
|
||||
->pAttachments[desc->pColorAttachments[j].attachment]
|
||||
.samples;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subpass->has_resolve = false;
|
||||
if (desc->pResolveAttachments) {
|
||||
subpass->resolve_attachments = p;
|
||||
p += desc->colorAttachmentCount;
|
||||
|
||||
for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
|
||||
uint32_t a = desc->pResolveAttachments[j].attachment;
|
||||
subpass->resolve_attachments[j] = (struct tu_subpass_attachment){
|
||||
.attachment = desc->pResolveAttachments[j].attachment,
|
||||
.layout = desc->pResolveAttachments[j].layout,
|
||||
};
|
||||
if (a != VK_ATTACHMENT_UNUSED) {
|
||||
subpass->has_resolve = true;
|
||||
pass->attachments[desc->pResolveAttachments[j].attachment]
|
||||
.view_mask |= subpass->view_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (desc->pDepthStencilAttachment) {
|
||||
subpass->depth_stencil_attachment = (struct tu_subpass_attachment){
|
||||
.attachment = desc->pDepthStencilAttachment->attachment,
|
||||
.layout = desc->pDepthStencilAttachment->layout,
|
||||
};
|
||||
if (desc->pDepthStencilAttachment->attachment !=
|
||||
VK_ATTACHMENT_UNUSED) {
|
||||
pass->attachments[desc->pDepthStencilAttachment->attachment]
|
||||
.view_mask |= subpass->view_mask;
|
||||
depth_sample_count =
|
||||
pCreateInfo
|
||||
->pAttachments[desc->pDepthStencilAttachment->attachment]
|
||||
.samples;
|
||||
}
|
||||
} else {
|
||||
subpass->depth_stencil_attachment.attachment = VK_ATTACHMENT_UNUSED;
|
||||
}
|
||||
|
||||
subpass->max_sample_count = MAX2(color_sample_count, depth_sample_count);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < pCreateInfo->dependencyCount; ++i) {
|
||||
uint32_t dst = pCreateInfo->pDependencies[i].dstSubpass;
|
||||
if (dst == VK_SUBPASS_EXTERNAL) {
|
||||
pass->end_barrier.src_stage_mask =
|
||||
pCreateInfo->pDependencies[i].srcStageMask;
|
||||
pass->end_barrier.src_access_mask =
|
||||
pCreateInfo->pDependencies[i].srcAccessMask;
|
||||
pass->end_barrier.dst_access_mask =
|
||||
pCreateInfo->pDependencies[i].dstAccessMask;
|
||||
} else {
|
||||
pass->subpasses[dst].start_barrier.src_stage_mask =
|
||||
pCreateInfo->pDependencies[i].srcStageMask;
|
||||
pass->subpasses[dst].start_barrier.src_access_mask =
|
||||
pCreateInfo->pDependencies[i].srcAccessMask;
|
||||
pass->subpasses[dst].start_barrier.dst_access_mask =
|
||||
pCreateInfo->pDependencies[i].dstAccessMask;
|
||||
}
|
||||
}
|
||||
|
||||
*pRenderPass = tu_render_pass_to_handle(pass);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_CreateRenderPass2KHR(VkDevice _device,
|
||||
const VkRenderPassCreateInfo2KHR *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkRenderPass *pRenderPass)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
struct tu_render_pass *pass;
|
||||
size_t size;
|
||||
size_t attachments_offset;
|
||||
|
||||
assert(pCreateInfo->sType ==
|
||||
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR);
|
||||
|
||||
size = sizeof(*pass);
|
||||
size += pCreateInfo->subpassCount * sizeof(pass->subpasses[0]);
|
||||
attachments_offset = size;
|
||||
size += pCreateInfo->attachmentCount * sizeof(pass->attachments[0]);
|
||||
|
||||
pass = vk_alloc2(
|
||||
&device->alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (pass == NULL)
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
memset(pass, 0, size);
|
||||
pass->attachment_count = pCreateInfo->attachmentCount;
|
||||
pass->subpass_count = pCreateInfo->subpassCount;
|
||||
pass->attachments = (void *)pass + attachments_offset;
|
||||
|
||||
for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
|
||||
struct tu_render_pass_attachment *att = &pass->attachments[i];
|
||||
|
||||
att->format = pCreateInfo->pAttachments[i].format;
|
||||
att->samples = pCreateInfo->pAttachments[i].samples;
|
||||
att->load_op = pCreateInfo->pAttachments[i].loadOp;
|
||||
att->stencil_load_op = pCreateInfo->pAttachments[i].stencilLoadOp;
|
||||
att->initial_layout = pCreateInfo->pAttachments[i].initialLayout;
|
||||
att->final_layout = pCreateInfo->pAttachments[i].finalLayout;
|
||||
// att->store_op = pCreateInfo->pAttachments[i].storeOp;
|
||||
// att->stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
|
||||
}
|
||||
uint32_t subpass_attachment_count = 0;
|
||||
struct tu_subpass_attachment *p;
|
||||
for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
|
||||
const VkSubpassDescription2KHR *desc = &pCreateInfo->pSubpasses[i];
|
||||
|
||||
subpass_attachment_count +=
|
||||
desc->inputAttachmentCount + desc->colorAttachmentCount +
|
||||
(desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
|
||||
(desc->pDepthStencilAttachment != NULL);
|
||||
}
|
||||
|
||||
if (subpass_attachment_count) {
|
||||
pass->subpass_attachments = vk_alloc2(
|
||||
&device->alloc,
|
||||
pAllocator,
|
||||
subpass_attachment_count * sizeof(struct tu_subpass_attachment),
|
||||
8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (pass->subpass_attachments == NULL) {
|
||||
vk_free2(&device->alloc, pAllocator, pass);
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
}
|
||||
} else
|
||||
pass->subpass_attachments = NULL;
|
||||
|
||||
p = pass->subpass_attachments;
|
||||
for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
|
||||
const VkSubpassDescription2KHR *desc = &pCreateInfo->pSubpasses[i];
|
||||
uint32_t color_sample_count = 1, depth_sample_count = 1;
|
||||
struct tu_subpass *subpass = &pass->subpasses[i];
|
||||
|
||||
subpass->input_count = desc->inputAttachmentCount;
|
||||
subpass->color_count = desc->colorAttachmentCount;
|
||||
subpass->view_mask = desc->viewMask;
|
||||
|
||||
if (desc->inputAttachmentCount > 0) {
|
||||
subpass->input_attachments = p;
|
||||
p += desc->inputAttachmentCount;
|
||||
|
||||
for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) {
|
||||
subpass->input_attachments[j] = (struct tu_subpass_attachment){
|
||||
.attachment = desc->pInputAttachments[j].attachment,
|
||||
.layout = desc->pInputAttachments[j].layout,
|
||||
};
|
||||
if (desc->pInputAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
|
||||
pass->attachments[desc->pInputAttachments[j].attachment]
|
||||
.view_mask |= subpass->view_mask;
|
||||
}
|
||||
}
|
||||
|
||||
if (desc->colorAttachmentCount > 0) {
|
||||
subpass->color_attachments = p;
|
||||
p += desc->colorAttachmentCount;
|
||||
|
||||
for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
|
||||
subpass->color_attachments[j] = (struct tu_subpass_attachment){
|
||||
.attachment = desc->pColorAttachments[j].attachment,
|
||||
.layout = desc->pColorAttachments[j].layout,
|
||||
};
|
||||
if (desc->pColorAttachments[j].attachment != VK_ATTACHMENT_UNUSED) {
|
||||
pass->attachments[desc->pColorAttachments[j].attachment]
|
||||
.view_mask |= subpass->view_mask;
|
||||
color_sample_count =
|
||||
pCreateInfo
|
||||
->pAttachments[desc->pColorAttachments[j].attachment]
|
||||
.samples;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subpass->has_resolve = false;
|
||||
if (desc->pResolveAttachments) {
|
||||
subpass->resolve_attachments = p;
|
||||
p += desc->colorAttachmentCount;
|
||||
|
||||
for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
|
||||
uint32_t a = desc->pResolveAttachments[j].attachment;
|
||||
subpass->resolve_attachments[j] = (struct tu_subpass_attachment){
|
||||
.attachment = desc->pResolveAttachments[j].attachment,
|
||||
.layout = desc->pResolveAttachments[j].layout,
|
||||
};
|
||||
if (a != VK_ATTACHMENT_UNUSED) {
|
||||
subpass->has_resolve = true;
|
||||
pass->attachments[desc->pResolveAttachments[j].attachment]
|
||||
.view_mask |= subpass->view_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (desc->pDepthStencilAttachment) {
|
||||
subpass->depth_stencil_attachment = (struct tu_subpass_attachment){
|
||||
.attachment = desc->pDepthStencilAttachment->attachment,
|
||||
.layout = desc->pDepthStencilAttachment->layout,
|
||||
};
|
||||
if (desc->pDepthStencilAttachment->attachment !=
|
||||
VK_ATTACHMENT_UNUSED) {
|
||||
pass->attachments[desc->pDepthStencilAttachment->attachment]
|
||||
.view_mask |= subpass->view_mask;
|
||||
depth_sample_count =
|
||||
pCreateInfo
|
||||
->pAttachments[desc->pDepthStencilAttachment->attachment]
|
||||
.samples;
|
||||
}
|
||||
} else {
|
||||
subpass->depth_stencil_attachment.attachment = VK_ATTACHMENT_UNUSED;
|
||||
}
|
||||
|
||||
subpass->max_sample_count = MAX2(color_sample_count, depth_sample_count);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < pCreateInfo->dependencyCount; ++i) {
|
||||
uint32_t dst = pCreateInfo->pDependencies[i].dstSubpass;
|
||||
if (dst == VK_SUBPASS_EXTERNAL) {
|
||||
pass->end_barrier.src_stage_mask =
|
||||
pCreateInfo->pDependencies[i].srcStageMask;
|
||||
pass->end_barrier.src_access_mask =
|
||||
pCreateInfo->pDependencies[i].srcAccessMask;
|
||||
pass->end_barrier.dst_access_mask =
|
||||
pCreateInfo->pDependencies[i].dstAccessMask;
|
||||
} else {
|
||||
pass->subpasses[dst].start_barrier.src_stage_mask =
|
||||
pCreateInfo->pDependencies[i].srcStageMask;
|
||||
pass->subpasses[dst].start_barrier.src_access_mask =
|
||||
pCreateInfo->pDependencies[i].srcAccessMask;
|
||||
pass->subpasses[dst].start_barrier.dst_access_mask =
|
||||
pCreateInfo->pDependencies[i].dstAccessMask;
|
||||
}
|
||||
}
|
||||
|
||||
*pRenderPass = tu_render_pass_to_handle(pass);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_DestroyRenderPass(VkDevice _device,
|
||||
VkRenderPass _pass,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_render_pass, pass, _pass);
|
||||
|
||||
if (!_pass)
|
||||
return;
|
||||
vk_free2(&device->alloc, pAllocator, pass->subpass_attachments);
|
||||
vk_free2(&device->alloc, pAllocator, pass);
|
||||
}
|
||||
|
||||
void
|
||||
tu_GetRenderAreaGranularity(VkDevice device,
|
||||
VkRenderPass renderPass,
|
||||
VkExtent2D *pGranularity)
|
||||
{
|
||||
pGranularity->width = 1;
|
||||
pGranularity->height = 1;
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright © 2016 Red Hat.
|
||||
* Copyright © 2016 Bas Nieuwenhuizen
|
||||
*
|
||||
* based in part on anv driver which is:
|
||||
* 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 "tu_private.h"
|
||||
#include "nir/nir.h"
|
||||
#include "nir/nir_builder.h"
|
||||
#include "spirv/nir_spirv.h"
|
||||
#include "util/mesa-sha1.h"
|
||||
#include "util/u_atomic.h"
|
||||
#include "vk_util.h"
|
||||
|
||||
#include "main/menums.h"
|
||||
#include "util/debug.h"
|
||||
#include "vk_format.h"
|
||||
|
||||
VkResult
|
||||
tu_graphics_pipeline_create(
|
||||
VkDevice _device,
|
||||
VkPipelineCache _cache,
|
||||
const VkGraphicsPipelineCreateInfo *pCreateInfo,
|
||||
const struct tu_graphics_pipeline_create_info *extra,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkPipeline *pPipeline)
|
||||
{
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_CreateGraphicsPipelines(VkDevice _device,
|
||||
VkPipelineCache pipelineCache,
|
||||
uint32_t count,
|
||||
const VkGraphicsPipelineCreateInfo *pCreateInfos,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkPipeline *pPipelines)
|
||||
{
|
||||
VkResult result = VK_SUCCESS;
|
||||
unsigned i = 0;
|
||||
|
||||
for (; i < count; i++) {
|
||||
VkResult r;
|
||||
r = tu_graphics_pipeline_create(_device,
|
||||
pipelineCache,
|
||||
&pCreateInfos[i],
|
||||
NULL,
|
||||
pAllocator,
|
||||
&pPipelines[i]);
|
||||
if (r != VK_SUCCESS) {
|
||||
result = r;
|
||||
pPipelines[i] = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
tu_compute_pipeline_create(VkDevice _device,
|
||||
VkPipelineCache _cache,
|
||||
const VkComputePipelineCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkPipeline *pPipeline)
|
||||
{
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_CreateComputePipelines(VkDevice _device,
|
||||
VkPipelineCache pipelineCache,
|
||||
uint32_t count,
|
||||
const VkComputePipelineCreateInfo *pCreateInfos,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkPipeline *pPipelines)
|
||||
{
|
||||
VkResult result = VK_SUCCESS;
|
||||
|
||||
unsigned i = 0;
|
||||
for (; i < count; i++) {
|
||||
VkResult r;
|
||||
r = tu_compute_pipeline_create(
|
||||
_device, pipelineCache, &pCreateInfos[i], pAllocator, &pPipelines[i]);
|
||||
if (r != VK_SUCCESS) {
|
||||
result = r;
|
||||
pPipelines[i] = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* 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 "tu_private.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/disk_cache.h"
|
||||
#include "util/mesa-sha1.h"
|
||||
#include "util/u_atomic.h"
|
||||
|
||||
struct cache_entry_variant_info
|
||||
{
|
||||
};
|
||||
|
||||
struct cache_entry
|
||||
{
|
||||
union
|
||||
{
|
||||
unsigned char sha1[20];
|
||||
uint32_t sha1_dw[5];
|
||||
};
|
||||
uint32_t code_sizes[MESA_SHADER_STAGES];
|
||||
struct tu_shader_variant *variants[MESA_SHADER_STAGES];
|
||||
char code[0];
|
||||
};
|
||||
|
||||
void
|
||||
tu_pipeline_cache_init(struct tu_pipeline_cache *cache,
|
||||
struct tu_device *device)
|
||||
{
|
||||
cache->device = device;
|
||||
pthread_mutex_init(&cache->mutex, NULL);
|
||||
|
||||
cache->modified = false;
|
||||
cache->kernel_count = 0;
|
||||
cache->total_size = 0;
|
||||
cache->table_size = 1024;
|
||||
const size_t byte_size = cache->table_size * sizeof(cache->hash_table[0]);
|
||||
cache->hash_table = malloc(byte_size);
|
||||
|
||||
/* We don't consider allocation failure fatal, we just start with a 0-sized
|
||||
* cache. Disable caching when we want to keep shader debug info, since
|
||||
* we don't get the debug info on cached shaders. */
|
||||
if (cache->hash_table == NULL)
|
||||
cache->table_size = 0;
|
||||
else
|
||||
memset(cache->hash_table, 0, byte_size);
|
||||
}
|
||||
|
||||
void
|
||||
tu_pipeline_cache_finish(struct tu_pipeline_cache *cache)
|
||||
{
|
||||
for (unsigned i = 0; i < cache->table_size; ++i)
|
||||
if (cache->hash_table[i]) {
|
||||
vk_free(&cache->alloc, cache->hash_table[i]);
|
||||
}
|
||||
pthread_mutex_destroy(&cache->mutex);
|
||||
free(cache->hash_table);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
entry_size(struct cache_entry *entry)
|
||||
{
|
||||
size_t ret = sizeof(*entry);
|
||||
for (int i = 0; i < MESA_SHADER_STAGES; ++i)
|
||||
if (entry->code_sizes[i])
|
||||
ret += sizeof(struct cache_entry_variant_info) + entry->code_sizes[i];
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
tu_hash_shaders(unsigned char *hash,
|
||||
const VkPipelineShaderStageCreateInfo **stages,
|
||||
const struct tu_pipeline_layout *layout,
|
||||
const struct tu_pipeline_key *key,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct mesa_sha1 ctx;
|
||||
|
||||
_mesa_sha1_init(&ctx);
|
||||
if (key)
|
||||
_mesa_sha1_update(&ctx, key, sizeof(*key));
|
||||
if (layout)
|
||||
_mesa_sha1_update(&ctx, layout->sha1, sizeof(layout->sha1));
|
||||
|
||||
for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
|
||||
if (stages[i]) {
|
||||
TU_FROM_HANDLE(tu_shader_module, module, stages[i]->module);
|
||||
const VkSpecializationInfo *spec_info = stages[i]->pSpecializationInfo;
|
||||
|
||||
_mesa_sha1_update(&ctx, module->sha1, sizeof(module->sha1));
|
||||
_mesa_sha1_update(&ctx, stages[i]->pName, strlen(stages[i]->pName));
|
||||
if (spec_info) {
|
||||
_mesa_sha1_update(&ctx,
|
||||
spec_info->pMapEntries,
|
||||
spec_info->mapEntryCount *
|
||||
sizeof spec_info->pMapEntries[0]);
|
||||
_mesa_sha1_update(&ctx, spec_info->pData, spec_info->dataSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
_mesa_sha1_update(&ctx, &flags, 4);
|
||||
_mesa_sha1_final(&ctx, hash);
|
||||
}
|
||||
|
||||
static struct cache_entry *
|
||||
tu_pipeline_cache_search_unlocked(struct tu_pipeline_cache *cache,
|
||||
const unsigned char *sha1)
|
||||
{
|
||||
const uint32_t mask = cache->table_size - 1;
|
||||
const uint32_t start = (*(uint32_t *)sha1);
|
||||
|
||||
if (cache->table_size == 0)
|
||||
return NULL;
|
||||
|
||||
for (uint32_t i = 0; i < cache->table_size; i++) {
|
||||
const uint32_t index = (start + i) & mask;
|
||||
struct cache_entry *entry = cache->hash_table[index];
|
||||
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
if (memcmp(entry->sha1, sha1, sizeof(entry->sha1)) == 0) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
unreachable("hash table should never be full");
|
||||
}
|
||||
|
||||
static struct cache_entry *
|
||||
tu_pipeline_cache_search(struct tu_pipeline_cache *cache,
|
||||
const unsigned char *sha1)
|
||||
{
|
||||
struct cache_entry *entry;
|
||||
|
||||
pthread_mutex_lock(&cache->mutex);
|
||||
|
||||
entry = tu_pipeline_cache_search_unlocked(cache, sha1);
|
||||
|
||||
pthread_mutex_unlock(&cache->mutex);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static void
|
||||
tu_pipeline_cache_set_entry(struct tu_pipeline_cache *cache,
|
||||
struct cache_entry *entry)
|
||||
{
|
||||
const uint32_t mask = cache->table_size - 1;
|
||||
const uint32_t start = entry->sha1_dw[0];
|
||||
|
||||
/* We'll always be able to insert when we get here. */
|
||||
assert(cache->kernel_count < cache->table_size / 2);
|
||||
|
||||
for (uint32_t i = 0; i < cache->table_size; i++) {
|
||||
const uint32_t index = (start + i) & mask;
|
||||
if (!cache->hash_table[index]) {
|
||||
cache->hash_table[index] = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cache->total_size += entry_size(entry);
|
||||
cache->kernel_count++;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
tu_pipeline_cache_grow(struct tu_pipeline_cache *cache)
|
||||
{
|
||||
const uint32_t table_size = cache->table_size * 2;
|
||||
const uint32_t old_table_size = cache->table_size;
|
||||
const size_t byte_size = table_size * sizeof(cache->hash_table[0]);
|
||||
struct cache_entry **table;
|
||||
struct cache_entry **old_table = cache->hash_table;
|
||||
|
||||
table = malloc(byte_size);
|
||||
if (table == NULL)
|
||||
return vk_error(cache->device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
cache->hash_table = table;
|
||||
cache->table_size = table_size;
|
||||
cache->kernel_count = 0;
|
||||
cache->total_size = 0;
|
||||
|
||||
memset(cache->hash_table, 0, byte_size);
|
||||
for (uint32_t i = 0; i < old_table_size; i++) {
|
||||
struct cache_entry *entry = old_table[i];
|
||||
if (!entry)
|
||||
continue;
|
||||
|
||||
tu_pipeline_cache_set_entry(cache, entry);
|
||||
}
|
||||
|
||||
free(old_table);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
tu_pipeline_cache_add_entry(struct tu_pipeline_cache *cache,
|
||||
struct cache_entry *entry)
|
||||
{
|
||||
if (cache->kernel_count == cache->table_size / 2)
|
||||
tu_pipeline_cache_grow(cache);
|
||||
|
||||
/* Failing to grow that hash table isn't fatal, but may mean we don't
|
||||
* have enough space to add this new kernel. Only add it if there's room.
|
||||
*/
|
||||
if (cache->kernel_count < cache->table_size / 2)
|
||||
tu_pipeline_cache_set_entry(cache, entry);
|
||||
}
|
||||
|
||||
struct cache_header
|
||||
{
|
||||
uint32_t header_size;
|
||||
uint32_t header_version;
|
||||
uint32_t vendor_id;
|
||||
uint32_t device_id;
|
||||
uint8_t uuid[VK_UUID_SIZE];
|
||||
};
|
||||
|
||||
void
|
||||
tu_pipeline_cache_load(struct tu_pipeline_cache *cache,
|
||||
const void *data,
|
||||
size_t size)
|
||||
{
|
||||
struct tu_device *device = cache->device;
|
||||
struct cache_header header;
|
||||
|
||||
if (size < sizeof(header))
|
||||
return;
|
||||
memcpy(&header, data, sizeof(header));
|
||||
if (header.header_size < sizeof(header))
|
||||
return;
|
||||
if (header.header_version != VK_PIPELINE_CACHE_HEADER_VERSION_ONE)
|
||||
return;
|
||||
if (header.vendor_id != 0 /* TODO */)
|
||||
return;
|
||||
if (header.device_id != 0 /* TODO */)
|
||||
return;
|
||||
if (memcmp(header.uuid, device->physical_device->cache_uuid, VK_UUID_SIZE) !=
|
||||
0)
|
||||
return;
|
||||
|
||||
char *end = (void *)data + size;
|
||||
char *p = (void *)data + header.header_size;
|
||||
|
||||
while (end - p >= sizeof(struct cache_entry)) {
|
||||
struct cache_entry *entry = (struct cache_entry *)p;
|
||||
struct cache_entry *dest_entry;
|
||||
size_t size = entry_size(entry);
|
||||
if (end - p < size)
|
||||
break;
|
||||
|
||||
dest_entry =
|
||||
vk_alloc(&cache->alloc, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_CACHE);
|
||||
if (dest_entry) {
|
||||
memcpy(dest_entry, entry, size);
|
||||
for (int i = 0; i < MESA_SHADER_STAGES; ++i)
|
||||
dest_entry->variants[i] = NULL;
|
||||
tu_pipeline_cache_add_entry(cache, dest_entry);
|
||||
}
|
||||
p += size;
|
||||
}
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_CreatePipelineCache(VkDevice _device,
|
||||
const VkPipelineCacheCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkPipelineCache *pPipelineCache)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
struct tu_pipeline_cache *cache;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO);
|
||||
assert(pCreateInfo->flags == 0);
|
||||
|
||||
cache = vk_alloc2(&device->alloc,
|
||||
pAllocator,
|
||||
sizeof(*cache),
|
||||
8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (cache == NULL)
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
if (pAllocator)
|
||||
cache->alloc = *pAllocator;
|
||||
else
|
||||
cache->alloc = device->alloc;
|
||||
|
||||
tu_pipeline_cache_init(cache, device);
|
||||
|
||||
if (pCreateInfo->initialDataSize > 0) {
|
||||
tu_pipeline_cache_load(
|
||||
cache, pCreateInfo->pInitialData, pCreateInfo->initialDataSize);
|
||||
}
|
||||
|
||||
*pPipelineCache = tu_pipeline_cache_to_handle(cache);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_DestroyPipelineCache(VkDevice _device,
|
||||
VkPipelineCache _cache,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_pipeline_cache, cache, _cache);
|
||||
|
||||
if (!cache)
|
||||
return;
|
||||
tu_pipeline_cache_finish(cache);
|
||||
|
||||
vk_free2(&device->alloc, pAllocator, cache);
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_GetPipelineCacheData(VkDevice _device,
|
||||
VkPipelineCache _cache,
|
||||
size_t *pDataSize,
|
||||
void *pData)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_pipeline_cache, cache, _cache);
|
||||
struct cache_header *header;
|
||||
VkResult result = VK_SUCCESS;
|
||||
|
||||
pthread_mutex_lock(&cache->mutex);
|
||||
|
||||
const size_t size = sizeof(*header) + cache->total_size;
|
||||
if (pData == NULL) {
|
||||
pthread_mutex_unlock(&cache->mutex);
|
||||
*pDataSize = size;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
if (*pDataSize < sizeof(*header)) {
|
||||
pthread_mutex_unlock(&cache->mutex);
|
||||
*pDataSize = 0;
|
||||
return VK_INCOMPLETE;
|
||||
}
|
||||
void *p = pData, *end = pData + *pDataSize;
|
||||
header = p;
|
||||
header->header_size = sizeof(*header);
|
||||
header->header_version = VK_PIPELINE_CACHE_HEADER_VERSION_ONE;
|
||||
header->vendor_id = 0 /* TODO */;
|
||||
header->device_id = 0 /* TODO */;
|
||||
memcpy(header->uuid, device->physical_device->cache_uuid, VK_UUID_SIZE);
|
||||
p += header->header_size;
|
||||
|
||||
struct cache_entry *entry;
|
||||
for (uint32_t i = 0; i < cache->table_size; i++) {
|
||||
if (!cache->hash_table[i])
|
||||
continue;
|
||||
entry = cache->hash_table[i];
|
||||
const uint32_t size = entry_size(entry);
|
||||
if (end < p + size) {
|
||||
result = VK_INCOMPLETE;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(p, entry, size);
|
||||
for (int j = 0; j < MESA_SHADER_STAGES; ++j)
|
||||
((struct cache_entry *)p)->variants[j] = NULL;
|
||||
p += size;
|
||||
}
|
||||
*pDataSize = p - pData;
|
||||
|
||||
pthread_mutex_unlock(&cache->mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
tu_pipeline_cache_merge(struct tu_pipeline_cache *dst,
|
||||
struct tu_pipeline_cache *src)
|
||||
{
|
||||
for (uint32_t i = 0; i < src->table_size; i++) {
|
||||
struct cache_entry *entry = src->hash_table[i];
|
||||
if (!entry || tu_pipeline_cache_search(dst, entry->sha1))
|
||||
continue;
|
||||
|
||||
tu_pipeline_cache_add_entry(dst, entry);
|
||||
|
||||
src->hash_table[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_MergePipelineCaches(VkDevice _device,
|
||||
VkPipelineCache destCache,
|
||||
uint32_t srcCacheCount,
|
||||
const VkPipelineCache *pSrcCaches)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_pipeline_cache, dst, destCache);
|
||||
|
||||
for (uint32_t i = 0; i < srcCacheCount; i++) {
|
||||
TU_FROM_HANDLE(tu_pipeline_cache, src, pSrcCaches[i]);
|
||||
|
||||
tu_pipeline_cache_merge(dst, src);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyrigh 2016 Red Hat Inc.
|
||||
* Based on anv:
|
||||
* 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 <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tu_private.h"
|
||||
#include "nir/nir_builder.h"
|
||||
|
||||
VkResult
|
||||
tu_CreateQueryPool(VkDevice _device,
|
||||
const VkQueryPoolCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkQueryPool *pQueryPool)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
struct tu_query_pool *pool = vk_alloc2(&device->alloc,
|
||||
pAllocator,
|
||||
sizeof(*pool),
|
||||
8,
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
|
||||
if (!pool)
|
||||
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
*pQueryPool = tu_query_pool_to_handle(pool);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_DestroyQueryPool(VkDevice _device,
|
||||
VkQueryPool _pool,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
TU_FROM_HANDLE(tu_device, device, _device);
|
||||
TU_FROM_HANDLE(tu_query_pool, pool, _pool);
|
||||
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
vk_free2(&device->alloc, pAllocator, pool);
|
||||
}
|
||||
|
||||
VkResult
|
||||
tu_GetQueryPoolResults(VkDevice _device,
|
||||
VkQueryPool queryPool,
|
||||
uint32_t firstQuery,
|
||||
uint32_t queryCount,
|
||||
size_t dataSize,
|
||||
void *pData,
|
||||
VkDeviceSize stride,
|
||||
VkQueryResultFlags flags)
|
||||
{
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer,
|
||||
VkQueryPool queryPool,
|
||||
uint32_t firstQuery,
|
||||
uint32_t queryCount,
|
||||
VkBuffer dstBuffer,
|
||||
VkDeviceSize dstOffset,
|
||||
VkDeviceSize stride,
|
||||
VkQueryResultFlags flags)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdResetQueryPool(VkCommandBuffer commandBuffer,
|
||||
VkQueryPool queryPool,
|
||||
uint32_t firstQuery,
|
||||
uint32_t queryCount)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdBeginQuery(VkCommandBuffer commandBuffer,
|
||||
VkQueryPool queryPool,
|
||||
uint32_t query,
|
||||
VkQueryControlFlags flags)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdEndQuery(VkCommandBuffer commandBuffer,
|
||||
VkQueryPool queryPool,
|
||||
uint32_t query)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
tu_CmdWriteTimestamp(VkCommandBuffer commandBuffer,
|
||||
VkPipelineStageFlagBits pipelineStage,
|
||||
VkQueryPool queryPool,
|
||||
uint32_t query)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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 <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tu_private.h"
|
||||
#include "vk_enum_to_str.h"
|
||||
|
||||
#include "util/u_math.h"
|
||||
|
||||
/** Log an error message. */
|
||||
void tu_printflike(1, 2) tu_loge(const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
tu_loge_v(format, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
/** \see tu_loge() */
|
||||
void
|
||||
tu_loge_v(const char *format, va_list va)
|
||||
{
|
||||
fprintf(stderr, "vk: error: ");
|
||||
vfprintf(stderr, format, va);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
/** Log an error message. */
|
||||
void tu_printflike(1, 2) tu_logi(const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
tu_logi_v(format, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
/** \see tu_logi() */
|
||||
void
|
||||
tu_logi_v(const char *format, va_list va)
|
||||
{
|
||||
fprintf(stderr, "tu: info: ");
|
||||
vfprintf(stderr, format, va);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void tu_printflike(3, 4)
|
||||
__tu_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);
|
||||
}
|
||||
|
||||
VkResult
|
||||
__vk_errorf(struct tu_instance *instance,
|
||||
VkResult error,
|
||||
const char *file,
|
||||
int line,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
char buffer[256];
|
||||
|
||||
const char *error_str = vk_Result_to_str(error);
|
||||
|
||||
#ifndef DEBUG
|
||||
return error;
|
||||
#endif
|
||||
|
||||
if (format) {
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "%s:%d: %s (%s)\n", file, line, buffer, error_str);
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d: %s\n", file, line, error_str);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef TU_UTIL_H
|
||||
#define TU_UTIL_H
|
||||
|
||||
#ifdef HAVE___BUILTIN_POPCOUNT
|
||||
#define util_bitcount(i) __builtin_popcount(i)
|
||||
#else
|
||||
extern unsigned int
|
||||
util_bitcount(unsigned int n);
|
||||
#endif
|
||||
|
||||
#endif /* TU_UTIL_H */
|
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
* Copyright © 2016 Red Hat.
|
||||
* Copyright © 2016 Bas Nieuwenhuizen
|
||||
*
|
||||
* Based on u_format.h which is:
|
||||
* Copyright 2009-2010 Vmware, Inc.
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef VK_FORMAT_H
|
||||
#define VK_FORMAT_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <util/macros.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
enum vk_format_layout
|
||||
{
|
||||
/**
|
||||
* Formats with vk_format_block::width == vk_format_block::height == 1
|
||||
* that can be described as an ordinary data structure.
|
||||
*/
|
||||
VK_FORMAT_LAYOUT_PLAIN = 0,
|
||||
|
||||
/**
|
||||
* Formats with sub-sampled channels.
|
||||
*
|
||||
* This is for formats like YVYU where there is less than one sample per
|
||||
* pixel.
|
||||
*/
|
||||
VK_FORMAT_LAYOUT_SUBSAMPLED = 3,
|
||||
|
||||
/**
|
||||
* S3 Texture Compression formats.
|
||||
*/
|
||||
VK_FORMAT_LAYOUT_S3TC = 4,
|
||||
|
||||
/**
|
||||
* Red-Green Texture Compression formats.
|
||||
*/
|
||||
VK_FORMAT_LAYOUT_RGTC = 5,
|
||||
|
||||
/**
|
||||
* Ericsson Texture Compression
|
||||
*/
|
||||
VK_FORMAT_LAYOUT_ETC = 6,
|
||||
|
||||
/**
|
||||
* BC6/7 Texture Compression
|
||||
*/
|
||||
VK_FORMAT_LAYOUT_BPTC = 7,
|
||||
|
||||
/**
|
||||
* ASTC
|
||||
*/
|
||||
VK_FORMAT_LAYOUT_ASTC = 8,
|
||||
|
||||
/**
|
||||
* Everything else that doesn't fit in any of the above layouts.
|
||||
*/
|
||||
VK_FORMAT_LAYOUT_OTHER = 9
|
||||
};
|
||||
|
||||
struct vk_format_block
|
||||
{
|
||||
/** Block width in pixels */
|
||||
unsigned width;
|
||||
|
||||
/** Block height in pixels */
|
||||
unsigned height;
|
||||
|
||||
/** Block size in bits */
|
||||
unsigned bits;
|
||||
};
|
||||
|
||||
enum vk_format_type
|
||||
{
|
||||
VK_FORMAT_TYPE_VOID = 0,
|
||||
VK_FORMAT_TYPE_UNSIGNED = 1,
|
||||
VK_FORMAT_TYPE_SIGNED = 2,
|
||||
VK_FORMAT_TYPE_FIXED = 3,
|
||||
VK_FORMAT_TYPE_FLOAT = 4
|
||||
};
|
||||
|
||||
enum vk_format_colorspace
|
||||
{
|
||||
VK_FORMAT_COLORSPACE_RGB = 0,
|
||||
VK_FORMAT_COLORSPACE_SRGB = 1,
|
||||
VK_FORMAT_COLORSPACE_YUV = 2,
|
||||
VK_FORMAT_COLORSPACE_ZS = 3
|
||||
};
|
||||
|
||||
struct vk_format_channel_description
|
||||
{
|
||||
unsigned type : 5;
|
||||
unsigned normalized : 1;
|
||||
unsigned pure_integer : 1;
|
||||
unsigned scaled : 1;
|
||||
unsigned size : 8;
|
||||
unsigned shift : 16;
|
||||
};
|
||||
|
||||
struct vk_format_description
|
||||
{
|
||||
VkFormat format;
|
||||
const char *name;
|
||||
const char *short_name;
|
||||
|
||||
struct vk_format_block block;
|
||||
enum vk_format_layout layout;
|
||||
|
||||
unsigned nr_channels : 3;
|
||||
unsigned is_array : 1;
|
||||
unsigned is_bitmask : 1;
|
||||
unsigned is_mixed : 1;
|
||||
|
||||
struct vk_format_channel_description channel[4];
|
||||
|
||||
unsigned char swizzle[4];
|
||||
|
||||
enum vk_format_colorspace colorspace;
|
||||
};
|
||||
|
||||
extern const struct vk_format_description vk_format_description_table[];
|
||||
|
||||
const struct vk_format_description *
|
||||
vk_format_description(VkFormat format);
|
||||
|
||||
/**
|
||||
* Return total bits needed for the pixel format per block.
|
||||
*/
|
||||
static inline unsigned
|
||||
vk_format_get_blocksizebits(VkFormat format)
|
||||
{
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
|
||||
assert(desc);
|
||||
if (!desc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return desc->block.bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return bytes per block (not pixel) for the given format.
|
||||
*/
|
||||
static inline unsigned
|
||||
vk_format_get_blocksize(VkFormat format)
|
||||
{
|
||||
unsigned bits = vk_format_get_blocksizebits(format);
|
||||
unsigned bytes = bits / 8;
|
||||
|
||||
assert(bits % 8 == 0);
|
||||
assert(bytes > 0);
|
||||
if (bytes == 0) {
|
||||
bytes = 1;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
vk_format_get_blockwidth(VkFormat format)
|
||||
{
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
|
||||
assert(desc);
|
||||
if (!desc) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return desc->block.width;
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
vk_format_get_blockheight(VkFormat format)
|
||||
{
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
|
||||
assert(desc);
|
||||
if (!desc) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return desc->block.height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the first non-void channel
|
||||
* -1 if no non-void channels
|
||||
*/
|
||||
static inline int
|
||||
vk_format_get_first_non_void_channel(VkFormat format)
|
||||
{
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
if (desc->channel[i].type != VK_FORMAT_TYPE_VOID)
|
||||
break;
|
||||
|
||||
if (i == 4)
|
||||
return -1;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
enum vk_swizzle
|
||||
{
|
||||
VK_SWIZZLE_X,
|
||||
VK_SWIZZLE_Y,
|
||||
VK_SWIZZLE_Z,
|
||||
VK_SWIZZLE_W,
|
||||
VK_SWIZZLE_0,
|
||||
VK_SWIZZLE_1,
|
||||
VK_SWIZZLE_NONE,
|
||||
VK_SWIZZLE_MAX, /**< Number of enums counter (must be last) */
|
||||
};
|
||||
|
||||
static inline VkImageAspectFlags
|
||||
vk_format_aspects(VkFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case VK_FORMAT_UNDEFINED:
|
||||
return 0;
|
||||
|
||||
case VK_FORMAT_S8_UINT:
|
||||
return VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
case VK_FORMAT_D16_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
||||
case VK_FORMAT_D32_SFLOAT:
|
||||
return VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
|
||||
default:
|
||||
return VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
static inline enum vk_swizzle
|
||||
tu_swizzle_conv(VkComponentSwizzle component,
|
||||
const unsigned char chan[4],
|
||||
VkComponentSwizzle vk_swiz)
|
||||
{
|
||||
int x;
|
||||
|
||||
if (vk_swiz == VK_COMPONENT_SWIZZLE_IDENTITY)
|
||||
vk_swiz = component;
|
||||
switch (vk_swiz) {
|
||||
case VK_COMPONENT_SWIZZLE_ZERO:
|
||||
return VK_SWIZZLE_0;
|
||||
case VK_COMPONENT_SWIZZLE_ONE:
|
||||
return VK_SWIZZLE_1;
|
||||
case VK_COMPONENT_SWIZZLE_R:
|
||||
for (x = 0; x < 4; x++)
|
||||
if (chan[x] == 0)
|
||||
return x;
|
||||
return VK_SWIZZLE_0;
|
||||
case VK_COMPONENT_SWIZZLE_G:
|
||||
for (x = 0; x < 4; x++)
|
||||
if (chan[x] == 1)
|
||||
return x;
|
||||
return VK_SWIZZLE_0;
|
||||
case VK_COMPONENT_SWIZZLE_B:
|
||||
for (x = 0; x < 4; x++)
|
||||
if (chan[x] == 2)
|
||||
return x;
|
||||
return VK_SWIZZLE_0;
|
||||
case VK_COMPONENT_SWIZZLE_A:
|
||||
for (x = 0; x < 4; x++)
|
||||
if (chan[x] == 3)
|
||||
return x;
|
||||
return VK_SWIZZLE_1;
|
||||
default:
|
||||
unreachable("Illegal swizzle");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
vk_format_compose_swizzles(const VkComponentMapping *mapping,
|
||||
const unsigned char swz[4],
|
||||
enum vk_swizzle dst[4])
|
||||
{
|
||||
dst[0] = tu_swizzle_conv(VK_COMPONENT_SWIZZLE_R, swz, mapping->r);
|
||||
dst[1] = tu_swizzle_conv(VK_COMPONENT_SWIZZLE_G, swz, mapping->g);
|
||||
dst[2] = tu_swizzle_conv(VK_COMPONENT_SWIZZLE_B, swz, mapping->b);
|
||||
dst[3] = tu_swizzle_conv(VK_COMPONENT_SWIZZLE_A, swz, mapping->a);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
vk_format_is_compressed(VkFormat format)
|
||||
{
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
|
||||
assert(desc);
|
||||
if (!desc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (desc->layout) {
|
||||
case VK_FORMAT_LAYOUT_S3TC:
|
||||
case VK_FORMAT_LAYOUT_RGTC:
|
||||
case VK_FORMAT_LAYOUT_ETC:
|
||||
case VK_FORMAT_LAYOUT_BPTC:
|
||||
case VK_FORMAT_LAYOUT_ASTC:
|
||||
/* XXX add other formats in the future */
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
vk_format_has_depth(const struct vk_format_description *desc)
|
||||
{
|
||||
return desc->colorspace == VK_FORMAT_COLORSPACE_ZS &&
|
||||
desc->swizzle[0] != VK_SWIZZLE_NONE;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
vk_format_has_stencil(const struct vk_format_description *desc)
|
||||
{
|
||||
return desc->colorspace == VK_FORMAT_COLORSPACE_ZS &&
|
||||
desc->swizzle[1] != VK_SWIZZLE_NONE;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
vk_format_is_depth_or_stencil(VkFormat format)
|
||||
{
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
|
||||
assert(desc);
|
||||
if (!desc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return vk_format_has_depth(desc) || vk_format_has_stencil(desc);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
vk_format_is_depth(VkFormat format)
|
||||
{
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
|
||||
assert(desc);
|
||||
if (!desc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return vk_format_has_depth(desc);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
vk_format_is_stencil(VkFormat format)
|
||||
{
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
|
||||
assert(desc);
|
||||
if (!desc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return vk_format_has_stencil(desc);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
vk_format_is_color(VkFormat format)
|
||||
{
|
||||
return !vk_format_is_depth_or_stencil(format);
|
||||
}
|
||||
|
||||
static inline VkFormat
|
||||
vk_format_depth_only(VkFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case VK_FORMAT_D16_UNORM_S8_UINT:
|
||||
return VK_FORMAT_D16_UNORM;
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
return VK_FORMAT_X8_D24_UNORM_PACK32;
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
return VK_FORMAT_D32_SFLOAT;
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
vk_format_is_int(VkFormat format)
|
||||
{
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
int channel = vk_format_get_first_non_void_channel(format);
|
||||
|
||||
return channel >= 0 && desc->channel[channel].pure_integer;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
vk_format_is_srgb(VkFormat format)
|
||||
{
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
return desc->colorspace == VK_FORMAT_COLORSPACE_SRGB;
|
||||
}
|
||||
|
||||
static inline VkFormat
|
||||
vk_format_no_srgb(VkFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case VK_FORMAT_R8_SRGB:
|
||||
return VK_FORMAT_R8_UNORM;
|
||||
case VK_FORMAT_R8G8_SRGB:
|
||||
return VK_FORMAT_R8G8_UNORM;
|
||||
case VK_FORMAT_R8G8B8_SRGB:
|
||||
return VK_FORMAT_R8G8B8_UNORM;
|
||||
case VK_FORMAT_B8G8R8_SRGB:
|
||||
return VK_FORMAT_B8G8R8_UNORM;
|
||||
case VK_FORMAT_R8G8B8A8_SRGB:
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
case VK_FORMAT_B8G8R8A8_SRGB:
|
||||
return VK_FORMAT_B8G8R8A8_UNORM;
|
||||
case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
|
||||
return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
|
||||
case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
|
||||
return VK_FORMAT_BC1_RGB_UNORM_BLOCK;
|
||||
case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
|
||||
return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
|
||||
case VK_FORMAT_BC2_SRGB_BLOCK:
|
||||
return VK_FORMAT_BC2_UNORM_BLOCK;
|
||||
case VK_FORMAT_BC3_SRGB_BLOCK:
|
||||
return VK_FORMAT_BC3_UNORM_BLOCK;
|
||||
case VK_FORMAT_BC7_SRGB_BLOCK:
|
||||
return VK_FORMAT_BC7_UNORM_BLOCK;
|
||||
case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
|
||||
return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
|
||||
case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
|
||||
return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
|
||||
case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
|
||||
return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
|
||||
default:
|
||||
assert(!vk_format_is_srgb(format));
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
static inline VkFormat
|
||||
vk_format_stencil_only(VkFormat format)
|
||||
{
|
||||
return VK_FORMAT_S8_UINT;
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
vk_format_get_component_bits(VkFormat format,
|
||||
enum vk_format_colorspace colorspace,
|
||||
unsigned component)
|
||||
{
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
enum vk_format_colorspace desc_colorspace;
|
||||
|
||||
assert(format);
|
||||
if (!format) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(component < 4);
|
||||
|
||||
/* Treat RGB and SRGB as equivalent. */
|
||||
if (colorspace == VK_FORMAT_COLORSPACE_SRGB) {
|
||||
colorspace = VK_FORMAT_COLORSPACE_RGB;
|
||||
}
|
||||
if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) {
|
||||
desc_colorspace = VK_FORMAT_COLORSPACE_RGB;
|
||||
} else {
|
||||
desc_colorspace = desc->colorspace;
|
||||
}
|
||||
|
||||
if (desc_colorspace != colorspace) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (desc->swizzle[component]) {
|
||||
case VK_SWIZZLE_X:
|
||||
return desc->channel[0].size;
|
||||
case VK_SWIZZLE_Y:
|
||||
return desc->channel[1].size;
|
||||
case VK_SWIZZLE_Z:
|
||||
return desc->channel[2].size;
|
||||
case VK_SWIZZLE_W:
|
||||
return desc->channel[3].size;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline VkFormat
|
||||
vk_to_non_srgb_format(VkFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case VK_FORMAT_R8_SRGB:
|
||||
return VK_FORMAT_R8_UNORM;
|
||||
case VK_FORMAT_R8G8_SRGB:
|
||||
return VK_FORMAT_R8G8_UNORM;
|
||||
case VK_FORMAT_R8G8B8_SRGB:
|
||||
return VK_FORMAT_R8G8B8_UNORM;
|
||||
case VK_FORMAT_B8G8R8_SRGB:
|
||||
return VK_FORMAT_B8G8R8_UNORM;
|
||||
case VK_FORMAT_R8G8B8A8_SRGB:
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
case VK_FORMAT_B8G8R8A8_SRGB:
|
||||
return VK_FORMAT_B8G8R8A8_UNORM;
|
||||
case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
|
||||
return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
vk_format_get_nr_components(VkFormat format)
|
||||
{
|
||||
const struct vk_format_description *desc = vk_format_description(format);
|
||||
return desc->nr_channels;
|
||||
}
|
||||
|
||||
#endif /* VK_FORMAT_H */
|
|
@ -0,0 +1,188 @@
|
|||
/* this is pretty much taken from the gallium one. */
|
||||
|
||||
|
||||
VK_FORMAT_UNDEFINED , plain, 1, 1, u8 , , , , x001, rgb
|
||||
VK_FORMAT_R4G4_UNORM_PACK8 , plain, 1, 1, un4 , un4 , , , xy01, rgb
|
||||
VK_FORMAT_R4G4B4A4_UNORM_PACK16 , plain, 1, 1, un4 , un4 , un4 , un4 , wzyx, rgb
|
||||
VK_FORMAT_B4G4R4A4_UNORM_PACK16 , plain, 1, 1, un4 , un4 , un4 , un4 , wxyz, rgb
|
||||
VK_FORMAT_R5G6B5_UNORM_PACK16 , plain, 1, 1, un5 , un6 , un5 , , zyx1, rgb
|
||||
VK_FORMAT_B5G6R5_UNORM_PACK16 , plain, 1, 1, un5 , un6 , un5 , , xyz1, rgb
|
||||
VK_FORMAT_R5G5B5A1_UNORM_PACK16 , plain, 1, 1, un1 , un5 , un5 , un5 , wzyx, rgb
|
||||
VK_FORMAT_B5G5R5A1_UNORM_PACK16 , plain, 1, 1, un1 , un5 , un5 , un5 , wxyz, rgb
|
||||
VK_FORMAT_A1R5G5B5_UNORM_PACK16 , plain, 1, 1, un5 , un5 , un5 , un1 , zyxw, rgb
|
||||
VK_FORMAT_R8_UNORM , plain, 1, 1, un8 , , , , x001, rgb
|
||||
VK_FORMAT_R8_SNORM , plain, 1, 1, sn8 , , , , x001, rgb
|
||||
VK_FORMAT_R8_USCALED , plain, 1, 1, us8 , , , , x001, rgb
|
||||
VK_FORMAT_R8_SSCALED , plain, 1, 1, ss8 , , , , x001, rgb
|
||||
VK_FORMAT_R8_UINT , plain, 1, 1, up8 , , , , x001, rgb
|
||||
VK_FORMAT_R8_SINT , plain, 1, 1, sp8 , , , , x001, rgb
|
||||
VK_FORMAT_R8_SRGB , plain, 1, 1, un8 , , , , x001, srgb
|
||||
VK_FORMAT_R8G8_UNORM , plain, 1, 1, un8 , un8 , , , xy01, rgb
|
||||
VK_FORMAT_R8G8_SNORM , plain, 1, 1, sn8 , sn8 , , , xy01, rgb
|
||||
VK_FORMAT_R8G8_USCALED , plain, 1, 1, us8 , us8 , , , xy01, rgb
|
||||
VK_FORMAT_R8G8_SSCALED , plain, 1, 1, ss8 , ss8 , , , xy01, rgb
|
||||
VK_FORMAT_R8G8_UINT , plain, 1, 1, up8 , up8 , , , xy01, rgb
|
||||
VK_FORMAT_R8G8_SINT , plain, 1, 1, sp8 , sp8 , , , xy01, rgb
|
||||
VK_FORMAT_R8G8_SRGB , plain, 1, 1, un8 , un8 , , , xy01, srgb
|
||||
VK_FORMAT_R8G8B8_UNORM , plain, 1, 1, un8 , un8 , un8 , , xyz1, rgb
|
||||
VK_FORMAT_R8G8B8_SNORM , plain, 1, 1, sn8 , sn8 , sn8 , , xyz1, rgb
|
||||
VK_FORMAT_R8G8B8_USCALED , plain, 1, 1, us8 , us8 , us8 , , xyz1, rgb
|
||||
VK_FORMAT_R8G8B8_SSCALED , plain, 1, 1, ss8 , ss8 , ss8 , , xyz1, rgb
|
||||
VK_FORMAT_R8G8B8_UINT , plain, 1, 1, up8 , up8 , up8 , , xyz1, rgb
|
||||
VK_FORMAT_R8G8B8_SINT , plain, 1, 1, sp8 , sp8 , sp8 , , xyz1, rgb
|
||||
VK_FORMAT_R8G8B8_SRGB , plain, 1, 1, un8 , un8 , un8 , , xyz1, srgb
|
||||
VK_FORMAT_B8G8R8_UNORM , plain, 1, 1, un8 , un8 , un8 , , zyx1, rgb
|
||||
VK_FORMAT_B8G8R8_SNORM , plain, 1, 1, sn8 , sn8 , sn8 , , zyx1, rgb
|
||||
VK_FORMAT_B8G8R8_USCALED , plain, 1, 1, us8 , us8 , us8 , , zyx1, rgb
|
||||
VK_FORMAT_B8G8R8_SSCALED , plain, 1, 1, ss8 , ss8 , ss8 , , zyx1, rgb
|
||||
VK_FORMAT_B8G8R8_UINT , plain, 1, 1, up8 , up8 , up8 , , zyx1, rgb
|
||||
VK_FORMAT_B8G8R8_SINT , plain, 1, 1, sp8 , sp8 , sp8 , , zyx1, rgb
|
||||
VK_FORMAT_B8G8R8_SRGB , plain, 1, 1, un8 , un8 , un8 , , zyx1, srgb
|
||||
VK_FORMAT_R8G8B8A8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , xyzw, rgb
|
||||
VK_FORMAT_R8G8B8A8_SNORM , plain, 1, 1, sn8 , sn8 , sn8 , sn8 , xyzw, rgb
|
||||
VK_FORMAT_R8G8B8A8_USCALED , plain, 1, 1, us8 , us8 , us8 , us8 , xyzw, rgb
|
||||
VK_FORMAT_R8G8B8A8_SSCALED , plain, 1, 1, ss8 , ss8 , ss8 , ss8 , xyzw, rgb
|
||||
VK_FORMAT_R8G8B8A8_UINT , plain, 1, 1, up8 , up8 , up8 , up8 , xyzw, rgb
|
||||
VK_FORMAT_R8G8B8A8_SINT , plain, 1, 1, sp8 , sp8 , sp8 , sp8 , xyzw, rgb
|
||||
VK_FORMAT_R8G8B8A8_SRGB , plain, 1, 1, un8 , un8 , un8 , un8 , xyzw, srgb
|
||||
VK_FORMAT_B8G8R8A8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , zyxw, rgb
|
||||
VK_FORMAT_B8G8R8A8_SNORM , plain, 1, 1, sn8 , sn8 , sn8 , sn8 , zyxw, rgb
|
||||
VK_FORMAT_B8G8R8A8_USCALED , plain, 1, 1, us8 , us8 , us8 , us8 , zyxw, rgb
|
||||
VK_FORMAT_B8G8R8A8_SSCALED , plain, 1, 1, ss8 , ss8 , ss8 , ss8 , zyxw, rgb
|
||||
VK_FORMAT_B8G8R8A8_UINT , plain, 1, 1, up8 , up8 , up8 , up8 , zyxw, rgb
|
||||
VK_FORMAT_B8G8R8A8_SINT , plain, 1, 1, sp8 , sp8 , sp8 , sp8 , zyxw, rgb
|
||||
VK_FORMAT_B8G8R8A8_SRGB , plain, 1, 1, un8 , un8 , un8 , un8 , zyxw, srgb
|
||||
VK_FORMAT_A8B8G8R8_UNORM_PACK32 , plain, 1, 1, un8 , un8 , un8 , un8 , xyzw, rgb
|
||||
VK_FORMAT_A8B8G8R8_SNORM_PACK32 , plain, 1, 1, sn8 , sn8 , sn8 , sn8 , xyzw, rgb
|
||||
VK_FORMAT_A8B8G8R8_USCALED_PACK32 , plain, 1, 1, us8 , us8 , us8 , us8 , xyzw, rgb
|
||||
VK_FORMAT_A8B8G8R8_SSCALED_PACK32 , plain, 1, 1, ss8 , ss8 , ss8 , ss8 , xyzw, rgb
|
||||
VK_FORMAT_A8B8G8R8_UINT_PACK32 , plain, 1, 1, up8 , up8 , up8 , up8 , xyzw, rgb
|
||||
VK_FORMAT_A8B8G8R8_SINT_PACK32 , plain, 1, 1, sp8 , sp8 , sp8 , sp8 , xyzw, rgb
|
||||
VK_FORMAT_A8B8G8R8_SRGB_PACK32 , plain, 1, 1, un8 , un8 , un8 , un8 , xyzw, srgb
|
||||
VK_FORMAT_A2R10G10B10_UNORM_PACK32 , plain, 1, 1, un10, un10, un10, un2 , zyxw, rgb
|
||||
VK_FORMAT_A2R10G10B10_SNORM_PACK32 , plain, 1, 1, sn10, sn10, sn10, sn2 , zyxw, rgb
|
||||
VK_FORMAT_A2R10G10B10_USCALED_PACK32 , plain, 1, 1, us10, us10, us10, us2 , zyxw, rgb
|
||||
VK_FORMAT_A2R10G10B10_SSCALED_PACK32 , plain, 1, 1, ss10, ss10, ss10, ss2 , zyxw, rgb
|
||||
VK_FORMAT_A2R10G10B10_UINT_PACK32 , plain, 1, 1, up10, up10, up10, up2 , zyxw, rgb
|
||||
VK_FORMAT_A2R10G10B10_SINT_PACK32 , plain, 1, 1, sp10, sp10, sp10, sp2 , zyxw, rgb
|
||||
VK_FORMAT_A2B10G10R10_UNORM_PACK32 , plain, 1, 1, un10, un10, un10, un2 , xyzw, rgb
|
||||
VK_FORMAT_A2B10G10R10_SNORM_PACK32 , plain, 1, 1, sn10, sn10, sn10, sn2 , xyzw, rgb
|
||||
VK_FORMAT_A2B10G10R10_USCALED_PACK32 , plain, 1, 1, us10, us10, us10, us2 , xyzw, rgb
|
||||
VK_FORMAT_A2B10G10R10_SSCALED_PACK32 , plain, 1, 1, ss10, ss10, ss10, ss2 , xyzw, rgb
|
||||
VK_FORMAT_A2B10G10R10_UINT_PACK32 , plain, 1, 1, up10, up10, up10, up2 , xyzw, rgb
|
||||
VK_FORMAT_A2B10G10R10_SINT_PACK32 , plain, 1, 1, sp10, sp10, sp10, sp2 , xyzw, rgb
|
||||
VK_FORMAT_R16_UNORM , plain, 1, 1, un16, , , , x001, rgb
|
||||
VK_FORMAT_R16_SNORM , plain, 1, 1, sn16, , , , x001, rgb
|
||||
VK_FORMAT_R16_USCALED , plain, 1, 1, us16, , , , x001, rgb
|
||||
VK_FORMAT_R16_SSCALED , plain, 1, 1, ss16, , , , x001, rgb
|
||||
VK_FORMAT_R16_UINT , plain, 1, 1, up16, , , , x001, rgb
|
||||
VK_FORMAT_R16_SINT , plain, 1, 1, sp16, , , , x001, rgb
|
||||
VK_FORMAT_R16_SFLOAT , plain, 1, 1, f16 , , , , x001, rgb
|
||||
VK_FORMAT_R16G16_UNORM , plain, 1, 1, un16, un16, , , xy01, rgb
|
||||
VK_FORMAT_R16G16_SNORM , plain, 1, 1, sn16, sn16, , , xy01, rgb
|
||||
VK_FORMAT_R16G16_USCALED , plain, 1, 1, us16, us16, , , xy01, rgb
|
||||
VK_FORMAT_R16G16_SSCALED , plain, 1, 1, ss16, ss16, , , xy01, rgb
|
||||
VK_FORMAT_R16G16_UINT , plain, 1, 1, up16, up16, , , xy01, rgb
|
||||
VK_FORMAT_R16G16_SINT , plain, 1, 1, sp16, sp16, , , xy01, rgb
|
||||
VK_FORMAT_R16G16_SFLOAT , plain, 1, 1, f16 , f16 , , , xy01, rgb
|
||||
VK_FORMAT_R16G16B16_UNORM , plain, 1, 1, un16, un16, un16, , xyz1, rgb
|
||||
VK_FORMAT_R16G16B16_SNORM , plain, 1, 1, sn16, sn16, sn16, , xyz1, rgb
|
||||
VK_FORMAT_R16G16B16_USCALED , plain, 1, 1, us16, us16, us16, , xyz1, rgb
|
||||
VK_FORMAT_R16G16B16_SSCALED , plain, 1, 1, ss16, ss16, ss16, , xyz1, rgb
|
||||
VK_FORMAT_R16G16B16_UINT , plain, 1, 1, up16, up16, up16, , xyz1, rgb
|
||||
VK_FORMAT_R16G16B16_SINT , plain, 1, 1, sp16, sp16, sp16, , xyz1, rgb
|
||||
VK_FORMAT_R16G16B16_SFLOAT , plain, 1, 1, f16 , f16 , f16 , , xyz1, rgb
|
||||
VK_FORMAT_R16G16B16A16_UNORM , plain, 1, 1, un16, un16, un16, un16, xyzw, rgb
|
||||
VK_FORMAT_R16G16B16A16_SNORM , plain, 1, 1, sn16, sn16, sn16, sn16, xyzw, rgb
|
||||
VK_FORMAT_R16G16B16A16_USCALED , plain, 1, 1, us16, us16, us16, us16, xyzw, rgb
|
||||
VK_FORMAT_R16G16B16A16_SSCALED , plain, 1, 1, ss16, ss16, ss16, ss16, xyzw, rgb
|
||||
VK_FORMAT_R16G16B16A16_UINT , plain, 1, 1, up16, up16, up16, up16, xyzw, rgb
|
||||
VK_FORMAT_R16G16B16A16_SINT , plain, 1, 1, sp16, sp16, sp16, sp16, xyzw, rgb
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT , plain, 1, 1, f16 , f16 , f16 , f16 , xyzw, rgb
|
||||
VK_FORMAT_R32_UINT , plain, 1, 1, up32, , , , x001, rgb
|
||||
VK_FORMAT_R32_SINT , plain, 1, 1, sp32, , , , x001, rgb
|
||||
VK_FORMAT_R32_SFLOAT , plain, 1, 1, f32 , , , , x001, rgb
|
||||
VK_FORMAT_R32G32_UINT , plain, 1, 1, up32, up32, , , xy01, rgb
|
||||
VK_FORMAT_R32G32_SINT , plain, 1, 1, sp32, sp32, , , xy01, rgb
|
||||
VK_FORMAT_R32G32_SFLOAT , plain, 1, 1, f32 , f32 , , , xy01, rgb
|
||||
VK_FORMAT_R32G32B32_UINT , plain, 1, 1, up32, up32, up32, , xyz1, rgb
|
||||
VK_FORMAT_R32G32B32_SINT , plain, 1, 1, sp32, sp32, sp32, , xyz1, rgb
|
||||
VK_FORMAT_R32G32B32_SFLOAT , plain, 1, 1, f32 , f32 , f32 , , xyz1, rgb
|
||||
VK_FORMAT_R32G32B32A32_UINT , plain, 1, 1, up32, up32, up32, up32, xyzw, rgb
|
||||
VK_FORMAT_R32G32B32A32_SINT , plain, 1, 1, sp32, sp32, sp32, sp32, xyzw, rgb
|
||||
VK_FORMAT_R32G32B32A32_SFLOAT , plain, 1, 1, f32 , f32 , f32 , f32 , xyzw, rgb
|
||||
VK_FORMAT_R64_UINT , plain, 1, 1, up64, , , , x001, rgb
|
||||
VK_FORMAT_R64_SINT , plain, 1, 1, sp64, , , , x001, rgb
|
||||
VK_FORMAT_R64_SFLOAT , plain, 1, 1, f64 , , , , x001, rgb
|
||||
VK_FORMAT_R64G64_UINT , plain, 1, 1, up64, up64, , , xy01, rgb
|
||||
VK_FORMAT_R64G64_SINT , plain, 1, 1, sp64, sp64, , , xy01, rgb
|
||||
VK_FORMAT_R64G64_SFLOAT , plain, 1, 1, f64 , f64 , , , xy01, rgb
|
||||
VK_FORMAT_R64G64B64_UINT , plain, 1, 1, up64, up64, up64, , xyz1, rgb
|
||||
VK_FORMAT_R64G64B64_SINT , plain, 1, 1, sp64, sp64, sp64, , xyz1, rgb
|
||||
VK_FORMAT_R64G64B64_SFLOAT , plain, 1, 1, f64 , f64 , f64 , , xyz1, rgb
|
||||
VK_FORMAT_R64G64B64A64_UINT , plain, 1, 1, up64, up64, up64, up64, xyzw, rgb
|
||||
VK_FORMAT_R64G64B64A64_SINT , plain, 1, 1, sp64, sp64, sp64, sp64, xyzw, rgb
|
||||
VK_FORMAT_R64G64B64A64_SFLOAT , plain, 1, 1, f64 , f64 , f64 , f64 , xyzw, rgb
|
||||
VK_FORMAT_B10G11R11_UFLOAT_PACK32 , other, 1, 1, x32 , , , , xyz1, rgb
|
||||
VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 , other, 1, 1, x32 , , , , xyz1, rgb
|
||||
VK_FORMAT_D16_UNORM , plain, 1, 1, un16, , , , x___, zs
|
||||
VK_FORMAT_X8_D24_UNORM_PACK32 , plain, 1, 1, un24, x8 , , , x___, zs
|
||||
VK_FORMAT_D32_SFLOAT , plain, 1, 1, f32 , , , , x___, zs
|
||||
VK_FORMAT_S8_UINT , plain, 1, 1, up8 , , , , _x__, zs
|
||||
VK_FORMAT_D16_UNORM_S8_UINT , plain, 1, 1, un16, up8 , , , xy__, zs
|
||||
VK_FORMAT_D24_UNORM_S8_UINT , plain, 1, 1, un24, up8 , , , xy__, zs
|
||||
VK_FORMAT_D32_SFLOAT_S8_UINT , plain, 1, 1, f32 , up8 , , , xy__, zs
|
||||
VK_FORMAT_BC1_RGB_UNORM_BLOCK , s3tc, 4, 4, x64 , , , , xyz1, rgb
|
||||
VK_FORMAT_BC1_RGB_SRGB_BLOCK , s3tc, 4, 4, x64 , , , , xyz1, srgb
|
||||
VK_FORMAT_BC1_RGBA_UNORM_BLOCK , s3tc, 4, 4, x64 , , , , xyzw, rgb
|
||||
VK_FORMAT_BC1_RGBA_SRGB_BLOCK , s3tc, 4, 4, x64 , , , , xyzw, srgb
|
||||
VK_FORMAT_BC2_UNORM_BLOCK , s3tc, 4, 4, x128, , , , xyzw, rgb
|
||||
VK_FORMAT_BC2_SRGB_BLOCK , s3tc, 4, 4, x128, , , , xyzw, srgb
|
||||
VK_FORMAT_BC3_UNORM_BLOCK , s3tc, 4, 4, x128, , , , xyzw, rgb
|
||||
VK_FORMAT_BC3_SRGB_BLOCK , s3tc, 4, 4, x128, , , , xyzw, srgb
|
||||
VK_FORMAT_BC4_UNORM_BLOCK , rgtc, 4, 4, x64, , , , x001, rgb
|
||||
VK_FORMAT_BC4_SNORM_BLOCK , rgtc, 4, 4, x64, , , , x001, rgb
|
||||
VK_FORMAT_BC5_UNORM_BLOCK , rgtc, 4, 4, x128, , , , xy01, rgb
|
||||
VK_FORMAT_BC5_SNORM_BLOCK , rgtc, 4, 4, x128, , , , xy01, rgb
|
||||
VK_FORMAT_BC6H_UFLOAT_BLOCK , bptc, 4, 4, x128, , , , xyz1, rgb
|
||||
VK_FORMAT_BC6H_SFLOAT_BLOCK , bptc, 4, 4, x128, , , , xyz1, rgb
|
||||
VK_FORMAT_BC7_UNORM_BLOCK , bptc, 4, 4, x128, , , , xyzw, rgb
|
||||
VK_FORMAT_BC7_SRGB_BLOCK , bptc, 4, 4, x128, , , , xyzw, srgb
|
||||
VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK , etc, 4, 4, x64, , , , xyz1, rgb
|
||||
VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK , etc, 4, 4, x64, , , , xyz1, srgb
|
||||
VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK , etc, 4, 4, x64, , , , xyzw, rgb
|
||||
VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK , etc, 4, 4, x64, , , , xyzw, srgb
|
||||
VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK , etc, 4, 4, x128, , , , xyzw, rgb
|
||||
VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK , etc, 4, 4, x128, , , , xyzw, srgb
|
||||
VK_FORMAT_EAC_R11_UNORM_BLOCK , etc, 4, 4, x64, , , , x001, rgb
|
||||
VK_FORMAT_EAC_R11_SNORM_BLOCK , etc, 4, 4, x64, , , , x001, rgb
|
||||
VK_FORMAT_EAC_R11G11_UNORM_BLOCK , etc, 4, 4, x128, , , , xy01, rgb
|
||||
VK_FORMAT_EAC_R11G11_SNORM_BLOCK , etc, 4, 4, x128, , , , xy01, rgb
|
||||
VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
|
||||
VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
|
||||
VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
|
|
|
@ -0,0 +1,388 @@
|
|||
|
||||
'''
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009 VMware, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
'''
|
||||
|
||||
|
||||
VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5)
|
||||
|
||||
SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7)
|
||||
|
||||
PLAIN = 'plain'
|
||||
SCALED = 'scaled'
|
||||
|
||||
RGB = 'rgb'
|
||||
SRGB = 'srgb'
|
||||
YUV = 'yuv'
|
||||
ZS = 'zs'
|
||||
|
||||
|
||||
def is_pot(x):
|
||||
return (x & (x - 1)) == 0
|
||||
|
||||
|
||||
VERY_LARGE = 99999999999999999999999
|
||||
|
||||
|
||||
class Channel:
|
||||
'''Describe the channel of a color channel.'''
|
||||
|
||||
def __init__(self, type, norm, pure, scaled, size, name = ''):
|
||||
self.type = type
|
||||
self.norm = norm
|
||||
self.pure = pure
|
||||
self.size = size
|
||||
self.scaled = scaled
|
||||
self.sign = type in (SIGNED, FIXED, FLOAT)
|
||||
self.name = name
|
||||
|
||||
def __str__(self):
|
||||
s = str(self.type)
|
||||
if self.norm:
|
||||
s += 'n'
|
||||
if self.pure:
|
||||
s += 'p'
|
||||
if self.scaled:
|
||||
s += 's'
|
||||
s += str(self.size)
|
||||
return s
|
||||
|
||||
def __eq__(self, other):
|
||||
return (other is not None and
|
||||
self.type == other.type and
|
||||
self.norm == other.norm and
|
||||
self.pure == other.pure and
|
||||
self.size == other.size and
|
||||
self.scaled == other.scaled)
|
||||
|
||||
def max(self):
|
||||
'''Maximum representable number.'''
|
||||
if self.type == FLOAT:
|
||||
return VERY_LARGE
|
||||
if self.type == FIXED:
|
||||
return (1 << (self.size/2)) - 1
|
||||
if self.norm:
|
||||
return 1
|
||||
if self.type == UNSIGNED:
|
||||
return (1 << self.size) - 1
|
||||
if self.type == SIGNED:
|
||||
return (1 << (self.size - 1)) - 1
|
||||
assert False
|
||||
|
||||
def min(self):
|
||||
'''Minimum representable number.'''
|
||||
if self.type == FLOAT:
|
||||
return -VERY_LARGE
|
||||
if self.type == FIXED:
|
||||
return -(1 << (self.size/2))
|
||||
if self.type == UNSIGNED:
|
||||
return 0
|
||||
if self.norm:
|
||||
return -1
|
||||
if self.type == SIGNED:
|
||||
return -(1 << (self.size - 1))
|
||||
assert False
|
||||
|
||||
|
||||
class Format:
|
||||
'''Describe a pixel format.'''
|
||||
|
||||
def __init__(self, name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace):
|
||||
self.name = name
|
||||
self.layout = layout
|
||||
self.block_width = block_width
|
||||
self.block_height = block_height
|
||||
self.le_channels = le_channels
|
||||
self.le_swizzles = le_swizzles
|
||||
self.be_channels = be_channels
|
||||
self.be_swizzles = be_swizzles
|
||||
self.name = name
|
||||
self.colorspace = colorspace
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def short_name(self):
|
||||
'''Make up a short norm for a format, suitable to be used as suffix in
|
||||
function names.'''
|
||||
|
||||
name = self.name
|
||||
if name.startswith('VK_FORMAT_'):
|
||||
name = name[len('VK_FORMAT_'):]
|
||||
name = name.lower()
|
||||
return name
|
||||
|
||||
def block_size(self):
|
||||
size = 0
|
||||
for channel in self.le_channels:
|
||||
size += channel.size
|
||||
return size
|
||||
|
||||
def nr_channels(self):
|
||||
nr_channels = 0
|
||||
for channel in self.le_channels:
|
||||
if channel.size:
|
||||
nr_channels += 1
|
||||
return nr_channels
|
||||
|
||||
def array_element(self):
|
||||
if self.layout != PLAIN:
|
||||
return None
|
||||
ref_channel = self.le_channels[0]
|
||||
if ref_channel.type == VOID:
|
||||
ref_channel = self.le_channels[1]
|
||||
for channel in self.le_channels:
|
||||
if channel.size and (channel.size != ref_channel.size or channel.size % 8):
|
||||
return None
|
||||
if channel.type != VOID:
|
||||
if channel.type != ref_channel.type:
|
||||
return None
|
||||
if channel.norm != ref_channel.norm:
|
||||
return None
|
||||
if channel.pure != ref_channel.pure:
|
||||
return None
|
||||
if channel.scaled != ref_channel.scaled:
|
||||
return None
|
||||
return ref_channel
|
||||
|
||||
def is_array(self):
|
||||
return self.array_element() != None
|
||||
|
||||
def is_mixed(self):
|
||||
if self.layout != PLAIN:
|
||||
return False
|
||||
ref_channel = self.le_channels[0]
|
||||
if ref_channel.type == VOID:
|
||||
ref_channel = self.le_channels[1]
|
||||
for channel in self.le_channels[1:]:
|
||||
if channel.type != VOID:
|
||||
if channel.type != ref_channel.type:
|
||||
return True
|
||||
if channel.norm != ref_channel.norm:
|
||||
return True
|
||||
if channel.pure != ref_channel.pure:
|
||||
return True
|
||||
if channel.scaled != ref_channel.scaled:
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_pot(self):
|
||||
return is_pot(self.block_size())
|
||||
|
||||
def is_int(self):
|
||||
if self.layout != PLAIN:
|
||||
return False
|
||||
for channel in self.le_channels:
|
||||
if channel.type not in (VOID, UNSIGNED, SIGNED):
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_float(self):
|
||||
if self.layout != PLAIN:
|
||||
return False
|
||||
for channel in self.le_channels:
|
||||
if channel.type not in (VOID, FLOAT):
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_bitmask(self):
|
||||
if self.layout != PLAIN:
|
||||
return False
|
||||
if self.block_size() not in (8, 16, 32):
|
||||
return False
|
||||
for channel in self.le_channels:
|
||||
if channel.type not in (VOID, UNSIGNED, SIGNED):
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_pure_color(self):
|
||||
if self.layout != PLAIN or self.colorspace == ZS:
|
||||
return False
|
||||
pures = [channel.pure
|
||||
for channel in self.le_channels
|
||||
if channel.type != VOID]
|
||||
for x in pures:
|
||||
assert x == pures[0]
|
||||
return pures[0]
|
||||
|
||||
def channel_type(self):
|
||||
types = [channel.type
|
||||
for channel in self.le_channels
|
||||
if channel.type != VOID]
|
||||
for x in types:
|
||||
assert x == types[0]
|
||||
return types[0]
|
||||
|
||||
def is_pure_signed(self):
|
||||
return self.is_pure_color() and self.channel_type() == SIGNED
|
||||
|
||||
def is_pure_unsigned(self):
|
||||
return self.is_pure_color() and self.channel_type() == UNSIGNED
|
||||
|
||||
def has_channel(self, id):
|
||||
return self.le_swizzles[id] != SWIZZLE_NONE
|
||||
|
||||
def has_depth(self):
|
||||
return self.colorspace == ZS and self.has_channel(0)
|
||||
|
||||
def has_stencil(self):
|
||||
return self.colorspace == ZS and self.has_channel(1)
|
||||
|
||||
def stride(self):
|
||||
return self.block_size()/8
|
||||
|
||||
|
||||
_type_parse_map = {
|
||||
'': VOID,
|
||||
'x': VOID,
|
||||
'u': UNSIGNED,
|
||||
's': SIGNED,
|
||||
'h': FIXED,
|
||||
'f': FLOAT,
|
||||
}
|
||||
|
||||
_swizzle_parse_map = {
|
||||
'x': SWIZZLE_X,
|
||||
'y': SWIZZLE_Y,
|
||||
'z': SWIZZLE_Z,
|
||||
'w': SWIZZLE_W,
|
||||
'0': SWIZZLE_0,
|
||||
'1': SWIZZLE_1,
|
||||
'_': SWIZZLE_NONE,
|
||||
}
|
||||
|
||||
def _parse_channels(fields, layout, colorspace, swizzles):
|
||||
if layout == PLAIN:
|
||||
names = ['']*4
|
||||
if colorspace in (RGB, SRGB):
|
||||
for i in range(4):
|
||||
swizzle = swizzles[i]
|
||||
if swizzle < 4:
|
||||
names[swizzle] += 'rgba'[i]
|
||||
elif colorspace == ZS:
|
||||
for i in range(4):
|
||||
swizzle = swizzles[i]
|
||||
if swizzle < 4:
|
||||
names[swizzle] += 'zs'[i]
|
||||
else:
|
||||
assert False
|
||||
for i in range(4):
|
||||
if names[i] == '':
|
||||
names[i] = 'x'
|
||||
else:
|
||||
names = ['x', 'y', 'z', 'w']
|
||||
|
||||
channels = []
|
||||
for i in range(0, 4):
|
||||
field = fields[i]
|
||||
if field:
|
||||
type = _type_parse_map[field[0]]
|
||||
if field[1] == 'n':
|
||||
norm = True
|
||||
pure = False
|
||||
scaled = False
|
||||
size = int(field[2:])
|
||||
elif field[1] == 'p':
|
||||
pure = True
|
||||
norm = False
|
||||
scaled = False
|
||||
size = int(field[2:])
|
||||
elif field[1] == 's':
|
||||
pure = False
|
||||
norm = False
|
||||
scaled = True
|
||||
size = int(field[2:])
|
||||
else:
|
||||
norm = False
|
||||
pure = False
|
||||
scaled = False
|
||||
size = int(field[1:])
|
||||
else:
|
||||
type = VOID
|
||||
norm = False
|
||||
pure = False
|
||||
scaled = False
|
||||
size = 0
|
||||
channel = Channel(type, norm, pure, scaled, size, names[i])
|
||||
channels.append(channel)
|
||||
|
||||
return channels
|
||||
|
||||
def parse(filename):
|
||||
'''Parse the format description in CSV format in terms of the
|
||||
Channel and Format classes above.'''
|
||||
|
||||
stream = open(filename)
|
||||
formats = []
|
||||
for line in stream:
|
||||
try:
|
||||
comment = line.index('#')
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
line = line[:comment]
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
fields = [field.strip() for field in line.split(',')]
|
||||
if len (fields) < 10:
|
||||
continue
|
||||
if len (fields) == 10:
|
||||
fields += fields[4:9]
|
||||
assert len (fields) == 15
|
||||
|
||||
name = fields[0]
|
||||
layout = fields[1]
|
||||
block_width, block_height = map(int, fields[2:4])
|
||||
colorspace = fields[9]
|
||||
|
||||
le_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
|
||||
le_channels = _parse_channels(fields[4:8], layout, colorspace, le_swizzles)
|
||||
|
||||
be_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[14]]
|
||||
be_channels = _parse_channels(fields[10:14], layout, colorspace, be_swizzles)
|
||||
|
||||
le_shift = 0
|
||||
for channel in le_channels:
|
||||
channel.shift = le_shift
|
||||
le_shift += channel.size
|
||||
|
||||
be_shift = 0
|
||||
for channel in be_channels[3::-1]:
|
||||
channel.shift = be_shift
|
||||
be_shift += channel.size
|
||||
|
||||
assert le_shift == be_shift
|
||||
for i in range(4):
|
||||
assert (le_swizzles[i] != SWIZZLE_NONE) == (be_swizzles[i] != SWIZZLE_NONE)
|
||||
|
||||
format = Format(name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace)
|
||||
formats.append(format)
|
||||
return formats
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
from __future__ import print_function
|
||||
|
||||
CopyRight = '''
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2010 VMware, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
'''
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
from vk_format_parse import *
|
||||
|
||||
def layout_map(layout):
|
||||
return 'VK_FORMAT_LAYOUT_' + str(layout).upper()
|
||||
|
||||
|
||||
def colorspace_map(colorspace):
|
||||
return 'VK_FORMAT_COLORSPACE_' + str(colorspace).upper()
|
||||
|
||||
|
||||
colorspace_channels_map = {
|
||||
'rgb': ['r', 'g', 'b', 'a'],
|
||||
'srgb': ['sr', 'sg', 'sb', 'a'],
|
||||
'zs': ['z', 's'],
|
||||
'yuv': ['y', 'u', 'v'],
|
||||
}
|
||||
|
||||
|
||||
type_map = {
|
||||
VOID: "VK_FORMAT_TYPE_VOID",
|
||||
UNSIGNED: "VK_FORMAT_TYPE_UNSIGNED",
|
||||
SIGNED: "VK_FORMAT_TYPE_SIGNED",
|
||||
FIXED: "VK_FORMAT_TYPE_FIXED",
|
||||
FLOAT: "VK_FORMAT_TYPE_FLOAT",
|
||||
}
|
||||
|
||||
|
||||
def bool_map(value):
|
||||
if value:
|
||||
return "true"
|
||||
else:
|
||||
return "false"
|
||||
|
||||
|
||||
swizzle_map = {
|
||||
SWIZZLE_X: "VK_SWIZZLE_X",
|
||||
SWIZZLE_Y: "VK_SWIZZLE_Y",
|
||||
SWIZZLE_Z: "VK_SWIZZLE_Z",
|
||||
SWIZZLE_W: "VK_SWIZZLE_W",
|
||||
SWIZZLE_0: "VK_SWIZZLE_0",
|
||||
SWIZZLE_1: "VK_SWIZZLE_1",
|
||||
SWIZZLE_NONE: "VK_SWIZZLE_NONE",
|
||||
}
|
||||
|
||||
def print_channels(format, func):
|
||||
if format.nr_channels() <= 1:
|
||||
func(format.le_channels, format.le_swizzles)
|
||||
else:
|
||||
print('#ifdef PIPE_ARCH_BIG_ENDIAN')
|
||||
func(format.be_channels, format.be_swizzles)
|
||||
print('#else')
|
||||
func(format.le_channels, format.le_swizzles)
|
||||
print('#endif')
|
||||
|
||||
def write_format_table(formats):
|
||||
print('/* This file is autogenerated by vk_format_table.py from vk_format_layout.csv. Do not edit directly. */')
|
||||
print()
|
||||
# This will print the copyright message on the top of this file
|
||||
print(CopyRight.strip())
|
||||
print()
|
||||
print('#include "stdbool.h"')
|
||||
print('#include "vk_format.h"')
|
||||
print()
|
||||
|
||||
def do_channel_array(channels, swizzles):
|
||||
print(" {")
|
||||
for i in range(4):
|
||||
channel = channels[i]
|
||||
if i < 3:
|
||||
sep = ","
|
||||
else:
|
||||
sep = ""
|
||||
if channel.size:
|
||||
print(" {%s, %s, %s, %s, %u, %u}%s\t/* %s = %s */" % (type_map[channel.type], bool_map(channel.norm), bool_map(channel.pure), bool_map(channel.scaled), channel.size, channel.shift, sep, "xyzw"[i], channel.name))
|
||||
else:
|
||||
print(" {0, 0, 0, 0, 0}%s" % (sep,))
|
||||
print(" },")
|
||||
|
||||
def do_swizzle_array(channels, swizzles):
|
||||
print(" {")
|
||||
for i in range(4):
|
||||
swizzle = swizzles[i]
|
||||
if i < 3:
|
||||
sep = ","
|
||||
else:
|
||||
sep = ""
|
||||
try:
|
||||
comment = colorspace_channels_map[format.colorspace][i]
|
||||
except (KeyError, IndexError):
|
||||
comment = 'ignored'
|
||||
print(" %s%s\t/* %s */" % (swizzle_map[swizzle], sep, comment))
|
||||
print(" },")
|
||||
|
||||
for format in formats:
|
||||
print('static const struct vk_format_description')
|
||||
print('vk_format_%s_description = {' % (format.short_name(),))
|
||||
print(" %s," % (format.name,))
|
||||
print(" \"%s\"," % (format.name,))
|
||||
print(" \"%s\"," % (format.short_name(),))
|
||||
print(" {%u, %u, %u},\t/* block */" % (format.block_width, format.block_height, format.block_size()))
|
||||
print(" %s," % (layout_map(format.layout),))
|
||||
print(" %u,\t/* nr_channels */" % (format.nr_channels(),))
|
||||
print(" %s,\t/* is_array */" % (bool_map(format.is_array()),))
|
||||
print(" %s,\t/* is_bitmask */" % (bool_map(format.is_bitmask()),))
|
||||
print(" %s,\t/* is_mixed */" % (bool_map(format.is_mixed()),))
|
||||
print_channels(format, do_channel_array)
|
||||
print_channels(format, do_swizzle_array)
|
||||
print(" %s," % (colorspace_map(format.colorspace),))
|
||||
print("};")
|
||||
print()
|
||||
|
||||
print("const struct vk_format_description *")
|
||||
print("vk_format_description(VkFormat format)")
|
||||
print("{")
|
||||
print(" if (format > VK_FORMAT_END_RANGE) {")
|
||||
print(" return NULL;")
|
||||
print(" }")
|
||||
print()
|
||||
print(" switch (format) {")
|
||||
for format in formats:
|
||||
print(" case %s:" % format.name)
|
||||
print(" return &vk_format_%s_description;" % (format.short_name(),))
|
||||
print(" default:")
|
||||
print(" return NULL;")
|
||||
print(" }")
|
||||
print("}")
|
||||
print()
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
formats = []
|
||||
for arg in sys.argv[1:]:
|
||||
formats.extend(parse(arg))
|
||||
write_format_table(formats)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -64,7 +64,7 @@ endif
|
|||
if with_gallium_vc4 or with_gallium_v3d
|
||||
subdir('broadcom')
|
||||
endif
|
||||
if with_gallium_freedreno
|
||||
if with_gallium_freedreno or with_freedreno_vk
|
||||
subdir('freedreno')
|
||||
endif
|
||||
if with_dri_i965 or with_intel_vk or with_gallium_iris
|
||||
|
|
Loading…
Reference in New Issue