mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 15:40:11 +01:00
zink: introduce opengl over vulkan
Here's zink, a so far pretty simple vulkan-gallium driver that is able to translate some applications from OpenGL to Vulkan. The compiler is quite limited for now, this will be improved on later. Signed-off-by: Erik Faye-Lund <erik.faye-lund@collabora.com> Acked-by: Jordan Justen <jordan.l.justen@intel.com>
This commit is contained in:
parent
5912792501
commit
8d46e35d16
36 changed files with 7009 additions and 3 deletions
|
|
@ -198,6 +198,7 @@ with_gallium_svga = gallium_drivers.contains('svga')
|
||||||
with_gallium_virgl = gallium_drivers.contains('virgl')
|
with_gallium_virgl = gallium_drivers.contains('virgl')
|
||||||
with_gallium_swr = gallium_drivers.contains('swr')
|
with_gallium_swr = gallium_drivers.contains('swr')
|
||||||
with_gallium_lima = gallium_drivers.contains('lima')
|
with_gallium_lima = gallium_drivers.contains('lima')
|
||||||
|
with_gallium_zink = gallium_drivers.contains('zink')
|
||||||
|
|
||||||
if cc.get_id().startswith('intel') and meson.version().version_compare('< 0.49.1')
|
if cc.get_id().startswith('intel') and meson.version().version_compare('< 0.49.1')
|
||||||
error('Meson does not have sufficient support of ICC before 0.49.1 to compile mesa')
|
error('Meson does not have sufficient support of ICC before 0.49.1 to compile mesa')
|
||||||
|
|
@ -491,6 +492,10 @@ if vdpau_drivers_path == ''
|
||||||
vdpau_drivers_path = join_paths(get_option('libdir'), 'vdpau')
|
vdpau_drivers_path = join_paths(get_option('libdir'), 'vdpau')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if with_gallium_zink
|
||||||
|
dep_vulkan = dependency('vulkan')
|
||||||
|
endif
|
||||||
|
|
||||||
_xvmc = get_option('gallium-xvmc')
|
_xvmc = get_option('gallium-xvmc')
|
||||||
if not system_has_kms_drm
|
if not system_has_kms_drm
|
||||||
if _xvmc == 'true'
|
if _xvmc == 'true'
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ option(
|
||||||
choices : [
|
choices : [
|
||||||
'', 'auto', 'kmsro', 'radeonsi', 'r300', 'r600', 'nouveau', 'freedreno',
|
'', 'auto', 'kmsro', 'radeonsi', 'r300', 'r600', 'nouveau', 'freedreno',
|
||||||
'swrast', 'v3d', 'vc4', 'etnaviv', 'tegra', 'i915', 'svga', 'virgl',
|
'swrast', 'v3d', 'vc4', 'etnaviv', 'tegra', 'i915', 'svga', 'virgl',
|
||||||
'swr', 'panfrost', 'iris', 'lima'
|
'swr', 'panfrost', 'iris', 'lima', 'zink'
|
||||||
],
|
],
|
||||||
description : 'List of gallium drivers to build. If this is set to auto all drivers applicable to the target OS/architecture will be built'
|
description : 'List of gallium drivers to build. If this is set to auto all drivers applicable to the target OS/architecture will be built'
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,11 @@ sw_screen_create_named(struct sw_winsys *winsys, const char *driver)
|
||||||
screen = swr_create_screen(winsys);
|
screen = swr_create_screen(winsys);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(GALLIUM_ZINK)
|
||||||
|
if (screen == NULL && strcmp(driver, "zink") == 0)
|
||||||
|
screen = zink_create_screen(winsys);
|
||||||
|
#endif
|
||||||
|
|
||||||
return screen;
|
return screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,6 +76,8 @@ sw_screen_create(struct sw_winsys *winsys)
|
||||||
default_driver = "softpipe";
|
default_driver = "softpipe";
|
||||||
#elif defined(GALLIUM_SWR)
|
#elif defined(GALLIUM_SWR)
|
||||||
default_driver = "swr";
|
default_driver = "swr";
|
||||||
|
#elif defined(GALLIUM_ZINK)
|
||||||
|
default_driver = "zink";
|
||||||
#else
|
#else
|
||||||
default_driver = "";
|
default_driver = "";
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,10 @@
|
||||||
* llvmpipe, softpipe, swr.
|
* llvmpipe, softpipe, swr.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef GALLIUM_ZINK
|
||||||
|
#include "zink/zink_public.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef GALLIUM_SOFTPIPE
|
#ifdef GALLIUM_SOFTPIPE
|
||||||
#include "softpipe/sp_public.h"
|
#include "softpipe/sp_public.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -57,6 +61,11 @@ sw_screen_create_named(struct sw_winsys *winsys, const char *driver)
|
||||||
screen = swr_create_screen(winsys);
|
screen = swr_create_screen(winsys);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(GALLIUM_ZINK)
|
||||||
|
if (screen == NULL && strcmp(driver, "zink") == 0)
|
||||||
|
screen = zink_create_screen(winsys);
|
||||||
|
#endif
|
||||||
|
|
||||||
return screen;
|
return screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,6 +82,8 @@ sw_screen_create(struct sw_winsys *winsys)
|
||||||
default_driver = "softpipe";
|
default_driver = "softpipe";
|
||||||
#elif defined(GALLIUM_SWR)
|
#elif defined(GALLIUM_SWR)
|
||||||
default_driver = "swr";
|
default_driver = "swr";
|
||||||
|
#elif defined(GALLIUM_SWR)
|
||||||
|
default_driver = "zink";
|
||||||
#else
|
#else
|
||||||
default_driver = "";
|
default_driver = "";
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
49
src/gallium/drivers/zink/meson.build
Normal file
49
src/gallium/drivers/zink/meson.build
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Copyright © 2018 Collabora Ltd
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
files_libzink = files(
|
||||||
|
'nir_to_spirv/nir_to_spirv.c',
|
||||||
|
'nir_to_spirv/spirv_builder.c',
|
||||||
|
'zink_cmdbuf.c',
|
||||||
|
'zink_compiler.c',
|
||||||
|
'zink_context.c',
|
||||||
|
'zink_fence.c',
|
||||||
|
'zink_framebuffer.c',
|
||||||
|
'zink_pipeline.c',
|
||||||
|
'zink_program.c',
|
||||||
|
'zink_render_pass.c',
|
||||||
|
'zink_resource.c',
|
||||||
|
'zink_screen.c',
|
||||||
|
'zink_state.c',
|
||||||
|
'zink_surface.c',
|
||||||
|
)
|
||||||
|
|
||||||
|
libzink = static_library(
|
||||||
|
'zink',
|
||||||
|
files_libzink,
|
||||||
|
c_args : c_vis_args,
|
||||||
|
include_directories : inc_common,
|
||||||
|
dependencies: [dep_vulkan, idep_nir_headers],
|
||||||
|
)
|
||||||
|
|
||||||
|
driver_zink = declare_dependency(
|
||||||
|
compile_args : '-DGALLIUM_ZINK',
|
||||||
|
link_with : [libzink],
|
||||||
|
)
|
||||||
1035
src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
Normal file
1035
src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
Normal file
File diff suppressed because it is too large
Load diff
47
src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.h
Normal file
47
src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.h
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
struct spirv_shader {
|
||||||
|
uint32_t *words;
|
||||||
|
size_t num_words;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nir_shader;
|
||||||
|
|
||||||
|
struct spirv_shader *
|
||||||
|
nir_to_spirv(struct nir_shader *s);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_shader_delete(struct spirv_shader *s);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
830
src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c
Normal file
830
src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c
Normal file
|
|
@ -0,0 +1,830 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "spirv_builder.h"
|
||||||
|
|
||||||
|
#include "util/macros.h"
|
||||||
|
#include "util/u_bitcast.h"
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
#include "util/hash_table.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static bool
|
||||||
|
spirv_buffer_grow(struct spirv_buffer *b, size_t needed)
|
||||||
|
{
|
||||||
|
size_t new_room = MAX3(64, (b->room * 3) / 2, needed);
|
||||||
|
|
||||||
|
uint32_t *new_words = realloc(b->words, new_room * sizeof(uint32_t));
|
||||||
|
if (!new_words)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
b->words = new_words;
|
||||||
|
b->room = new_room;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
spirv_buffer_prepare(struct spirv_buffer *b, size_t needed)
|
||||||
|
{
|
||||||
|
needed += b->num_words;
|
||||||
|
if (b->room >= b->num_words + needed)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return spirv_buffer_grow(b, needed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
spirv_buffer_emit_word(struct spirv_buffer *b, uint32_t word)
|
||||||
|
{
|
||||||
|
assert(b->num_words < b->room);
|
||||||
|
b->words[b->num_words++] = word;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
spirv_buffer_emit_string(struct spirv_buffer *b, const char *str)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
uint32_t word = 0;
|
||||||
|
while (str[pos] != '\0') {
|
||||||
|
word |= str[pos] << (8 * (pos % 4));
|
||||||
|
if (++pos % 4 == 0) {
|
||||||
|
spirv_buffer_prepare(b, 1);
|
||||||
|
spirv_buffer_emit_word(b, word);
|
||||||
|
word = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spirv_buffer_prepare(b, 1);
|
||||||
|
spirv_buffer_emit_word(b, word);
|
||||||
|
|
||||||
|
return 1 + pos / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_cap(struct spirv_builder *b, SpvCapability cap)
|
||||||
|
{
|
||||||
|
spirv_buffer_prepare(&b->capabilities, 2);
|
||||||
|
spirv_buffer_emit_word(&b->capabilities, SpvOpCapability | (2 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->capabilities, cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_source(struct spirv_builder *b, SpvSourceLanguage lang,
|
||||||
|
uint32_t version)
|
||||||
|
{
|
||||||
|
spirv_buffer_prepare(&b->debug_names, 3);
|
||||||
|
spirv_buffer_emit_word(&b->debug_names, SpvOpSource | (3 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->debug_names, lang);
|
||||||
|
spirv_buffer_emit_word(&b->debug_names, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_mem_model(struct spirv_builder *b,
|
||||||
|
SpvAddressingModel addr_model,
|
||||||
|
SpvMemoryModel mem_model)
|
||||||
|
{
|
||||||
|
spirv_buffer_prepare(&b->memory_model, 3);
|
||||||
|
spirv_buffer_emit_word(&b->memory_model, SpvOpMemoryModel | (3 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->memory_model, addr_model);
|
||||||
|
spirv_buffer_emit_word(&b->memory_model, mem_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_entry_point(struct spirv_builder *b,
|
||||||
|
SpvExecutionModel exec_model, SpvId entry_point,
|
||||||
|
const char *name, const SpvId interfaces[],
|
||||||
|
size_t num_interfaces)
|
||||||
|
{
|
||||||
|
size_t pos = b->entry_points.num_words;
|
||||||
|
spirv_buffer_prepare(&b->entry_points, 3);
|
||||||
|
spirv_buffer_emit_word(&b->entry_points, SpvOpEntryPoint);
|
||||||
|
spirv_buffer_emit_word(&b->entry_points, exec_model);
|
||||||
|
spirv_buffer_emit_word(&b->entry_points, entry_point);
|
||||||
|
int len = spirv_buffer_emit_string(&b->entry_points, name);
|
||||||
|
b->entry_points.words[pos] |= (3 + len + num_interfaces) << 16;
|
||||||
|
spirv_buffer_prepare(&b->entry_points, num_interfaces);
|
||||||
|
for (int i = 0; i < num_interfaces; ++i)
|
||||||
|
spirv_buffer_emit_word(&b->entry_points, interfaces[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_exec_mode(struct spirv_builder *b, SpvId entry_point,
|
||||||
|
SpvExecutionMode exec_mode)
|
||||||
|
{
|
||||||
|
spirv_buffer_prepare(&b->exec_modes, 3);
|
||||||
|
spirv_buffer_emit_word(&b->exec_modes, SpvOpExecutionMode | (3 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->exec_modes, entry_point);
|
||||||
|
spirv_buffer_emit_word(&b->exec_modes, exec_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_name(struct spirv_builder *b, SpvId target,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
size_t pos = b->debug_names.num_words;
|
||||||
|
spirv_buffer_prepare(&b->debug_names, 2);
|
||||||
|
spirv_buffer_emit_word(&b->debug_names, SpvOpName);
|
||||||
|
spirv_buffer_emit_word(&b->debug_names, target);
|
||||||
|
int len = spirv_buffer_emit_string(&b->debug_names, name);
|
||||||
|
b->debug_names.words[pos] |= (2 + len) << 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
emit_decoration(struct spirv_builder *b, SpvId target,
|
||||||
|
SpvDecoration decoration, const uint32_t extra_operands[],
|
||||||
|
size_t num_extra_operands)
|
||||||
|
{
|
||||||
|
int words = 3 + num_extra_operands;
|
||||||
|
spirv_buffer_prepare(&b->decorations, words);
|
||||||
|
spirv_buffer_emit_word(&b->decorations, SpvOpDecorate | (words << 16));
|
||||||
|
spirv_buffer_emit_word(&b->decorations, target);
|
||||||
|
spirv_buffer_emit_word(&b->decorations, decoration);
|
||||||
|
for (int i = 0; i < num_extra_operands; ++i)
|
||||||
|
spirv_buffer_emit_word(&b->decorations, extra_operands[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_decoration(struct spirv_builder *b, SpvId target,
|
||||||
|
SpvDecoration decoration)
|
||||||
|
{
|
||||||
|
emit_decoration(b, target, decoration, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_location(struct spirv_builder *b, SpvId target,
|
||||||
|
uint32_t location)
|
||||||
|
{
|
||||||
|
uint32_t args[] = { location };
|
||||||
|
emit_decoration(b, target, SpvDecorationLocation, args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_component(struct spirv_builder *b, SpvId target,
|
||||||
|
uint32_t component)
|
||||||
|
{
|
||||||
|
uint32_t args[] = { component };
|
||||||
|
emit_decoration(b, target, SpvDecorationComponent, args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_builtin(struct spirv_builder *b, SpvId target,
|
||||||
|
SpvBuiltIn builtin)
|
||||||
|
{
|
||||||
|
uint32_t args[] = { builtin };
|
||||||
|
emit_decoration(b, target, SpvDecorationBuiltIn, args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_descriptor_set(struct spirv_builder *b, SpvId target,
|
||||||
|
uint32_t descriptor_set)
|
||||||
|
{
|
||||||
|
uint32_t args[] = { descriptor_set };
|
||||||
|
emit_decoration(b, target, SpvDecorationDescriptorSet, args,
|
||||||
|
ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_binding(struct spirv_builder *b, SpvId target,
|
||||||
|
uint32_t binding)
|
||||||
|
{
|
||||||
|
uint32_t args[] = { binding };
|
||||||
|
emit_decoration(b, target, SpvDecorationBinding, args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_array_stride(struct spirv_builder *b, SpvId target,
|
||||||
|
uint32_t stride)
|
||||||
|
{
|
||||||
|
uint32_t args[] = { stride };
|
||||||
|
emit_decoration(b, target, SpvDecorationArrayStride, args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
emit_member_decoration(struct spirv_builder *b, SpvId target, uint32_t member,
|
||||||
|
SpvDecoration decoration, const uint32_t extra_operands[],
|
||||||
|
size_t num_extra_operands)
|
||||||
|
{
|
||||||
|
int words = 4 + num_extra_operands;
|
||||||
|
spirv_buffer_prepare(&b->decorations, words);
|
||||||
|
spirv_buffer_emit_word(&b->decorations,
|
||||||
|
SpvOpMemberDecorate | (words << 16));
|
||||||
|
spirv_buffer_emit_word(&b->decorations, target);
|
||||||
|
spirv_buffer_emit_word(&b->decorations, member);
|
||||||
|
spirv_buffer_emit_word(&b->decorations, decoration);
|
||||||
|
for (int i = 0; i < num_extra_operands; ++i)
|
||||||
|
spirv_buffer_emit_word(&b->decorations, extra_operands[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_member_offset(struct spirv_builder *b, SpvId target,
|
||||||
|
uint32_t member, uint32_t offset)
|
||||||
|
{
|
||||||
|
uint32_t args[] = { offset };
|
||||||
|
emit_member_decoration(b, target, member, SpvDecorationOffset,
|
||||||
|
args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_undef(struct spirv_builder *b, SpvId result_type)
|
||||||
|
{
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
spirv_buffer_prepare(&b->instructions, 3);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, SpvOpUndef | (3 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result_type);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_function(struct spirv_builder *b, SpvId result,
|
||||||
|
SpvId return_type,
|
||||||
|
SpvFunctionControlMask function_control,
|
||||||
|
SpvId function_type)
|
||||||
|
{
|
||||||
|
spirv_buffer_prepare(&b->instructions, 5);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, SpvOpFunction | (5 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, return_type);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, function_control);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, function_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_function_end(struct spirv_builder *b)
|
||||||
|
{
|
||||||
|
spirv_buffer_prepare(&b->instructions, 1);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, SpvOpFunctionEnd | (1 << 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_label(struct spirv_builder *b, SpvId label)
|
||||||
|
{
|
||||||
|
spirv_buffer_prepare(&b->instructions, 2);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, SpvOpLabel | (2 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_return(struct spirv_builder *b)
|
||||||
|
{
|
||||||
|
spirv_buffer_prepare(&b->instructions, 1);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, SpvOpReturn | (1 << 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_load(struct spirv_builder *b, SpvId result_type,
|
||||||
|
SpvId pointer)
|
||||||
|
{
|
||||||
|
return spirv_builder_emit_unop(b, SpvOpLoad, result_type, pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_store(struct spirv_builder *b, SpvId pointer, SpvId object)
|
||||||
|
{
|
||||||
|
spirv_buffer_prepare(&b->instructions, 3);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, SpvOpStore | (3 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, pointer);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_access_chain(struct spirv_builder *b, SpvId result_type,
|
||||||
|
SpvId base, const SpvId indexes[],
|
||||||
|
size_t num_indexes)
|
||||||
|
{
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
|
||||||
|
int words = 4 + num_indexes;
|
||||||
|
spirv_buffer_prepare(&b->instructions, words);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, SpvOpAccessChain | (words << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result_type);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, base);
|
||||||
|
for (int i = 0; i < num_indexes; ++i)
|
||||||
|
spirv_buffer_emit_word(&b->instructions, indexes[i]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_unop(struct spirv_builder *b, SpvOp op, SpvId result_type,
|
||||||
|
SpvId operand)
|
||||||
|
{
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
spirv_buffer_prepare(&b->instructions, 4);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, op | (4 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result_type);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, operand);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_binop(struct spirv_builder *b, SpvOp op, SpvId result_type,
|
||||||
|
SpvId operand0, SpvId operand1)
|
||||||
|
{
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
spirv_buffer_prepare(&b->instructions, 5);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, op | (5 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result_type);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, operand0);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, operand1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_triop(struct spirv_builder *b, SpvOp op, SpvId result_type,
|
||||||
|
SpvId operand0, SpvId operand1, SpvId operand2)
|
||||||
|
{
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
spirv_buffer_prepare(&b->instructions, 6);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, op | (6 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result_type);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, operand0);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, operand1);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, operand2);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_composite_extract(struct spirv_builder *b, SpvId result_type,
|
||||||
|
SpvId composite, const uint32_t indexes[],
|
||||||
|
size_t num_indexes)
|
||||||
|
{
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
|
||||||
|
assert(num_indexes > 0);
|
||||||
|
int words = 4 + num_indexes;
|
||||||
|
spirv_buffer_prepare(&b->instructions, words);
|
||||||
|
spirv_buffer_emit_word(&b->instructions,
|
||||||
|
SpvOpCompositeExtract | (words << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result_type);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, composite);
|
||||||
|
for (int i = 0; i < num_indexes; ++i)
|
||||||
|
spirv_buffer_emit_word(&b->instructions, indexes[i]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_composite_construct(struct spirv_builder *b,
|
||||||
|
SpvId result_type,
|
||||||
|
const SpvId constituents[],
|
||||||
|
size_t num_constituents)
|
||||||
|
{
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
|
||||||
|
assert(num_constituents > 0);
|
||||||
|
int words = 3 + num_constituents;
|
||||||
|
spirv_buffer_prepare(&b->instructions, words);
|
||||||
|
spirv_buffer_emit_word(&b->instructions,
|
||||||
|
SpvOpCompositeConstruct | (words << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result_type);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result);
|
||||||
|
for (int i = 0; i < num_constituents; ++i)
|
||||||
|
spirv_buffer_emit_word(&b->instructions, constituents[i]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_vector_shuffle(struct spirv_builder *b, SpvId result_type,
|
||||||
|
SpvId vector_1, SpvId vector_2,
|
||||||
|
const uint32_t components[],
|
||||||
|
size_t num_components)
|
||||||
|
{
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
|
||||||
|
assert(num_components > 0);
|
||||||
|
int words = 5 + num_components;
|
||||||
|
spirv_buffer_prepare(&b->instructions, words);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, SpvOpVectorShuffle | (words << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result_type);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, vector_1);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, vector_2);
|
||||||
|
for (int i = 0; i < num_components; ++i)
|
||||||
|
spirv_buffer_emit_word(&b->instructions, components[i]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_image_sample_implicit_lod(struct spirv_builder *b,
|
||||||
|
SpvId result_type,
|
||||||
|
SpvId sampled_image,
|
||||||
|
SpvId coordinate)
|
||||||
|
{
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
spirv_buffer_prepare(&b->instructions, 5);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, SpvOpImageSampleImplicitLod | (5 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result_type);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, sampled_image);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, coordinate);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_image_sample_proj_implicit_lod(struct spirv_builder *b,
|
||||||
|
SpvId result_type,
|
||||||
|
SpvId sampled_image,
|
||||||
|
SpvId coordinate)
|
||||||
|
{
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
spirv_buffer_prepare(&b->instructions, 5);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, SpvOpImageSampleProjImplicitLod | (5 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result_type);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, sampled_image);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, coordinate);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_ext_inst(struct spirv_builder *b, SpvId result_type,
|
||||||
|
SpvId set, uint32_t instruction,
|
||||||
|
const SpvId *args, size_t num_args)
|
||||||
|
{
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
|
||||||
|
int words = 5 + num_args;
|
||||||
|
spirv_buffer_prepare(&b->instructions, words);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, SpvOpExtInst | (words << 16));
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result_type);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, result);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, set);
|
||||||
|
spirv_buffer_emit_word(&b->instructions, instruction);
|
||||||
|
for (int i = 0; i < num_args; ++i)
|
||||||
|
spirv_buffer_emit_word(&b->instructions, args[i]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct spirv_type {
|
||||||
|
SpvOp op;
|
||||||
|
uint32_t args[8];
|
||||||
|
size_t num_args;
|
||||||
|
|
||||||
|
SpvId type;
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
non_aggregate_type_hash(const void *arg)
|
||||||
|
{
|
||||||
|
const struct spirv_type *type = arg;
|
||||||
|
|
||||||
|
uint32_t hash = _mesa_fnv32_1a_offset_bias;
|
||||||
|
hash = _mesa_fnv32_1a_accumulate(hash, type->op);
|
||||||
|
hash = _mesa_fnv32_1a_accumulate_block(hash, type->args, sizeof(uint32_t) *
|
||||||
|
type->num_args);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
non_aggregate_type_equals(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const struct spirv_type *ta = a, *tb = b;
|
||||||
|
|
||||||
|
if (ta->op != tb->op)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
assert(ta->num_args == tb->num_args);
|
||||||
|
return memcmp(ta->args, tb->args, sizeof(uint32_t) * ta->num_args) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SpvId
|
||||||
|
get_type_def(struct spirv_builder *b, SpvOp op, const uint32_t args[],
|
||||||
|
size_t num_args)
|
||||||
|
{
|
||||||
|
/* According to the SPIR-V specification:
|
||||||
|
*
|
||||||
|
* "Two different type <id>s form, by definition, two different types. It
|
||||||
|
* is valid to declare multiple aggregate type <id>s having the same
|
||||||
|
* opcode and operands. This is to allow multiple instances of aggregate
|
||||||
|
* types with the same structure to be decorated differently. (Different
|
||||||
|
* decorations are not required; two different aggregate type <id>s are
|
||||||
|
* allowed to have identical declarations and decorations, and will still
|
||||||
|
* be two different types.) Non-aggregate types are different: It is
|
||||||
|
* invalid to declare multiple type <id>s for the same scalar, vector, or
|
||||||
|
* matrix type. That is, non-aggregate type declarations must all have
|
||||||
|
* different opcodes or operands. (Note that non-aggregate types cannot
|
||||||
|
* be decorated in ways that affect their type.)"
|
||||||
|
*
|
||||||
|
* ..so, we need to prevent the same non-aggregate type to be re-defined
|
||||||
|
* with a new <id>. We do this by putting the definitions in a hash-map, so
|
||||||
|
* we can easily look up and reuse them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct spirv_type key;
|
||||||
|
assert(num_args < ARRAY_SIZE(key.args));
|
||||||
|
key.op = op;
|
||||||
|
memcpy(&key.args, args, sizeof(uint32_t) * num_args);
|
||||||
|
key.num_args = num_args;
|
||||||
|
|
||||||
|
struct hash_entry *entry;
|
||||||
|
if (b->types) {
|
||||||
|
entry = _mesa_hash_table_search(b->types, &key);
|
||||||
|
if (entry)
|
||||||
|
return ((struct spirv_type *)entry->data)->type;
|
||||||
|
} else {
|
||||||
|
b->types = _mesa_hash_table_create(NULL, non_aggregate_type_hash,
|
||||||
|
non_aggregate_type_equals);
|
||||||
|
assert(b->types);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct spirv_type *type = CALLOC_STRUCT(spirv_type);
|
||||||
|
if (!type)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
type->op = op;
|
||||||
|
memcpy(&type->args, args, sizeof(uint32_t) * num_args);
|
||||||
|
type->num_args = num_args;
|
||||||
|
|
||||||
|
type->type = spirv_builder_new_id(b);
|
||||||
|
spirv_buffer_prepare(&b->types_const_defs, 2 + num_args);
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, op | ((2 + num_args) << 16));
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, type->type);
|
||||||
|
for (int i = 0; i < num_args; ++i)
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, args[i]);
|
||||||
|
|
||||||
|
entry = _mesa_hash_table_insert(b->types, type, type);
|
||||||
|
assert(entry);
|
||||||
|
|
||||||
|
return ((struct spirv_type *)entry->data)->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_void(struct spirv_builder *b)
|
||||||
|
{
|
||||||
|
return get_type_def(b, SpvOpTypeVoid, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_bool(struct spirv_builder *b)
|
||||||
|
{
|
||||||
|
return get_type_def(b, SpvOpTypeBool, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_int(struct spirv_builder *b, unsigned width)
|
||||||
|
{
|
||||||
|
uint32_t args[] = { width, 1 };
|
||||||
|
return get_type_def(b, SpvOpTypeInt, args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_uint(struct spirv_builder *b, unsigned width)
|
||||||
|
{
|
||||||
|
uint32_t args[] = { width, 0 };
|
||||||
|
return get_type_def(b, SpvOpTypeInt, args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_float(struct spirv_builder *b, unsigned width)
|
||||||
|
{
|
||||||
|
uint32_t args[] = { width };
|
||||||
|
return get_type_def(b, SpvOpTypeFloat, args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_image(struct spirv_builder *b, SpvId sampled_type,
|
||||||
|
SpvDim dim, bool depth, bool arrayed, bool ms,
|
||||||
|
unsigned sampled, SpvImageFormat image_format)
|
||||||
|
{
|
||||||
|
assert(sampled < 3);
|
||||||
|
uint32_t args[] = {
|
||||||
|
sampled_type, dim, depth ? 1 : 0, arrayed ? 1 : 0, ms ? 1 : 0, sampled,
|
||||||
|
image_format
|
||||||
|
};
|
||||||
|
return get_type_def(b, SpvOpTypeImage, args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_sampled_image(struct spirv_builder *b, SpvId image_type)
|
||||||
|
{
|
||||||
|
uint32_t args[] = { image_type };
|
||||||
|
return get_type_def(b, SpvOpTypeSampledImage, args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_pointer(struct spirv_builder *b,
|
||||||
|
SpvStorageClass storage_class, SpvId type)
|
||||||
|
{
|
||||||
|
uint32_t args[] = { storage_class, type };
|
||||||
|
return get_type_def(b, SpvOpTypePointer, args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_vector(struct spirv_builder *b, SpvId component_type,
|
||||||
|
unsigned component_count)
|
||||||
|
{
|
||||||
|
assert(component_count > 1);
|
||||||
|
uint32_t args[] = { component_type, component_count };
|
||||||
|
return get_type_def(b, SpvOpTypeVector, args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_array(struct spirv_builder *b, SpvId component_type,
|
||||||
|
SpvId length)
|
||||||
|
{
|
||||||
|
SpvId type = spirv_builder_new_id(b);
|
||||||
|
spirv_buffer_prepare(&b->types_const_defs, 4);
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeArray | (4 << 16));
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, type);
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, component_type);
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, length);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_struct(struct spirv_builder *b, const SpvId member_types[],
|
||||||
|
size_t num_member_types)
|
||||||
|
{
|
||||||
|
int words = 2 + num_member_types;
|
||||||
|
SpvId type = spirv_builder_new_id(b);
|
||||||
|
spirv_buffer_prepare(&b->types_const_defs, words);
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeStruct | (words << 16));
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, type);
|
||||||
|
for (int i = 0; i < num_member_types; ++i)
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, member_types[i]);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_function(struct spirv_builder *b, SpvId return_type,
|
||||||
|
const SpvId parameter_types[],
|
||||||
|
size_t num_parameter_types)
|
||||||
|
{
|
||||||
|
int words = 3 + num_parameter_types;
|
||||||
|
SpvId type = spirv_builder_new_id(b);
|
||||||
|
spirv_buffer_prepare(&b->types_const_defs, words);
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeFunction | (words << 16));
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, type);
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, return_type);
|
||||||
|
for (int i = 0; i < num_parameter_types; ++i)
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, parameter_types[i]);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SpvId
|
||||||
|
get_const_def(struct spirv_builder *b, SpvOp op, SpvId type,
|
||||||
|
const uint32_t args[], size_t num_args)
|
||||||
|
{
|
||||||
|
/* TODO: reuse constants */
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
spirv_buffer_prepare(&b->types_const_defs, 3 + num_args);
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, op | ((3 + num_args) << 16));
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, type);
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, result);
|
||||||
|
for (int i = 0; i < num_args; ++i)
|
||||||
|
spirv_buffer_emit_word(&b->types_const_defs, args[i]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_const_bool(struct spirv_builder *b, bool val)
|
||||||
|
{
|
||||||
|
return get_const_def(b, val ? SpvOpConstantTrue : SpvOpConstantFalse,
|
||||||
|
spirv_builder_type_bool(b), NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_const_int(struct spirv_builder *b, int width, int32_t val)
|
||||||
|
{
|
||||||
|
assert(width <= 32);
|
||||||
|
uint32_t args[] = { val };
|
||||||
|
return get_const_def(b, SpvOpConstant, spirv_builder_type_int(b, width),
|
||||||
|
args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_const_uint(struct spirv_builder *b, int width, uint32_t val)
|
||||||
|
{
|
||||||
|
assert(width <= 32);
|
||||||
|
uint32_t args[] = { val };
|
||||||
|
return get_const_def(b, SpvOpConstant, spirv_builder_type_uint(b, width),
|
||||||
|
args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_const_float(struct spirv_builder *b, int width, float val)
|
||||||
|
{
|
||||||
|
assert(width <= 32);
|
||||||
|
uint32_t args[] = { u_bitcast_f2u(val) };
|
||||||
|
return get_const_def(b, SpvOpConstant, spirv_builder_type_float(b, width),
|
||||||
|
args, ARRAY_SIZE(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_const_composite(struct spirv_builder *b, SpvId result_type,
|
||||||
|
const SpvId constituents[],
|
||||||
|
size_t num_constituents)
|
||||||
|
{
|
||||||
|
return get_const_def(b, SpvOpConstantComposite, result_type,
|
||||||
|
(const uint32_t *)constituents,
|
||||||
|
num_constituents);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_var(struct spirv_builder *b, SpvId type,
|
||||||
|
SpvStorageClass storage_class)
|
||||||
|
{
|
||||||
|
assert(storage_class != SpvStorageClassGeneric);
|
||||||
|
struct spirv_buffer *buf = storage_class != SpvStorageClassFunction ?
|
||||||
|
&b->types_const_defs : &b->instructions;
|
||||||
|
|
||||||
|
SpvId ret = spirv_builder_new_id(b);
|
||||||
|
spirv_buffer_prepare(buf, 4);
|
||||||
|
spirv_buffer_emit_word(buf, SpvOpVariable | (4 << 16));
|
||||||
|
spirv_buffer_emit_word(buf, type);
|
||||||
|
spirv_buffer_emit_word(buf, ret);
|
||||||
|
spirv_buffer_emit_word(buf, storage_class);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_import(struct spirv_builder *b, const char *name)
|
||||||
|
{
|
||||||
|
SpvId result = spirv_builder_new_id(b);
|
||||||
|
size_t pos = b->imports.num_words;
|
||||||
|
spirv_buffer_prepare(&b->imports, 2);
|
||||||
|
spirv_buffer_emit_word(&b->imports, SpvOpExtInstImport);
|
||||||
|
spirv_buffer_emit_word(&b->imports, result);
|
||||||
|
int len = spirv_buffer_emit_string(&b->imports, name);
|
||||||
|
b->imports.words[pos] |= (2 + len) << 16;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
spirv_builder_get_num_words(struct spirv_builder *b)
|
||||||
|
{
|
||||||
|
const size_t header_size = 5;
|
||||||
|
return header_size +
|
||||||
|
b->capabilities.num_words +
|
||||||
|
b->imports.num_words +
|
||||||
|
b->memory_model.num_words +
|
||||||
|
b->entry_points.num_words +
|
||||||
|
b->exec_modes.num_words +
|
||||||
|
b->debug_names.num_words +
|
||||||
|
b->decorations.num_words +
|
||||||
|
b->types_const_defs.num_words +
|
||||||
|
b->instructions.num_words;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
spirv_builder_get_words(struct spirv_builder *b, uint32_t *words,
|
||||||
|
size_t num_words)
|
||||||
|
{
|
||||||
|
assert(num_words >= spirv_builder_get_num_words(b));
|
||||||
|
|
||||||
|
size_t written = 0;
|
||||||
|
words[written++] = SpvMagicNumber;
|
||||||
|
words[written++] = 0x00010000;
|
||||||
|
words[written++] = 0;
|
||||||
|
words[written++] = b->prev_id + 1;
|
||||||
|
words[written++] = 0;
|
||||||
|
|
||||||
|
const struct spirv_buffer *buffers[] = {
|
||||||
|
&b->capabilities,
|
||||||
|
&b->imports,
|
||||||
|
&b->memory_model,
|
||||||
|
&b->entry_points,
|
||||||
|
&b->exec_modes,
|
||||||
|
&b->debug_names,
|
||||||
|
&b->decorations,
|
||||||
|
&b->types_const_defs,
|
||||||
|
&b->instructions
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(buffers); ++i) {
|
||||||
|
const struct spirv_buffer *buffer = buffers[i];
|
||||||
|
for (int j = 0; j < buffer->num_words; ++j)
|
||||||
|
words[written++] = buffer->words[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(written == spirv_builder_get_num_words(b));
|
||||||
|
return written;
|
||||||
|
}
|
||||||
270
src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h
Normal file
270
src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPIRV_BUILDER_H
|
||||||
|
#define SPIRV_BUILDER_H
|
||||||
|
|
||||||
|
#include "compiler/spirv/spirv.h"
|
||||||
|
#include "compiler/spirv/GLSL.std.450.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct spirv_buffer {
|
||||||
|
uint32_t *words;
|
||||||
|
size_t num_words, room;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spirv_builder {
|
||||||
|
struct spirv_buffer capabilities;
|
||||||
|
struct spirv_buffer imports;
|
||||||
|
struct spirv_buffer memory_model;
|
||||||
|
struct spirv_buffer entry_points;
|
||||||
|
struct spirv_buffer exec_modes;
|
||||||
|
struct spirv_buffer debug_names;
|
||||||
|
struct spirv_buffer decorations;
|
||||||
|
|
||||||
|
struct spirv_buffer types_const_defs;
|
||||||
|
struct hash_table *types;
|
||||||
|
|
||||||
|
struct spirv_buffer instructions;
|
||||||
|
SpvId prev_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline SpvId
|
||||||
|
spirv_builder_new_id(struct spirv_builder *b)
|
||||||
|
{
|
||||||
|
return ++b->prev_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_cap(struct spirv_builder *b, SpvCapability cap);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_source(struct spirv_builder *b, SpvSourceLanguage lang,
|
||||||
|
uint32_t version);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_mem_model(struct spirv_builder *b,
|
||||||
|
SpvAddressingModel addr_model,
|
||||||
|
SpvMemoryModel mem_model);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_name(struct spirv_builder *b, SpvId target,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_decoration(struct spirv_builder *b, SpvId target,
|
||||||
|
SpvDecoration decoration);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_location(struct spirv_builder *b, SpvId target,
|
||||||
|
uint32_t location);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_component(struct spirv_builder *b, SpvId target,
|
||||||
|
uint32_t component);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_builtin(struct spirv_builder *b, SpvId target,
|
||||||
|
SpvBuiltIn builtin);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_descriptor_set(struct spirv_builder *b, SpvId target,
|
||||||
|
uint32_t descriptor_set);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_binding(struct spirv_builder *b, SpvId target,
|
||||||
|
uint32_t binding);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_array_stride(struct spirv_builder *b, SpvId target,
|
||||||
|
uint32_t stride);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_member_offset(struct spirv_builder *b, SpvId target,
|
||||||
|
uint32_t member, uint32_t offset);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_entry_point(struct spirv_builder *b,
|
||||||
|
SpvExecutionModel exec_model, SpvId entry_point,
|
||||||
|
const char *name, const SpvId interfaces[],
|
||||||
|
size_t num_interfaces);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_exec_mode(struct spirv_builder *b, SpvId entry_point,
|
||||||
|
SpvExecutionMode exec_mode);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_function(struct spirv_builder *b, SpvId result,
|
||||||
|
SpvId return_type,
|
||||||
|
SpvFunctionControlMask function_control,
|
||||||
|
SpvId function_type);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_function_end(struct spirv_builder *b);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_label(struct spirv_builder *b, SpvId label);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_return(struct spirv_builder *b);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_undef(struct spirv_builder *b, SpvId result_type);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_load(struct spirv_builder *b, SpvId result_type,
|
||||||
|
SpvId pointer);
|
||||||
|
|
||||||
|
void
|
||||||
|
spirv_builder_emit_store(struct spirv_builder *b, SpvId pointer, SpvId object);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_access_chain(struct spirv_builder *b, SpvId result_type,
|
||||||
|
SpvId base, const SpvId indexes[],
|
||||||
|
size_t num_indexes);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_unop(struct spirv_builder *b, SpvOp op, SpvId result_type,
|
||||||
|
SpvId operand);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_binop(struct spirv_builder *b, SpvOp op, SpvId result_type,
|
||||||
|
SpvId operand0, SpvId operand1);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_triop(struct spirv_builder *b, SpvOp op, SpvId result_type,
|
||||||
|
SpvId operand0, SpvId operand1, SpvId operand2);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_composite_extract(struct spirv_builder *b, SpvId result_type,
|
||||||
|
SpvId composite, const uint32_t indexes[],
|
||||||
|
size_t num_indexes);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_composite_construct(struct spirv_builder *b,
|
||||||
|
SpvId result_type,
|
||||||
|
const SpvId constituents[],
|
||||||
|
size_t num_constituents);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_vector_shuffle(struct spirv_builder *b, SpvId result_type,
|
||||||
|
SpvId vector_1, SpvId vector_2,
|
||||||
|
const uint32_t components[],
|
||||||
|
size_t num_components);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_image_sample_implicit_lod(struct spirv_builder *b,
|
||||||
|
SpvId result_type,
|
||||||
|
SpvId sampled_image,
|
||||||
|
SpvId coordinate);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_image_sample_proj_implicit_lod(struct spirv_builder *b,
|
||||||
|
SpvId result_type,
|
||||||
|
SpvId sampled_image,
|
||||||
|
SpvId coordinate);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_ext_inst(struct spirv_builder *b, SpvId result_type,
|
||||||
|
SpvId set, uint32_t instruction,
|
||||||
|
const SpvId args[], size_t num_args);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_void(struct spirv_builder *b);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_bool(struct spirv_builder *b);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_int(struct spirv_builder *b, unsigned width);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_uint(struct spirv_builder *b, unsigned width);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_float(struct spirv_builder *b, unsigned width);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_image(struct spirv_builder *b, SpvId sampled_type,
|
||||||
|
SpvDim dim, bool depth, bool arrayed, bool ms,
|
||||||
|
unsigned sampled, SpvImageFormat image_format);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_sampled_image(struct spirv_builder *b, SpvId image_type);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_pointer(struct spirv_builder *b,
|
||||||
|
SpvStorageClass storage_class, SpvId type);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_vector(struct spirv_builder *b, SpvId component_type,
|
||||||
|
unsigned component_count);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_array(struct spirv_builder *b, SpvId component_type,
|
||||||
|
SpvId length);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_struct(struct spirv_builder *b, const SpvId member_types[],
|
||||||
|
size_t num_member_types);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_type_function(struct spirv_builder *b, SpvId return_type,
|
||||||
|
const SpvId parameter_types[],
|
||||||
|
size_t num_parameter_types);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_const_bool(struct spirv_builder *b, bool val);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_const_int(struct spirv_builder *b, int width, int32_t val);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_const_uint(struct spirv_builder *b, int width, uint32_t val);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_const_float(struct spirv_builder *b, int width, float val);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_const_composite(struct spirv_builder *b, SpvId result_type,
|
||||||
|
const SpvId constituents[],
|
||||||
|
size_t num_constituents);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_emit_var(struct spirv_builder *b, SpvId type,
|
||||||
|
SpvStorageClass storage_class);
|
||||||
|
|
||||||
|
SpvId
|
||||||
|
spirv_builder_import(struct spirv_builder *b, const char *name);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
spirv_builder_get_num_words(struct spirv_builder *b);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
spirv_builder_get_words(struct spirv_builder *b, uint32_t *words,
|
||||||
|
size_t num_words);
|
||||||
|
|
||||||
|
#endif
|
||||||
70
src/gallium/drivers/zink/zink_cmdbuf.c
Normal file
70
src/gallium/drivers/zink/zink_cmdbuf.c
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
#include "zink_cmdbuf.h"
|
||||||
|
|
||||||
|
#include "zink_context.h"
|
||||||
|
#include "zink_fence.h"
|
||||||
|
#include "zink_screen.h"
|
||||||
|
|
||||||
|
#include "util/u_debug.h"
|
||||||
|
|
||||||
|
struct zink_cmdbuf *
|
||||||
|
zink_start_cmdbuf(struct zink_context *ctx)
|
||||||
|
{
|
||||||
|
struct zink_cmdbuf *cmdbuf = &ctx->cmdbuf;
|
||||||
|
|
||||||
|
if (cmdbuf->fence) {
|
||||||
|
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||||
|
zink_fence_finish(screen, cmdbuf->fence, PIPE_TIMEOUT_INFINITE);
|
||||||
|
zink_fence_reference(screen, &cmdbuf->fence, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkCommandBufferBeginInfo cbbi = {};
|
||||||
|
cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||||
|
if (vkBeginCommandBuffer(cmdbuf->cmdbuf, &cbbi) != VK_SUCCESS) {
|
||||||
|
debug_printf("vkBeginCommandBuffer failed\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmdbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
submit_cmdbuf(struct zink_context *ctx, VkCommandBuffer cmdbuf, VkFence fence)
|
||||||
|
{
|
||||||
|
VkPipelineStageFlags wait = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||||
|
|
||||||
|
VkSubmitInfo si = {};
|
||||||
|
si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
si.waitSemaphoreCount = 0;
|
||||||
|
si.pWaitSemaphores = NULL;
|
||||||
|
si.signalSemaphoreCount = 0;
|
||||||
|
si.pSignalSemaphores = NULL;
|
||||||
|
si.pWaitDstStageMask = &wait;
|
||||||
|
si.commandBufferCount = 1;
|
||||||
|
si.pCommandBuffers = &cmdbuf;
|
||||||
|
|
||||||
|
if (vkQueueSubmit(ctx->queue, 1, &si, fence) != VK_SUCCESS) {
|
||||||
|
debug_printf("vkQueueSubmit failed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_end_cmdbuf(struct zink_context *ctx, struct zink_cmdbuf *cmdbuf)
|
||||||
|
{
|
||||||
|
if (vkEndCommandBuffer(cmdbuf->cmdbuf) != VK_SUCCESS) {
|
||||||
|
debug_printf("vkEndCommandBuffer failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(cmdbuf->fence == NULL);
|
||||||
|
cmdbuf->fence = zink_create_fence(ctx->base.screen);
|
||||||
|
if (!cmdbuf->fence ||
|
||||||
|
!submit_cmdbuf(ctx, cmdbuf->cmdbuf, cmdbuf->fence->fence))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (vkQueueWaitIdle(ctx->queue) != VK_SUCCESS)
|
||||||
|
debug_printf("vkQueueWaitIdle failed\n");
|
||||||
|
}
|
||||||
43
src/gallium/drivers/zink/zink_cmdbuf.h
Normal file
43
src/gallium/drivers/zink/zink_cmdbuf.h
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_CMDBUF_H
|
||||||
|
#define ZINK_CMDBUF_H
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
struct zink_context;
|
||||||
|
struct zink_fence;
|
||||||
|
|
||||||
|
struct zink_cmdbuf {
|
||||||
|
VkCommandBuffer cmdbuf;
|
||||||
|
struct zink_fence *fence;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zink_cmdbuf *
|
||||||
|
zink_start_cmdbuf(struct zink_context *ctx);
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_end_cmdbuf(struct zink_context *ctx, struct zink_cmdbuf *cmdbuf);
|
||||||
|
|
||||||
|
#endif
|
||||||
263
src/gallium/drivers/zink/zink_compiler.c
Normal file
263
src/gallium/drivers/zink/zink_compiler.c
Normal file
|
|
@ -0,0 +1,263 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zink_compiler.h"
|
||||||
|
#include "zink_screen.h"
|
||||||
|
#include "nir_to_spirv/nir_to_spirv.h"
|
||||||
|
|
||||||
|
#include "pipe/p_state.h"
|
||||||
|
|
||||||
|
#include "nir.h"
|
||||||
|
#include "compiler/nir/nir_builder.h"
|
||||||
|
|
||||||
|
#include "nir/tgsi_to_nir.h"
|
||||||
|
#include "tgsi/tgsi_dump.h"
|
||||||
|
#include "tgsi/tgsi_from_mesa.h"
|
||||||
|
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
|
||||||
|
static bool
|
||||||
|
lower_instr(nir_intrinsic_instr *instr, nir_builder *b)
|
||||||
|
{
|
||||||
|
b->cursor = nir_before_instr(&instr->instr);
|
||||||
|
|
||||||
|
if (instr->intrinsic == nir_intrinsic_load_ubo) {
|
||||||
|
nir_ssa_def *old_idx = nir_ssa_for_src(b, instr->src[0], 1);
|
||||||
|
nir_ssa_def *new_idx = nir_iadd(b, old_idx, nir_imm_int(b, 1));
|
||||||
|
nir_instr_rewrite_src(&instr->instr, &instr->src[0],
|
||||||
|
nir_src_for_ssa(new_idx));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instr->intrinsic == nir_intrinsic_load_uniform) {
|
||||||
|
nir_ssa_def *ubo_idx = nir_imm_int(b, 0);
|
||||||
|
nir_ssa_def *ubo_offset =
|
||||||
|
nir_iadd(b, nir_imm_int(b, nir_intrinsic_base(instr)),
|
||||||
|
nir_ssa_for_src(b, instr->src[0], 1));
|
||||||
|
|
||||||
|
nir_intrinsic_instr *load =
|
||||||
|
nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_ubo);
|
||||||
|
load->num_components = instr->num_components;
|
||||||
|
load->src[0] = nir_src_for_ssa(ubo_idx);
|
||||||
|
load->src[1] = nir_src_for_ssa(ubo_offset);
|
||||||
|
nir_ssa_dest_init(&load->instr, &load->dest,
|
||||||
|
load->num_components, instr->dest.ssa.bit_size,
|
||||||
|
instr->dest.ssa.name);
|
||||||
|
nir_builder_instr_insert(b, &load->instr);
|
||||||
|
nir_ssa_def_rewrite_uses(&instr->dest.ssa, nir_src_for_ssa(&load->dest.ssa));
|
||||||
|
|
||||||
|
nir_instr_remove(&instr->instr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
lower_uniforms_to_ubo(nir_shader *shader)
|
||||||
|
{
|
||||||
|
bool progress = false;
|
||||||
|
|
||||||
|
nir_foreach_function(function, shader) {
|
||||||
|
if (function->impl) {
|
||||||
|
nir_builder builder;
|
||||||
|
nir_builder_init(&builder, function->impl);
|
||||||
|
nir_foreach_block(block, function->impl) {
|
||||||
|
nir_foreach_instr_safe(instr, block) {
|
||||||
|
if (instr->type == nir_instr_type_intrinsic)
|
||||||
|
progress |= lower_instr(nir_instr_as_intrinsic(instr),
|
||||||
|
&builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nir_metadata_preserve(function->impl, nir_metadata_block_index |
|
||||||
|
nir_metadata_dominance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progress) {
|
||||||
|
assert(shader->num_uniforms > 0);
|
||||||
|
const struct glsl_type *type = glsl_array_type(glsl_vec4_type(),
|
||||||
|
shader->num_uniforms, 0);
|
||||||
|
nir_variable *ubo = nir_variable_create(shader, nir_var_mem_ubo, type,
|
||||||
|
"uniform_0");
|
||||||
|
ubo->data.binding = 0;
|
||||||
|
|
||||||
|
struct glsl_struct_field field = {
|
||||||
|
.type = type,
|
||||||
|
.name = "data",
|
||||||
|
.location = -1,
|
||||||
|
};
|
||||||
|
ubo->interface_type =
|
||||||
|
glsl_interface_type(&field, 1, GLSL_INTERFACE_PACKING_STD430,
|
||||||
|
false, "__ubo0_interface");
|
||||||
|
}
|
||||||
|
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct nir_shader_compiler_options nir_options = {
|
||||||
|
.lower_all_io_to_temps = true,
|
||||||
|
.lower_ffma = true,
|
||||||
|
.lower_flrp32 = true,
|
||||||
|
.lower_fpow = true,
|
||||||
|
.lower_fsat = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const void *
|
||||||
|
zink_get_compiler_options(struct pipe_screen *screen,
|
||||||
|
enum pipe_shader_ir ir,
|
||||||
|
enum pipe_shader_type shader)
|
||||||
|
{
|
||||||
|
assert(ir == PIPE_SHADER_IR_NIR);
|
||||||
|
return &nir_options;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nir_shader *
|
||||||
|
zink_tgsi_to_nir(struct pipe_screen *screen, const struct tgsi_token *tokens)
|
||||||
|
{
|
||||||
|
if (zink_debug & ZINK_DEBUG_TGSI) {
|
||||||
|
fprintf(stderr, "TGSI shader:\n---8<---\n");
|
||||||
|
tgsi_dump_to_file(tokens, 0, stderr);
|
||||||
|
fprintf(stderr, "---8<---\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return tgsi_to_nir(tokens, screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
optimize_nir(struct nir_shader *s)
|
||||||
|
{
|
||||||
|
bool progress;
|
||||||
|
do {
|
||||||
|
progress = false;
|
||||||
|
NIR_PASS_V(s, nir_lower_vars_to_ssa);
|
||||||
|
NIR_PASS(progress, s, nir_copy_prop);
|
||||||
|
NIR_PASS(progress, s, nir_opt_remove_phis);
|
||||||
|
NIR_PASS(progress, s, nir_opt_dce);
|
||||||
|
NIR_PASS(progress, s, nir_opt_dead_cf);
|
||||||
|
NIR_PASS(progress, s, nir_opt_cse);
|
||||||
|
NIR_PASS(progress, s, nir_opt_peephole_select, 8, true, true);
|
||||||
|
NIR_PASS(progress, s, nir_opt_algebraic);
|
||||||
|
NIR_PASS(progress, s, nir_opt_constant_folding);
|
||||||
|
NIR_PASS(progress, s, nir_opt_undef);
|
||||||
|
} while (progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
glsl_type_size(const struct glsl_type *type, bool bindless)
|
||||||
|
{
|
||||||
|
return glsl_count_attribute_slots(type, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
zink_binding(enum pipe_shader_type stage, VkDescriptorType type, int index)
|
||||||
|
{
|
||||||
|
if (stage == PIPE_SHADER_COMPUTE) {
|
||||||
|
unreachable("not supported");
|
||||||
|
} else {
|
||||||
|
uint32_t stage_offset = (uint32_t)stage * (PIPE_MAX_CONSTANT_BUFFERS +
|
||||||
|
PIPE_MAX_SHADER_SAMPLER_VIEWS);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||||
|
assert(index < PIPE_MAX_CONSTANT_BUFFERS);
|
||||||
|
return stage_offset + index;
|
||||||
|
|
||||||
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||||
|
assert(index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
|
||||||
|
return stage_offset + PIPE_MAX_CONSTANT_BUFFERS + index;
|
||||||
|
|
||||||
|
default:
|
||||||
|
unreachable("unexpected type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zink_shader *
|
||||||
|
zink_compile_nir(struct zink_screen *screen, struct nir_shader *nir)
|
||||||
|
{
|
||||||
|
struct zink_shader *ret = CALLOC_STRUCT(zink_shader);
|
||||||
|
|
||||||
|
NIR_PASS_V(nir, nir_lower_io, nir_var_all, glsl_type_size, (nir_lower_io_options)0);
|
||||||
|
NIR_PASS_V(nir, lower_uniforms_to_ubo);
|
||||||
|
NIR_PASS_V(nir, nir_lower_regs_to_ssa);
|
||||||
|
NIR_PASS_V(nir, nir_lower_bool_to_float);
|
||||||
|
optimize_nir(nir);
|
||||||
|
NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_function_temp);
|
||||||
|
|
||||||
|
if (zink_debug & ZINK_DEBUG_NIR) {
|
||||||
|
fprintf(stderr, "NIR shader:\n---8<---\n");
|
||||||
|
nir_print_shader(nir, stderr);
|
||||||
|
fprintf(stderr, "---8<---\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
enum pipe_shader_type stage = pipe_shader_type_from_mesa(nir->info.stage);
|
||||||
|
|
||||||
|
ret->num_bindings = 0;
|
||||||
|
nir_foreach_variable(var, &nir->uniforms) {
|
||||||
|
if (glsl_type_is_sampler(var->type)) {
|
||||||
|
ret->bindings[ret->num_bindings].index = var->data.driver_location;
|
||||||
|
var->data.binding = zink_binding(stage, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, var->data.driver_location);
|
||||||
|
ret->bindings[ret->num_bindings].binding = var->data.binding;
|
||||||
|
ret->bindings[ret->num_bindings].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
ret->num_bindings++;
|
||||||
|
} else if (var->interface_type) {
|
||||||
|
ret->bindings[ret->num_bindings].index = var->data.binding;
|
||||||
|
var->data.binding = zink_binding(stage, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, var->data.binding);
|
||||||
|
ret->bindings[ret->num_bindings].binding = var->data.binding;
|
||||||
|
ret->bindings[ret->num_bindings].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
ret->num_bindings++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct spirv_shader *spirv = nir_to_spirv(nir);
|
||||||
|
assert(spirv);
|
||||||
|
|
||||||
|
if (zink_debug & ZINK_DEBUG_SPIRV) {
|
||||||
|
char buf[256];
|
||||||
|
static int i;
|
||||||
|
snprintf(buf, sizeof(buf), "dump%02d.spv", i++);
|
||||||
|
FILE *fp = fopen(buf, "wb");
|
||||||
|
fwrite(spirv->words, sizeof(uint32_t), spirv->num_words, fp);
|
||||||
|
fclose(fp);
|
||||||
|
fprintf(stderr, "wrote '%s'...\n", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkShaderModuleCreateInfo smci = {};
|
||||||
|
smci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||||
|
smci.codeSize = spirv->num_words * sizeof(uint32_t);
|
||||||
|
smci.pCode = spirv->words;
|
||||||
|
|
||||||
|
if (vkCreateShaderModule(screen->dev, &smci, NULL, &ret->shader_module) != VK_SUCCESS)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_shader_free(struct zink_screen *screen, struct zink_shader *shader)
|
||||||
|
{
|
||||||
|
vkDestroyShaderModule(screen->dev, shader->shader_module, NULL);
|
||||||
|
FREE(shader);
|
||||||
|
}
|
||||||
65
src/gallium/drivers/zink/zink_compiler.h
Normal file
65
src/gallium/drivers/zink/zink_compiler.h
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_COMPILER_H
|
||||||
|
#define ZINK_COMPILER_H
|
||||||
|
|
||||||
|
#include "pipe/p_defines.h"
|
||||||
|
#include "pipe/p_state.h"
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
struct pipe_screen;
|
||||||
|
struct zink_screen;
|
||||||
|
|
||||||
|
struct nir_shader_compiler_options;
|
||||||
|
struct nir_shader;
|
||||||
|
|
||||||
|
struct tgsi_token;
|
||||||
|
|
||||||
|
const void *
|
||||||
|
zink_get_compiler_options(struct pipe_screen *screen,
|
||||||
|
enum pipe_shader_ir ir,
|
||||||
|
enum pipe_shader_type shader);
|
||||||
|
|
||||||
|
struct nir_shader *
|
||||||
|
zink_tgsi_to_nir(struct pipe_screen *screen, const struct tgsi_token *tokens);
|
||||||
|
|
||||||
|
struct zink_shader {
|
||||||
|
VkShaderModule shader_module;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int index;
|
||||||
|
int binding;
|
||||||
|
VkDescriptorType type;
|
||||||
|
} bindings[PIPE_MAX_CONSTANT_BUFFERS + PIPE_MAX_SHADER_SAMPLER_VIEWS];
|
||||||
|
size_t num_bindings;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zink_shader *
|
||||||
|
zink_compile_nir(struct zink_screen *screen, struct nir_shader *nir);
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_shader_free(struct zink_screen *screen, struct zink_shader *shader);
|
||||||
|
|
||||||
|
#endif
|
||||||
1198
src/gallium/drivers/zink/zink_context.c
Normal file
1198
src/gallium/drivers/zink/zink_context.c
Normal file
File diff suppressed because it is too large
Load diff
107
src/gallium/drivers/zink/zink_context.h
Normal file
107
src/gallium/drivers/zink/zink_context.h
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_CONTEXT_H
|
||||||
|
#define ZINK_CONTEXT_H
|
||||||
|
|
||||||
|
#include "zink_pipeline.h"
|
||||||
|
#include "zink_cmdbuf.h"
|
||||||
|
|
||||||
|
#include "pipe/p_context.h"
|
||||||
|
#include "pipe/p_state.h"
|
||||||
|
|
||||||
|
#include "util/slab.h"
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
struct blitter_context;
|
||||||
|
struct primconvert_context;
|
||||||
|
struct zink_resource;
|
||||||
|
|
||||||
|
struct zink_vertex_elements_state;
|
||||||
|
struct zink_rasterizer_state;
|
||||||
|
struct zink_blend_state;
|
||||||
|
struct zink_depth_stencil_alpha_state;
|
||||||
|
|
||||||
|
struct zink_sampler_view {
|
||||||
|
struct pipe_sampler_view base;
|
||||||
|
VkImageView image_view;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zink_context {
|
||||||
|
struct pipe_context base;
|
||||||
|
struct slab_child_pool transfer_pool;
|
||||||
|
struct blitter_context *blitter;
|
||||||
|
|
||||||
|
VkCommandPool cmdpool;
|
||||||
|
struct zink_cmdbuf cmdbuf;
|
||||||
|
|
||||||
|
VkQueue queue;
|
||||||
|
|
||||||
|
VkDescriptorPool descpool;
|
||||||
|
|
||||||
|
struct pipe_constant_buffer ubos[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
|
||||||
|
struct pipe_framebuffer_state fb_state;
|
||||||
|
|
||||||
|
struct zink_shader *gfx_stages[PIPE_SHADER_TYPES - 1];
|
||||||
|
struct zink_gfx_pipeline_state gfx_pipeline_state;
|
||||||
|
|
||||||
|
struct primconvert_context *primconvert;
|
||||||
|
|
||||||
|
struct zink_render_pass *render_pass;
|
||||||
|
struct zink_framebuffer *framebuffer;
|
||||||
|
|
||||||
|
VkViewport viewports[PIPE_MAX_VIEWPORTS];
|
||||||
|
unsigned num_viewports;
|
||||||
|
|
||||||
|
VkRect2D scissors[PIPE_MAX_VIEWPORTS];
|
||||||
|
unsigned num_scissors;
|
||||||
|
|
||||||
|
struct pipe_vertex_buffer buffers[PIPE_MAX_ATTRIBS];
|
||||||
|
uint32_t buffers_enabled_mask;
|
||||||
|
|
||||||
|
VkSampler samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
|
||||||
|
struct pipe_sampler_view *image_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
|
||||||
|
|
||||||
|
float blend_constants[4];
|
||||||
|
|
||||||
|
uint32_t stencil_ref[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct zink_context *
|
||||||
|
zink_context(struct pipe_context *context)
|
||||||
|
{
|
||||||
|
return (struct zink_context *)context;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_resource_barrier(VkCommandBuffer cmdbuf, struct zink_resource *res,
|
||||||
|
VkImageAspectFlags aspect, VkImageLayout new_layout);
|
||||||
|
|
||||||
|
VkShaderStageFlagBits
|
||||||
|
zink_shader_stage(enum pipe_shader_type type);
|
||||||
|
|
||||||
|
struct pipe_context *
|
||||||
|
zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags);
|
||||||
|
|
||||||
|
#endif
|
||||||
100
src/gallium/drivers/zink/zink_fence.c
Normal file
100
src/gallium/drivers/zink/zink_fence.c
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zink_fence.h"
|
||||||
|
|
||||||
|
#include "zink_screen.h"
|
||||||
|
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
|
||||||
|
struct zink_fence *
|
||||||
|
zink_create_fence(struct pipe_screen *pscreen)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pscreen);
|
||||||
|
|
||||||
|
VkFenceCreateInfo fci = {};
|
||||||
|
fci.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||||
|
|
||||||
|
struct zink_fence *ret = CALLOC_STRUCT(zink_fence);
|
||||||
|
if (!ret) {
|
||||||
|
debug_printf("CALLOC_STRUCT failed\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vkCreateFence(screen->dev, &fci, NULL, &ret->fence) != VK_SUCCESS) {
|
||||||
|
debug_printf("vkCreateFence failed\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipe_reference_init(&ret->reference, 1);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
FREE(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_fence_reference(struct zink_screen *screen,
|
||||||
|
struct zink_fence **ptr,
|
||||||
|
struct zink_fence *fence)
|
||||||
|
{
|
||||||
|
if (pipe_reference(&(*ptr)->reference, &fence->reference)) {
|
||||||
|
vkDestroyFence(screen->dev, (*ptr)->fence, NULL);
|
||||||
|
free(*ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
*ptr = fence;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fence_reference(struct pipe_screen *pscreen,
|
||||||
|
struct pipe_fence_handle **pptr,
|
||||||
|
struct pipe_fence_handle *pfence)
|
||||||
|
{
|
||||||
|
zink_fence_reference(zink_screen(pscreen), (struct zink_fence **)pptr,
|
||||||
|
zink_fence(pfence));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
zink_fence_finish(struct zink_screen *screen, struct zink_fence *fence,
|
||||||
|
uint64_t timeout_ns)
|
||||||
|
{
|
||||||
|
return vkWaitForFences(screen->dev, 1, &fence->fence, VK_TRUE,
|
||||||
|
timeout_ns) == VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
fence_finish(struct pipe_screen *pscreen, struct pipe_context *pctx,
|
||||||
|
struct pipe_fence_handle *pfence, uint64_t timeout_ns)
|
||||||
|
{
|
||||||
|
return zink_fence_finish(zink_screen(pscreen), zink_fence(pfence),
|
||||||
|
timeout_ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_screen_fence_init(struct pipe_screen *pscreen)
|
||||||
|
{
|
||||||
|
pscreen->fence_reference = fence_reference;
|
||||||
|
pscreen->fence_finish = fence_finish;
|
||||||
|
}
|
||||||
60
src/gallium/drivers/zink/zink_fence.h
Normal file
60
src/gallium/drivers/zink/zink_fence.h
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_FENCE_H
|
||||||
|
#define ZINK_FENCE_H
|
||||||
|
|
||||||
|
#include "util/u_inlines.h"
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
struct pipe_screen;
|
||||||
|
struct zink_screen;
|
||||||
|
|
||||||
|
struct zink_fence {
|
||||||
|
struct pipe_reference reference;
|
||||||
|
VkFence fence;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct zink_fence *
|
||||||
|
zink_fence(struct pipe_fence_handle *pfence)
|
||||||
|
{
|
||||||
|
return (struct zink_fence *)pfence;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zink_fence *
|
||||||
|
zink_create_fence(struct pipe_screen *pscreen);
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_fence_reference(struct zink_screen *screen,
|
||||||
|
struct zink_fence **ptr,
|
||||||
|
struct zink_fence *fence);
|
||||||
|
|
||||||
|
bool
|
||||||
|
zink_fence_finish(struct zink_screen *screen, struct zink_fence *fence,
|
||||||
|
uint64_t timeout_ns);
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_screen_fence_init(struct pipe_screen *pscreen);
|
||||||
|
|
||||||
|
#endif
|
||||||
95
src/gallium/drivers/zink/zink_framebuffer.c
Normal file
95
src/gallium/drivers/zink/zink_framebuffer.c
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zink_framebuffer.h"
|
||||||
|
|
||||||
|
#include "zink_render_pass.h"
|
||||||
|
#include "zink_screen.h"
|
||||||
|
#include "zink_surface.h"
|
||||||
|
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
#include "util/u_string.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_destroy_framebuffer(struct zink_screen *screen,
|
||||||
|
struct zink_framebuffer *fbuf)
|
||||||
|
{
|
||||||
|
vkDestroyFramebuffer(screen->dev, fbuf->fb, NULL);
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(fbuf->surfaces); ++i)
|
||||||
|
pipe_surface_reference(fbuf->surfaces + i, NULL);
|
||||||
|
|
||||||
|
zink_render_pass_reference(screen, &fbuf->rp, NULL);
|
||||||
|
|
||||||
|
FREE(fbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zink_framebuffer *
|
||||||
|
zink_create_framebuffer(struct zink_screen *screen,
|
||||||
|
const struct pipe_framebuffer_state *fb,
|
||||||
|
struct zink_render_pass *rp)
|
||||||
|
{
|
||||||
|
struct zink_framebuffer *fbuf = CALLOC_STRUCT(zink_framebuffer);
|
||||||
|
if (!fbuf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pipe_reference_init(&fbuf->reference, 1);
|
||||||
|
|
||||||
|
VkImageView attachments[PIPE_MAX_COLOR_BUFS + 1];
|
||||||
|
for (int i = 0; i < fb->nr_cbufs; i++) {
|
||||||
|
struct pipe_surface *psurf = fb->cbufs[i];
|
||||||
|
pipe_surface_reference(fbuf->surfaces + i, psurf);
|
||||||
|
attachments[i] = zink_surface(psurf)->image_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_attachments = fb->nr_cbufs;
|
||||||
|
if (fb->zsbuf) {
|
||||||
|
struct pipe_surface *psurf = fb->zsbuf;
|
||||||
|
pipe_surface_reference(fbuf->surfaces + num_attachments, psurf);
|
||||||
|
attachments[num_attachments++] = zink_surface(psurf)->image_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(rp);
|
||||||
|
zink_render_pass_reference(screen, &fbuf->rp, rp);
|
||||||
|
|
||||||
|
VkFramebufferCreateInfo fci = {};
|
||||||
|
fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||||
|
fci.renderPass = rp->render_pass;
|
||||||
|
fci.attachmentCount = num_attachments;
|
||||||
|
fci.pAttachments = attachments;
|
||||||
|
fci.width = (uint32_t)fb->width;
|
||||||
|
fci.height = (uint32_t)fb->height;
|
||||||
|
fci.layers = (uint32_t)MAX2(fb->layers, 1);
|
||||||
|
|
||||||
|
if (vkCreateFramebuffer(screen->dev, &fci, NULL, &fbuf->fb) != VK_SUCCESS) {
|
||||||
|
zink_destroy_framebuffer(screen, fbuf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
debug_describe_zink_framebuffer(char* buf, const struct zink_framebuffer *ptr)
|
||||||
|
{
|
||||||
|
sprintf(buf, "zink_framebuffer");
|
||||||
|
}
|
||||||
68
src/gallium/drivers/zink/zink_framebuffer.h
Normal file
68
src/gallium/drivers/zink/zink_framebuffer.h
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_FRAMEBUFFER_H
|
||||||
|
#define ZINK_FRAMEBUFFER_H
|
||||||
|
|
||||||
|
#include "pipe/p_state.h"
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
#include "util/u_inlines.h"
|
||||||
|
|
||||||
|
struct zink_screen;
|
||||||
|
struct zink_render_pass;
|
||||||
|
|
||||||
|
struct zink_framebuffer {
|
||||||
|
struct pipe_reference reference;
|
||||||
|
VkFramebuffer fb;
|
||||||
|
|
||||||
|
struct pipe_surface *surfaces[PIPE_MAX_COLOR_BUFS + 1];
|
||||||
|
struct zink_render_pass *rp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zink_framebuffer *
|
||||||
|
zink_create_framebuffer(struct zink_screen *screen,
|
||||||
|
const struct pipe_framebuffer_state *fb,
|
||||||
|
struct zink_render_pass *rp);
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_destroy_framebuffer(struct zink_screen *screen,
|
||||||
|
struct zink_framebuffer *fbuf);
|
||||||
|
|
||||||
|
void
|
||||||
|
debug_describe_zink_framebuffer(char* buf, const struct zink_framebuffer *ptr);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
zink_framebuffer_reference(struct zink_screen *screen,
|
||||||
|
struct zink_framebuffer **dst,
|
||||||
|
struct zink_framebuffer *src)
|
||||||
|
{
|
||||||
|
struct zink_framebuffer *old_dst = *dst;
|
||||||
|
|
||||||
|
if (pipe_reference_described(&old_dst->reference, &src->reference,
|
||||||
|
(debug_reference_descriptor) debug_describe_zink_framebuffer))
|
||||||
|
zink_destroy_framebuffer(screen, old_dst);
|
||||||
|
*dst = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
151
src/gallium/drivers/zink/zink_pipeline.c
Normal file
151
src/gallium/drivers/zink/zink_pipeline.c
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zink_pipeline.h"
|
||||||
|
|
||||||
|
#include "zink_compiler.h"
|
||||||
|
#include "zink_context.h"
|
||||||
|
#include "zink_program.h"
|
||||||
|
#include "zink_screen.h"
|
||||||
|
#include "zink_state.h"
|
||||||
|
|
||||||
|
#include "util/u_debug.h"
|
||||||
|
#include "util/u_prim.h"
|
||||||
|
|
||||||
|
VkPipeline
|
||||||
|
zink_create_gfx_pipeline(VkDevice dev, struct zink_gfx_program *prog,
|
||||||
|
struct zink_gfx_pipeline_state *state,
|
||||||
|
VkRenderPass render_pass)
|
||||||
|
{
|
||||||
|
VkPipelineVertexInputStateCreateInfo vertex_input_state = {};
|
||||||
|
vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
vertex_input_state.pVertexBindingDescriptions = state->bindings;
|
||||||
|
vertex_input_state.vertexBindingDescriptionCount = state->element_state->num_bindings;
|
||||||
|
vertex_input_state.pVertexAttributeDescriptions = state->element_state->attribs;
|
||||||
|
vertex_input_state.vertexAttributeDescriptionCount = state->element_state->num_attribs;
|
||||||
|
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo primitive_state = {};
|
||||||
|
primitive_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
|
primitive_state.topology = state->primitive_topology;
|
||||||
|
primitive_state.primitiveRestartEnable = VK_FALSE;
|
||||||
|
|
||||||
|
VkPipelineColorBlendStateCreateInfo blend_state = {};
|
||||||
|
blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||||
|
blend_state.pAttachments = state->blend_state->attachments;
|
||||||
|
blend_state.attachmentCount = state->num_attachments;
|
||||||
|
blend_state.logicOpEnable = state->blend_state->logicop_enable;
|
||||||
|
blend_state.logicOp = state->blend_state->logicop_func;
|
||||||
|
|
||||||
|
VkPipelineMultisampleStateCreateInfo ms_state = {};
|
||||||
|
ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
|
ms_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
ms_state.alphaToCoverageEnable = state->blend_state->alpha_to_coverage;
|
||||||
|
ms_state.alphaToOneEnable = state->blend_state->alpha_to_one;
|
||||||
|
|
||||||
|
VkPipelineViewportStateCreateInfo viewport_state = {};
|
||||||
|
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||||
|
viewport_state.viewportCount = 1;
|
||||||
|
viewport_state.pViewports = NULL;
|
||||||
|
viewport_state.scissorCount = 1;
|
||||||
|
viewport_state.pScissors = NULL;
|
||||||
|
|
||||||
|
VkPipelineRasterizationStateCreateInfo rast_state = {};
|
||||||
|
rast_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||||
|
|
||||||
|
rast_state.depthClampEnable = state->rast_state->depth_clamp;
|
||||||
|
rast_state.rasterizerDiscardEnable = state->rast_state->rasterizer_discard;
|
||||||
|
rast_state.polygonMode = state->rast_state->polygon_mode;
|
||||||
|
rast_state.cullMode = state->rast_state->cull_mode;
|
||||||
|
rast_state.frontFace = state->rast_state->front_face;
|
||||||
|
|
||||||
|
rast_state.depthBiasEnable = VK_TRUE;
|
||||||
|
rast_state.depthBiasConstantFactor = 0.0;
|
||||||
|
rast_state.depthBiasClamp = 0.0;
|
||||||
|
rast_state.depthBiasSlopeFactor = 0.0;
|
||||||
|
rast_state.lineWidth = state->line_width;
|
||||||
|
|
||||||
|
VkPipelineDepthStencilStateCreateInfo depth_stencil_state = {};
|
||||||
|
depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||||
|
depth_stencil_state.depthTestEnable = state->depth_stencil_alpha_state->depth_test;
|
||||||
|
depth_stencil_state.depthCompareOp = state->depth_stencil_alpha_state->depth_compare_op;
|
||||||
|
depth_stencil_state.depthBoundsTestEnable = state->depth_stencil_alpha_state->depth_bounds_test;
|
||||||
|
depth_stencil_state.minDepthBounds = state->depth_stencil_alpha_state->min_depth_bounds;
|
||||||
|
depth_stencil_state.maxDepthBounds = state->depth_stencil_alpha_state->max_depth_bounds;
|
||||||
|
depth_stencil_state.stencilTestEnable = state->depth_stencil_alpha_state->stencil_test;
|
||||||
|
depth_stencil_state.front = state->depth_stencil_alpha_state->stencil_front;
|
||||||
|
depth_stencil_state.back = state->depth_stencil_alpha_state->stencil_back;
|
||||||
|
depth_stencil_state.depthWriteEnable = state->depth_stencil_alpha_state->depth_write;
|
||||||
|
|
||||||
|
VkDynamicState dynamicStateEnables[] = {
|
||||||
|
VK_DYNAMIC_STATE_DEPTH_BIAS,
|
||||||
|
VK_DYNAMIC_STATE_SCISSOR,
|
||||||
|
VK_DYNAMIC_STATE_STENCIL_REFERENCE,
|
||||||
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
|
VK_DYNAMIC_STATE_BLEND_CONSTANTS,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {};
|
||||||
|
pipelineDynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||||
|
pipelineDynamicStateCreateInfo.pDynamicStates = dynamicStateEnables;
|
||||||
|
pipelineDynamicStateCreateInfo.dynamicStateCount = ARRAY_SIZE(dynamicStateEnables);
|
||||||
|
|
||||||
|
VkGraphicsPipelineCreateInfo pci = {};
|
||||||
|
pci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
|
pci.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
|
||||||
|
pci.layout = prog->layout;
|
||||||
|
pci.renderPass = render_pass;
|
||||||
|
pci.pVertexInputState = &vertex_input_state;
|
||||||
|
pci.pInputAssemblyState = &primitive_state;
|
||||||
|
pci.pRasterizationState = &rast_state;
|
||||||
|
pci.pColorBlendState = &blend_state;
|
||||||
|
pci.pMultisampleState = &ms_state;
|
||||||
|
pci.pViewportState = &viewport_state;
|
||||||
|
pci.pDepthStencilState = &depth_stencil_state;
|
||||||
|
pci.pDynamicState = &pipelineDynamicStateCreateInfo;
|
||||||
|
|
||||||
|
VkPipelineShaderStageCreateInfo shader_stages[PIPE_SHADER_TYPES - 1];
|
||||||
|
uint32_t num_stages = 0;
|
||||||
|
for (int i = 0; i < PIPE_SHADER_TYPES - 1; ++i) {
|
||||||
|
if (!prog->stages[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
VkPipelineShaderStageCreateInfo stage = {};
|
||||||
|
stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
|
stage.stage = zink_shader_stage(i);
|
||||||
|
stage.module = prog->stages[i]->shader_module;
|
||||||
|
stage.pName = "main";
|
||||||
|
shader_stages[num_stages++] = stage;
|
||||||
|
}
|
||||||
|
assert(num_stages > 0);
|
||||||
|
|
||||||
|
pci.pStages = shader_stages;
|
||||||
|
pci.stageCount = num_stages;
|
||||||
|
|
||||||
|
VkPipeline pipeline;
|
||||||
|
if (vkCreateGraphicsPipelines(dev, VK_NULL_HANDLE, 1, &pci, NULL, &pipeline) != VK_SUCCESS) {
|
||||||
|
debug_printf("vkCreateGraphicsPipelines failed\n");
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
59
src/gallium/drivers/zink/zink_pipeline.h
Normal file
59
src/gallium/drivers/zink/zink_pipeline.h
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_PIPELINE_H
|
||||||
|
#define ZINK_PIPELINE_H
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
#include "pipe/p_state.h"
|
||||||
|
|
||||||
|
struct zink_blend_state;
|
||||||
|
struct zink_depth_stencil_alpha_state;
|
||||||
|
struct zink_gfx_program;
|
||||||
|
struct zink_rasterizer_state;
|
||||||
|
struct zink_shader;
|
||||||
|
struct zink_vertex_elements_state;
|
||||||
|
|
||||||
|
struct zink_gfx_pipeline_state {
|
||||||
|
VkPrimitiveTopology primitive_topology;
|
||||||
|
|
||||||
|
struct zink_vertex_elements_state *element_state;
|
||||||
|
VkVertexInputBindingDescription bindings[PIPE_MAX_ATTRIBS]; // combination of element_state and stride
|
||||||
|
|
||||||
|
uint32_t num_attachments;
|
||||||
|
struct zink_blend_state *blend_state;
|
||||||
|
|
||||||
|
struct zink_rasterizer_state *rast_state;
|
||||||
|
|
||||||
|
struct zink_depth_stencil_alpha_state *depth_stencil_alpha_state;
|
||||||
|
|
||||||
|
float line_width;
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipeline
|
||||||
|
zink_create_gfx_pipeline(VkDevice dev, struct zink_gfx_program *prog,
|
||||||
|
struct zink_gfx_pipeline_state *state,
|
||||||
|
VkRenderPass render_pass);
|
||||||
|
|
||||||
|
#endif
|
||||||
132
src/gallium/drivers/zink/zink_program.c
Normal file
132
src/gallium/drivers/zink/zink_program.c
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zink_program.h"
|
||||||
|
|
||||||
|
#include "zink_compiler.h"
|
||||||
|
#include "zink_context.h"
|
||||||
|
|
||||||
|
#include "util/u_debug.h"
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
|
||||||
|
static VkDescriptorSetLayout
|
||||||
|
create_desc_set_layout(VkDevice dev,
|
||||||
|
struct zink_shader *stages[PIPE_SHADER_TYPES - 1])
|
||||||
|
{
|
||||||
|
VkDescriptorSetLayoutBinding bindings[PIPE_SHADER_TYPES * PIPE_MAX_CONSTANT_BUFFERS];
|
||||||
|
int num_bindings = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < PIPE_SHADER_TYPES - 1; i++) {
|
||||||
|
struct zink_shader *shader = stages[i];
|
||||||
|
if (!shader)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
VkShaderStageFlagBits stage_flags = zink_shader_stage(i);
|
||||||
|
for (int j = 0; j < shader->num_bindings; j++) {
|
||||||
|
assert(num_bindings < ARRAY_SIZE(bindings));
|
||||||
|
bindings[num_bindings].binding = shader->bindings[j].binding;
|
||||||
|
bindings[num_bindings].descriptorType = shader->bindings[j].type;
|
||||||
|
bindings[num_bindings].descriptorCount = 1;
|
||||||
|
bindings[num_bindings].stageFlags = stage_flags;
|
||||||
|
bindings[num_bindings].pImmutableSamplers = NULL;
|
||||||
|
++num_bindings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDescriptorSetLayoutCreateInfo dcslci = {};
|
||||||
|
dcslci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||||
|
dcslci.pNext = NULL;
|
||||||
|
dcslci.flags = 0;
|
||||||
|
dcslci.bindingCount = num_bindings;
|
||||||
|
dcslci.pBindings = bindings;
|
||||||
|
|
||||||
|
VkDescriptorSetLayout dsl;
|
||||||
|
if (vkCreateDescriptorSetLayout(dev, &dcslci, 0, &dsl) != VK_SUCCESS) {
|
||||||
|
debug_printf("vkCreateDescriptorSetLayout failed\n");
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dsl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkPipelineLayout
|
||||||
|
create_pipeline_layout(VkDevice dev, VkDescriptorSetLayout dsl)
|
||||||
|
{
|
||||||
|
assert(dsl != VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
VkPipelineLayoutCreateInfo plci = {};
|
||||||
|
plci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
|
|
||||||
|
plci.pSetLayouts = &dsl;
|
||||||
|
plci.setLayoutCount = 1;
|
||||||
|
|
||||||
|
VkPipelineLayout layout;
|
||||||
|
if (vkCreatePipelineLayout(dev, &plci, NULL, &layout) != VK_SUCCESS) {
|
||||||
|
debug_printf("vkCreatePipelineLayout failed!\n");
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zink_gfx_program *
|
||||||
|
zink_create_gfx_program(VkDevice dev,
|
||||||
|
struct zink_shader *stages[PIPE_SHADER_TYPES - 1])
|
||||||
|
{
|
||||||
|
struct zink_gfx_program *prog = CALLOC_STRUCT(zink_gfx_program);
|
||||||
|
if (!prog) {
|
||||||
|
debug_printf("failed to allocate gfx-program\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < PIPE_SHADER_TYPES - 1; ++i)
|
||||||
|
prog->stages[i] = stages[i];
|
||||||
|
|
||||||
|
prog->dsl = create_desc_set_layout(dev, stages);
|
||||||
|
if (!prog->dsl)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
prog->layout = create_pipeline_layout(dev, prog->dsl);
|
||||||
|
if (!prog->layout)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return prog;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (prog)
|
||||||
|
zink_destroy_gfx_program(dev, prog);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_destroy_gfx_program(VkDevice dev, struct zink_gfx_program *prog)
|
||||||
|
{
|
||||||
|
if (prog->layout)
|
||||||
|
vkDestroyPipelineLayout(dev, prog->layout, NULL);
|
||||||
|
|
||||||
|
if (prog->dsl)
|
||||||
|
vkDestroyDescriptorSetLayout(dev, prog->dsl, NULL);
|
||||||
|
|
||||||
|
FREE(prog);
|
||||||
|
}
|
||||||
|
|
||||||
48
src/gallium/drivers/zink/zink_program.h
Normal file
48
src/gallium/drivers/zink/zink_program.h
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_PROGRAM_H
|
||||||
|
#define ZINK_PROGRAM_H
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
#include "pipe/p_state.h"
|
||||||
|
|
||||||
|
struct zink_context;
|
||||||
|
struct zink_shader;
|
||||||
|
struct zink_gfx_pipeline_state;
|
||||||
|
|
||||||
|
struct zink_gfx_program {
|
||||||
|
struct zink_shader *stages[PIPE_SHADER_TYPES - 1]; // compute stage doesn't belong here
|
||||||
|
VkDescriptorSetLayout dsl;
|
||||||
|
VkPipelineLayout layout;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zink_gfx_program *
|
||||||
|
zink_create_gfx_program(VkDevice dev,
|
||||||
|
struct zink_shader *stages[PIPE_SHADER_TYPES - 1]);
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_destroy_gfx_program(VkDevice dev, struct zink_gfx_program *);
|
||||||
|
|
||||||
|
#endif
|
||||||
33
src/gallium/drivers/zink/zink_public.h
Normal file
33
src/gallium/drivers/zink/zink_public.h
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_PUBLIC_H
|
||||||
|
#define ZINK_PUBLIC_H
|
||||||
|
|
||||||
|
struct pipe_screen;
|
||||||
|
struct sw_winsys;
|
||||||
|
|
||||||
|
struct pipe_screen *
|
||||||
|
zink_create_screen(struct sw_winsys *winsys);
|
||||||
|
|
||||||
|
#endif
|
||||||
124
src/gallium/drivers/zink/zink_render_pass.c
Normal file
124
src/gallium/drivers/zink/zink_render_pass.c
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zink_render_pass.h"
|
||||||
|
|
||||||
|
#include "zink_screen.h"
|
||||||
|
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
#include "util/u_string.h"
|
||||||
|
|
||||||
|
static VkRenderPass
|
||||||
|
create_render_pass(VkDevice dev, struct zink_render_pass_state *state)
|
||||||
|
{
|
||||||
|
|
||||||
|
VkAttachmentReference color_refs[PIPE_MAX_COLOR_BUFS], zs_ref;
|
||||||
|
VkAttachmentDescription attachments[PIPE_MAX_COLOR_BUFS + 1];
|
||||||
|
|
||||||
|
for (int i = 0; i < state->num_cbufs; i++) {
|
||||||
|
struct zink_rt_attrib *rt = state->rts + i;
|
||||||
|
attachments[i].flags = 0;
|
||||||
|
attachments[i].format = rt->format;
|
||||||
|
attachments[i].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
attachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
|
attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
attachments[i].initialLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
attachments[i].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
color_refs[i].attachment = i;
|
||||||
|
color_refs[i].layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_attachments = state->num_cbufs;
|
||||||
|
if (state->have_zsbuf) {
|
||||||
|
struct zink_rt_attrib *rt = state->rts + state->num_cbufs;
|
||||||
|
attachments[num_attachments].flags = 0;
|
||||||
|
attachments[num_attachments].format = rt->format;
|
||||||
|
attachments[num_attachments].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
attachments[num_attachments].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
|
attachments[num_attachments].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
attachments[num_attachments].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
|
attachments[num_attachments].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
attachments[num_attachments].initialLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
attachments[num_attachments].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
|
||||||
|
zs_ref.attachment = num_attachments++;
|
||||||
|
zs_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSubpassDescription subpass = {};
|
||||||
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
|
subpass.colorAttachmentCount = state->num_cbufs;
|
||||||
|
subpass.pColorAttachments = color_refs;
|
||||||
|
subpass.pDepthStencilAttachment = state->have_zsbuf ? &zs_ref : NULL;
|
||||||
|
|
||||||
|
VkRenderPassCreateInfo rpci = {};
|
||||||
|
rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||||
|
rpci.attachmentCount = num_attachments;
|
||||||
|
rpci.pAttachments = attachments;
|
||||||
|
rpci.subpassCount = 1;
|
||||||
|
rpci.pSubpasses = &subpass;
|
||||||
|
|
||||||
|
VkRenderPass render_pass;
|
||||||
|
if (vkCreateRenderPass(dev, &rpci, NULL, &render_pass) != VK_SUCCESS)
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
return render_pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zink_render_pass *
|
||||||
|
zink_create_render_pass(struct zink_screen *screen,
|
||||||
|
struct zink_render_pass_state *state)
|
||||||
|
{
|
||||||
|
struct zink_render_pass *rp = CALLOC_STRUCT(zink_render_pass);
|
||||||
|
if (!rp)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
pipe_reference_init(&rp->reference, 1);
|
||||||
|
|
||||||
|
rp->render_pass = create_render_pass(screen->dev, state);
|
||||||
|
if (!rp->render_pass)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return rp;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (rp)
|
||||||
|
zink_destroy_render_pass(screen, rp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_destroy_render_pass(struct zink_screen *screen,
|
||||||
|
struct zink_render_pass *rp)
|
||||||
|
{
|
||||||
|
vkDestroyRenderPass(screen->dev, rp->render_pass, NULL);
|
||||||
|
FREE(rp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
debug_describe_zink_render_pass(char* buf, const struct zink_render_pass *ptr)
|
||||||
|
{
|
||||||
|
sprintf(buf, "zink_render_pass");
|
||||||
|
}
|
||||||
74
src/gallium/drivers/zink/zink_render_pass.h
Normal file
74
src/gallium/drivers/zink/zink_render_pass.h
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_RENDERPASS_H
|
||||||
|
#define ZINK_RENDERPASS_H
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
#include "pipe/p_state.h"
|
||||||
|
#include "util/u_inlines.h"
|
||||||
|
|
||||||
|
struct zink_screen;
|
||||||
|
|
||||||
|
struct zink_rt_attrib {
|
||||||
|
VkFormat format;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zink_render_pass_state {
|
||||||
|
uint8_t num_cbufs : 4; /* PIPE_MAX_COLOR_BUFS = 8 */
|
||||||
|
uint8_t have_zsbuf : 1;
|
||||||
|
struct zink_rt_attrib rts[PIPE_MAX_COLOR_BUFS + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zink_render_pass {
|
||||||
|
struct pipe_reference reference;
|
||||||
|
|
||||||
|
VkRenderPass render_pass;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zink_render_pass *
|
||||||
|
zink_create_render_pass(struct zink_screen *screen,
|
||||||
|
struct zink_render_pass_state *state);
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_destroy_render_pass(struct zink_screen *screen,
|
||||||
|
struct zink_render_pass *rp);
|
||||||
|
|
||||||
|
void
|
||||||
|
debug_describe_zink_render_pass(char* buf, const struct zink_render_pass *ptr);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
zink_render_pass_reference(struct zink_screen *screen,
|
||||||
|
struct zink_render_pass **dst,
|
||||||
|
struct zink_render_pass *src)
|
||||||
|
{
|
||||||
|
struct zink_render_pass *old_dst = *dst;
|
||||||
|
|
||||||
|
if (pipe_reference_described(&old_dst->reference, &src->reference,
|
||||||
|
(debug_reference_descriptor) debug_describe_zink_render_pass))
|
||||||
|
zink_destroy_render_pass(screen, old_dst);
|
||||||
|
*dst = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
465
src/gallium/drivers/zink/zink_resource.c
Normal file
465
src/gallium/drivers/zink/zink_resource.c
Normal file
|
|
@ -0,0 +1,465 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zink_resource.h"
|
||||||
|
|
||||||
|
#include "zink_cmdbuf.h"
|
||||||
|
#include "zink_context.h"
|
||||||
|
#include "zink_screen.h"
|
||||||
|
|
||||||
|
#include "util/slab.h"
|
||||||
|
#include "util/u_debug.h"
|
||||||
|
#include "util/u_format.h"
|
||||||
|
#include "util/u_inlines.h"
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
|
||||||
|
#include "state_tracker/sw_winsys.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_resource_destroy(struct pipe_screen *pscreen,
|
||||||
|
struct pipe_resource *pres)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pscreen);
|
||||||
|
struct zink_resource *res = zink_resource(pres);
|
||||||
|
if (pres->target == PIPE_BUFFER)
|
||||||
|
vkDestroyBuffer(screen->dev, res->buffer, NULL);
|
||||||
|
else
|
||||||
|
vkDestroyImage(screen->dev, res->image, NULL);
|
||||||
|
|
||||||
|
vkFreeMemory(screen->dev, res->mem, NULL);
|
||||||
|
FREE(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
get_memory_type_index(struct zink_screen *screen,
|
||||||
|
const VkMemoryRequirements *reqs,
|
||||||
|
VkMemoryPropertyFlags props)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0u; i < VK_MAX_MEMORY_TYPES; i++) {
|
||||||
|
if (((reqs->memoryTypeBits >> i) & 1) == 1) {
|
||||||
|
if ((screen->mem_props.memoryTypes[i].propertyFlags & props) == props) {
|
||||||
|
return i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable("Unsupported memory-type");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImageAspectFlags
|
||||||
|
zink_aspect_from_format(enum pipe_format fmt)
|
||||||
|
{
|
||||||
|
if (util_format_is_depth_or_stencil(fmt)) {
|
||||||
|
VkImageAspectFlags aspect = 0;
|
||||||
|
const struct util_format_description *desc = util_format_description(fmt);
|
||||||
|
if (util_format_has_depth(desc))
|
||||||
|
aspect |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
if (util_format_has_stencil(desc))
|
||||||
|
aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||||
|
return aspect;
|
||||||
|
} else
|
||||||
|
return VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pipe_resource *
|
||||||
|
zink_resource_create(struct pipe_screen *pscreen,
|
||||||
|
const struct pipe_resource *templ)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pscreen);
|
||||||
|
struct zink_resource *res = CALLOC_STRUCT(zink_resource);
|
||||||
|
|
||||||
|
res->base = *templ;
|
||||||
|
|
||||||
|
pipe_reference_init(&res->base.reference, 1);
|
||||||
|
res->base.screen = pscreen;
|
||||||
|
|
||||||
|
VkMemoryRequirements reqs;
|
||||||
|
VkMemoryPropertyFlags flags = 0;
|
||||||
|
if (templ->target == PIPE_BUFFER) {
|
||||||
|
VkBufferCreateInfo bci = {};
|
||||||
|
bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
bci.size = templ->width0;
|
||||||
|
|
||||||
|
bci.usage = 0;
|
||||||
|
|
||||||
|
if (templ->bind & PIPE_BIND_VERTEX_BUFFER)
|
||||||
|
bci.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||||
|
|
||||||
|
if (templ->bind & PIPE_BIND_INDEX_BUFFER)
|
||||||
|
bci.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
||||||
|
|
||||||
|
if (templ->bind & PIPE_BIND_CONSTANT_BUFFER)
|
||||||
|
bci.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||||
|
|
||||||
|
if (templ->bind & PIPE_BIND_SHADER_BUFFER)
|
||||||
|
bci.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||||
|
|
||||||
|
if (templ->bind & PIPE_BIND_COMMAND_ARGS_BUFFER)
|
||||||
|
bci.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
|
||||||
|
|
||||||
|
if (templ->usage == PIPE_USAGE_STAGING)
|
||||||
|
bci.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||||
|
|
||||||
|
if (vkCreateBuffer(screen->dev, &bci, NULL, &res->buffer) !=
|
||||||
|
VK_SUCCESS) {
|
||||||
|
FREE(res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vkGetBufferMemoryRequirements(screen->dev, res->buffer, &reqs);
|
||||||
|
flags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||||
|
} else {
|
||||||
|
res->format = zink_get_format(templ->format);
|
||||||
|
|
||||||
|
VkImageCreateInfo ici = {};
|
||||||
|
ici.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
|
|
||||||
|
switch (templ->target) {
|
||||||
|
case PIPE_TEXTURE_1D:
|
||||||
|
case PIPE_TEXTURE_1D_ARRAY:
|
||||||
|
ici.imageType = VK_IMAGE_TYPE_1D;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIPE_TEXTURE_2D:
|
||||||
|
case PIPE_TEXTURE_2D_ARRAY:
|
||||||
|
case PIPE_TEXTURE_CUBE:
|
||||||
|
case PIPE_TEXTURE_CUBE_ARRAY:
|
||||||
|
ici.imageType = VK_IMAGE_TYPE_2D;
|
||||||
|
/* cube and 2D array needs some quirks here */
|
||||||
|
if (templ->target == PIPE_TEXTURE_CUBE)
|
||||||
|
ici.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
||||||
|
else if (templ->target == PIPE_TEXTURE_2D_ARRAY)
|
||||||
|
ici.flags = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
|
||||||
|
else if (templ->target == PIPE_TEXTURE_CUBE_ARRAY)
|
||||||
|
ici.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT |
|
||||||
|
VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIPE_TEXTURE_3D:
|
||||||
|
ici.imageType = VK_IMAGE_TYPE_3D;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIPE_TEXTURE_RECT:
|
||||||
|
unreachable("texture rects not supported");
|
||||||
|
|
||||||
|
case PIPE_BUFFER:
|
||||||
|
unreachable("PIPE_BUFFER should already be handled");
|
||||||
|
|
||||||
|
default:
|
||||||
|
unreachable("Unknown target");
|
||||||
|
}
|
||||||
|
|
||||||
|
ici.format = res->format;
|
||||||
|
ici.extent.width = templ->width0;
|
||||||
|
ici.extent.height = templ->height0;
|
||||||
|
ici.extent.depth = templ->depth0;
|
||||||
|
ici.mipLevels = templ->last_level + 1;
|
||||||
|
ici.arrayLayers = templ->array_size;
|
||||||
|
ici.samples = templ->nr_samples ? templ->nr_samples : VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
ici.tiling = templ->bind & PIPE_BIND_LINEAR ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
|
||||||
|
|
||||||
|
if (templ->target == PIPE_TEXTURE_CUBE ||
|
||||||
|
templ->target == PIPE_TEXTURE_CUBE_ARRAY)
|
||||||
|
ici.arrayLayers *= 6;
|
||||||
|
|
||||||
|
if (templ->bind & (PIPE_BIND_DISPLAY_TARGET |
|
||||||
|
PIPE_BIND_SCANOUT |
|
||||||
|
PIPE_BIND_SHARED)) {
|
||||||
|
// assert(ici.tiling == VK_IMAGE_TILING_LINEAR);
|
||||||
|
ici.tiling = VK_IMAGE_TILING_LINEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (templ->usage == PIPE_USAGE_STAGING)
|
||||||
|
ici.tiling = VK_IMAGE_TILING_LINEAR;
|
||||||
|
|
||||||
|
/* sadly, gallium doesn't let us know if it'll ever need this, so we have to assume */
|
||||||
|
ici.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
|
|
||||||
|
if (templ->bind & PIPE_BIND_SAMPLER_VIEW)
|
||||||
|
ici.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
|
|
||||||
|
if (templ->bind & PIPE_BIND_SHADER_IMAGE)
|
||||||
|
ici.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
|
||||||
|
|
||||||
|
if (templ->bind & PIPE_BIND_RENDER_TARGET)
|
||||||
|
ici.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
|
||||||
|
if (templ->bind & PIPE_BIND_DEPTH_STENCIL)
|
||||||
|
ici.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||||
|
|
||||||
|
if (templ->flags & PIPE_RESOURCE_FLAG_SPARSE)
|
||||||
|
ici.usage |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
|
||||||
|
|
||||||
|
if (templ->bind & PIPE_BIND_STREAM_OUTPUT)
|
||||||
|
ici.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||||
|
|
||||||
|
ici.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
res->layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
|
VkResult result = vkCreateImage(screen->dev, &ici, NULL, &res->image);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
FREE(res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
res->optimial_tiling = ici.tiling != VK_IMAGE_TILING_LINEAR;
|
||||||
|
res->aspect = zink_aspect_from_format(templ->format);
|
||||||
|
|
||||||
|
vkGetImageMemoryRequirements(screen->dev, res->image, &reqs);
|
||||||
|
if (templ->usage == PIPE_USAGE_STAGING || (templ->bind & (PIPE_BIND_SCANOUT|PIPE_BIND_DISPLAY_TARGET|PIPE_BIND_SHARED)))
|
||||||
|
flags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||||
|
else
|
||||||
|
flags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkMemoryAllocateInfo mai = {};
|
||||||
|
mai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
|
mai.allocationSize = reqs.size;
|
||||||
|
mai.memoryTypeIndex = get_memory_type_index(screen, &reqs, flags);
|
||||||
|
|
||||||
|
if (vkAllocateMemory(screen->dev, &mai, NULL, &res->mem) != VK_SUCCESS)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
res->offset = 0;
|
||||||
|
res->size = reqs.size;
|
||||||
|
|
||||||
|
if (templ->target == PIPE_BUFFER)
|
||||||
|
vkBindBufferMemory(screen->dev, res->buffer, res->mem, res->offset);
|
||||||
|
else
|
||||||
|
vkBindImageMemory(screen->dev, res->image, res->mem, res->offset);
|
||||||
|
|
||||||
|
if (templ->bind & (PIPE_BIND_DISPLAY_TARGET |
|
||||||
|
PIPE_BIND_SCANOUT |
|
||||||
|
PIPE_BIND_SHARED)) {
|
||||||
|
struct sw_winsys *winsys = screen->winsys;
|
||||||
|
res->dt = winsys->displaytarget_create(screen->winsys,
|
||||||
|
res->base.bind,
|
||||||
|
res->base.format,
|
||||||
|
templ->width0,
|
||||||
|
templ->height0,
|
||||||
|
64, NULL,
|
||||||
|
&res->dt_stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res->base;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (templ->target == PIPE_BUFFER)
|
||||||
|
vkDestroyBuffer(screen->dev, res->buffer, NULL);
|
||||||
|
else
|
||||||
|
vkDestroyImage(screen->dev, res->image, NULL);
|
||||||
|
|
||||||
|
FREE(res);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_screen_resource_init(struct pipe_screen *pscreen)
|
||||||
|
{
|
||||||
|
pscreen->resource_create = zink_resource_create;
|
||||||
|
pscreen->resource_destroy = zink_resource_destroy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
zink_transfer_copy_bufimage(struct zink_context *ctx,
|
||||||
|
struct zink_resource *res,
|
||||||
|
struct zink_resource *staging_res,
|
||||||
|
struct zink_transfer *trans,
|
||||||
|
bool buf2img)
|
||||||
|
{
|
||||||
|
struct zink_cmdbuf *cmdbuf = zink_start_cmdbuf(ctx);
|
||||||
|
if (!cmdbuf)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (res->layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL &&
|
||||||
|
res->layout != VK_IMAGE_LAYOUT_GENERAL) {
|
||||||
|
zink_resource_barrier(cmdbuf->cmdbuf, res, res->aspect,
|
||||||
|
VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
res->layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkBufferImageCopy copyRegion = {};
|
||||||
|
copyRegion.bufferOffset = staging_res->offset;
|
||||||
|
copyRegion.bufferRowLength = 0;
|
||||||
|
copyRegion.bufferImageHeight = 0;
|
||||||
|
copyRegion.imageSubresource.aspectMask = res->aspect;
|
||||||
|
copyRegion.imageSubresource.mipLevel = trans->base.level;
|
||||||
|
copyRegion.imageSubresource.layerCount = 1;
|
||||||
|
if (res->base.array_size > 1) {
|
||||||
|
copyRegion.imageSubresource.baseArrayLayer = trans->base.box.z;
|
||||||
|
copyRegion.imageSubresource.layerCount = trans->base.box.depth;
|
||||||
|
} else {
|
||||||
|
copyRegion.imageOffset.z = trans->base.box.z;
|
||||||
|
copyRegion.imageExtent.depth = trans->base.box.depth;
|
||||||
|
}
|
||||||
|
copyRegion.imageOffset.x = trans->base.box.x;
|
||||||
|
copyRegion.imageOffset.y = trans->base.box.y;
|
||||||
|
|
||||||
|
copyRegion.imageExtent.width = trans->base.box.width;
|
||||||
|
copyRegion.imageExtent.height = trans->base.box.height;
|
||||||
|
|
||||||
|
if (buf2img)
|
||||||
|
vkCmdCopyBufferToImage(cmdbuf->cmdbuf, staging_res->buffer, res->image, res->layout, 1, ©Region);
|
||||||
|
else
|
||||||
|
vkCmdCopyImageToBuffer(cmdbuf->cmdbuf, res->image, res->layout, staging_res->buffer, 1, ©Region);
|
||||||
|
|
||||||
|
zink_end_cmdbuf(ctx, cmdbuf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
zink_transfer_map(struct pipe_context *pctx,
|
||||||
|
struct pipe_resource *pres,
|
||||||
|
unsigned level,
|
||||||
|
unsigned usage,
|
||||||
|
const struct pipe_box *box,
|
||||||
|
struct pipe_transfer **transfer)
|
||||||
|
{
|
||||||
|
struct zink_context *ctx = zink_context(pctx);
|
||||||
|
struct zink_screen *screen = zink_screen(pctx->screen);
|
||||||
|
struct zink_resource *res = zink_resource(pres);
|
||||||
|
|
||||||
|
struct zink_transfer *trans = slab_alloc(&ctx->transfer_pool);
|
||||||
|
if (!trans)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memset(trans, 0, sizeof(*trans));
|
||||||
|
pipe_resource_reference(&trans->base.resource, pres);
|
||||||
|
|
||||||
|
trans->base.resource = pres;
|
||||||
|
trans->base.level = level;
|
||||||
|
trans->base.usage = usage;
|
||||||
|
trans->base.box = *box;
|
||||||
|
|
||||||
|
void *ptr;
|
||||||
|
if (pres->target == PIPE_BUFFER) {
|
||||||
|
VkResult result = vkMapMemory(screen->dev, res->mem, res->offset, res->size, 0, &ptr);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
trans->base.stride = 0;
|
||||||
|
trans->base.layer_stride = 0;
|
||||||
|
ptr = ((uint8_t *)ptr) + box->x;
|
||||||
|
} else {
|
||||||
|
if (res->optimial_tiling || ((res->base.usage != PIPE_USAGE_STAGING))) {
|
||||||
|
trans->base.stride = util_format_get_stride(pres->format, box->width);
|
||||||
|
trans->base.layer_stride = util_format_get_2d_size(pres->format,
|
||||||
|
trans->base.stride,
|
||||||
|
box->height);
|
||||||
|
|
||||||
|
struct pipe_resource templ = *pres;
|
||||||
|
templ.usage = PIPE_USAGE_STAGING;
|
||||||
|
templ.target = PIPE_BUFFER;
|
||||||
|
templ.bind = 0; // HACK: there's no transfer binding, but usage should tell us enough
|
||||||
|
templ.width0 = trans->base.layer_stride * box->depth;
|
||||||
|
templ.height0 = templ.depth0 = 0;
|
||||||
|
templ.last_level = 0;
|
||||||
|
templ.array_size = 1;
|
||||||
|
templ.flags = 0;
|
||||||
|
|
||||||
|
trans->staging_res = zink_resource_create(pctx->screen, &templ);
|
||||||
|
if (!trans->staging_res)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct zink_resource *staging_res = zink_resource(trans->staging_res);
|
||||||
|
|
||||||
|
if (usage & PIPE_TRANSFER_READ) {
|
||||||
|
struct zink_context *ctx = zink_context(pctx);
|
||||||
|
bool ret = zink_transfer_copy_bufimage(ctx, res,
|
||||||
|
staging_res, trans,
|
||||||
|
false);
|
||||||
|
if (ret == false)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult result = vkMapMemory(screen->dev, staging_res->mem,
|
||||||
|
staging_res->offset,
|
||||||
|
staging_res->size, 0, &ptr);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
assert(!res->optimial_tiling);
|
||||||
|
VkResult result = vkMapMemory(screen->dev, res->mem, res->offset, res->size, 0, &ptr);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
return NULL;
|
||||||
|
VkImageSubresource isr = {
|
||||||
|
res->aspect,
|
||||||
|
level,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
VkSubresourceLayout srl;
|
||||||
|
vkGetImageSubresourceLayout(screen->dev, res->image, &isr, &srl);
|
||||||
|
trans->base.stride = srl.rowPitch;
|
||||||
|
trans->base.layer_stride = srl.arrayPitch;
|
||||||
|
ptr = ((uint8_t *)ptr) + box->z * srl.depthPitch +
|
||||||
|
box->y * srl.rowPitch +
|
||||||
|
box->x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*transfer = &trans->base;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_transfer_unmap(struct pipe_context *pctx,
|
||||||
|
struct pipe_transfer *ptrans)
|
||||||
|
{
|
||||||
|
struct zink_context *ctx = zink_context(pctx);
|
||||||
|
struct zink_screen *screen = zink_screen(pctx->screen);
|
||||||
|
struct zink_resource *res = zink_resource(ptrans->resource);
|
||||||
|
struct zink_transfer *trans = (struct zink_transfer *)ptrans;
|
||||||
|
if (trans->staging_res) {
|
||||||
|
struct zink_resource *staging_res = zink_resource(trans->staging_res);
|
||||||
|
vkUnmapMemory(screen->dev, staging_res->mem);
|
||||||
|
|
||||||
|
if (trans->base.usage & PIPE_TRANSFER_WRITE) {
|
||||||
|
struct zink_context *ctx = zink_context(pctx);
|
||||||
|
|
||||||
|
zink_transfer_copy_bufimage(ctx, res, staging_res, trans, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
zink_resource_destroy(pctx->screen, trans->staging_res);
|
||||||
|
trans->staging_res = NULL;
|
||||||
|
} else
|
||||||
|
vkUnmapMemory(screen->dev, res->mem);
|
||||||
|
|
||||||
|
pipe_resource_reference(&trans->base.resource, NULL);
|
||||||
|
slab_free(&ctx->transfer_pool, ptrans);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_context_resource_init(struct pipe_context *pctx)
|
||||||
|
{
|
||||||
|
pctx->transfer_map = zink_transfer_map;
|
||||||
|
pctx->transfer_unmap = zink_transfer_unmap;
|
||||||
|
|
||||||
|
pctx->transfer_flush_region = u_default_transfer_flush_region;
|
||||||
|
pctx->buffer_subdata = u_default_buffer_subdata;
|
||||||
|
pctx->texture_subdata = u_default_texture_subdata;
|
||||||
|
}
|
||||||
74
src/gallium/drivers/zink/zink_resource.h
Normal file
74
src/gallium/drivers/zink/zink_resource.h
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_RESOURCE_H
|
||||||
|
#define ZINK_RESOURCE_H
|
||||||
|
|
||||||
|
struct pipe_screen;
|
||||||
|
struct sw_displaytarget;
|
||||||
|
|
||||||
|
#include "util/u_transfer.h"
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
struct zink_resource {
|
||||||
|
struct pipe_resource base;
|
||||||
|
|
||||||
|
union {
|
||||||
|
VkBuffer buffer;
|
||||||
|
struct {
|
||||||
|
VkFormat format;
|
||||||
|
VkImage image;
|
||||||
|
VkImageLayout layout;
|
||||||
|
VkImageAspectFlags aspect;
|
||||||
|
bool optimial_tiling;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
VkDeviceMemory mem;
|
||||||
|
VkDeviceSize offset, size;
|
||||||
|
|
||||||
|
struct sw_displaytarget *dt;
|
||||||
|
unsigned dt_stride;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zink_transfer {
|
||||||
|
struct pipe_transfer base;
|
||||||
|
struct pipe_resource *staging_res;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct zink_resource *
|
||||||
|
zink_resource(struct pipe_resource *r)
|
||||||
|
{
|
||||||
|
return (struct zink_resource *)r;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImageAspectFlags
|
||||||
|
zink_aspect_from_format(enum pipe_format fmt);
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_screen_resource_init(struct pipe_screen *pscreen);
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_context_resource_init(struct pipe_context *pctx);
|
||||||
|
|
||||||
|
#endif
|
||||||
752
src/gallium/drivers/zink/zink_screen.c
Normal file
752
src/gallium/drivers/zink/zink_screen.c
Normal file
|
|
@ -0,0 +1,752 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zink_screen.h"
|
||||||
|
|
||||||
|
#include "zink_compiler.h"
|
||||||
|
#include "zink_context.h"
|
||||||
|
#include "zink_fence.h"
|
||||||
|
#include "zink_public.h"
|
||||||
|
#include "zink_resource.h"
|
||||||
|
|
||||||
|
#include "os/os_process.h"
|
||||||
|
#include "util/u_debug.h"
|
||||||
|
#include "util/u_math.h"
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
#include "util/u_screen.h"
|
||||||
|
#include "util/u_string.h"
|
||||||
|
|
||||||
|
#include "state_tracker/sw_winsys.h"
|
||||||
|
|
||||||
|
static const struct debug_named_value
|
||||||
|
debug_options[] = {
|
||||||
|
{ "nir", ZINK_DEBUG_NIR, "Dump NIR during program compile" },
|
||||||
|
{ "spirv", ZINK_DEBUG_SPIRV, "Dump SPIR-V during program compile" },
|
||||||
|
{ "tgsi", ZINK_DEBUG_TGSI, "Dump TGSI during program compile" },
|
||||||
|
DEBUG_NAMED_VALUE_END
|
||||||
|
};
|
||||||
|
|
||||||
|
DEBUG_GET_ONCE_FLAGS_OPTION(zink_debug, "ZINK_DEBUG", debug_options, 0)
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
zink_debug;
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
zink_get_vendor(struct pipe_screen *pscreen)
|
||||||
|
{
|
||||||
|
return "Collabora Ltd";
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
zink_get_device_vendor(struct pipe_screen *pscreen)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pscreen);
|
||||||
|
static char buf[1000];
|
||||||
|
snprintf(buf, sizeof(buf), "Unknown (vendor-id: 0x%04x)", screen->props.vendorID);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
zink_get_name(struct pipe_screen *pscreen)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pscreen);
|
||||||
|
static char buf[1000];
|
||||||
|
snprintf(buf, sizeof(buf), "zink (%s)", screen->props.deviceName);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_video_mem(struct zink_screen *screen)
|
||||||
|
{
|
||||||
|
VkDeviceSize size = 0;
|
||||||
|
for (uint32_t i = 0; i < screen->mem_props.memoryHeapCount; ++i)
|
||||||
|
size += screen->mem_props.memoryHeaps[i].size;
|
||||||
|
return (int)(size >> 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
zink_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pscreen);
|
||||||
|
|
||||||
|
switch (param) {
|
||||||
|
case PIPE_CAP_NPOT_TEXTURES:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
|
||||||
|
return screen->props.limits.maxFragmentDualSrcAttachments;
|
||||||
|
|
||||||
|
case PIPE_CAP_MAX_RENDER_TARGETS:
|
||||||
|
return screen->props.limits.maxColorAttachments;
|
||||||
|
|
||||||
|
case PIPE_CAP_TEXTURE_SWIZZLE:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case PIPE_CAP_MAX_TEXTURE_2D_SIZE:
|
||||||
|
return screen->props.limits.maxImageDimension2D;
|
||||||
|
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
|
||||||
|
return 1 + util_logbase2(screen->props.limits.maxImageDimension3D);
|
||||||
|
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
|
||||||
|
return 1 + util_logbase2(screen->props.limits.maxImageDimensionCube);
|
||||||
|
|
||||||
|
case PIPE_CAP_BLEND_EQUATION_SEPARATE:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:
|
||||||
|
case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:
|
||||||
|
case PIPE_CAP_VERTEX_SHADER_SATURATE:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case PIPE_CAP_INDEP_BLEND_ENABLE:
|
||||||
|
case PIPE_CAP_INDEP_BLEND_FUNC:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
|
||||||
|
return screen->props.limits.maxImageArrayLayers;
|
||||||
|
|
||||||
|
#if 0 /* TODO: Enable me */
|
||||||
|
case PIPE_CAP_DEPTH_CLIP_DISABLE:
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 /* TODO: Enable me */
|
||||||
|
case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case PIPE_CAP_SEAMLESS_CUBE_MAP:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case PIPE_CAP_MIN_TEXEL_OFFSET:
|
||||||
|
return screen->props.limits.minTexelOffset;
|
||||||
|
case PIPE_CAP_MAX_TEXEL_OFFSET:
|
||||||
|
return screen->props.limits.maxTexelOffset;
|
||||||
|
|
||||||
|
case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case PIPE_CAP_GLSL_FEATURE_LEVEL:
|
||||||
|
case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:
|
||||||
|
return 450; /* unsure (probably wrong) */
|
||||||
|
|
||||||
|
#if 0 /* TODO: Enable me */
|
||||||
|
case PIPE_CAP_COMPUTE:
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
|
||||||
|
return screen->props.limits.minUniformBufferOffsetAlignment;
|
||||||
|
|
||||||
|
case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
|
||||||
|
return screen->props.limits.minMemoryMapAlignment;
|
||||||
|
|
||||||
|
case PIPE_CAP_CUBE_MAP_ARRAY:
|
||||||
|
return screen->feats.imageCubeArray;
|
||||||
|
|
||||||
|
case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
|
||||||
|
return 0; /* unsure */
|
||||||
|
|
||||||
|
case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
|
||||||
|
return screen->props.limits.maxTexelBufferElements;
|
||||||
|
|
||||||
|
case PIPE_CAP_ENDIANNESS:
|
||||||
|
return PIPE_ENDIAN_NATIVE; /* unsure */
|
||||||
|
|
||||||
|
case PIPE_CAP_MAX_VIEWPORTS:
|
||||||
|
return screen->props.limits.maxViewports;
|
||||||
|
|
||||||
|
case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
|
||||||
|
return screen->props.limits.maxGeometryOutputVertices;
|
||||||
|
case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
|
||||||
|
return screen->props.limits.maxGeometryOutputComponents;
|
||||||
|
|
||||||
|
#if 0 /* TODO: Enable me. Enables ARB_texture_gather */
|
||||||
|
case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
|
||||||
|
return 4;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET:
|
||||||
|
return screen->props.limits.minTexelGatherOffset;
|
||||||
|
case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET:
|
||||||
|
return screen->props.limits.maxTexelGatherOffset;
|
||||||
|
|
||||||
|
case PIPE_CAP_VENDOR_ID:
|
||||||
|
return screen->props.vendorID;
|
||||||
|
case PIPE_CAP_DEVICE_ID:
|
||||||
|
return screen->props.deviceID;
|
||||||
|
|
||||||
|
case PIPE_CAP_ACCELERATED:
|
||||||
|
return 1;
|
||||||
|
case PIPE_CAP_VIDEO_MEMORY:
|
||||||
|
return get_video_mem(screen);
|
||||||
|
case PIPE_CAP_UMA:
|
||||||
|
/* inaccurate */
|
||||||
|
return screen->props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
|
||||||
|
|
||||||
|
case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
|
||||||
|
return screen->props.limits.maxVertexInputBindingStride;
|
||||||
|
|
||||||
|
#if 0 /* TODO: Enable me */
|
||||||
|
case PIPE_CAP_SAMPLER_VIEW_TARGET:
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 /* TODO: Enable me */
|
||||||
|
case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
|
||||||
|
case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case PIPE_CAP_SHAREABLE_SHADERS:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
#if 0 /* TODO: Enable me. Enables GL_ARB_shader_storage_buffer_object */
|
||||||
|
case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
|
||||||
|
return screen->props.limits.minStorageBufferOffsetAlignment;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case PIPE_CAP_PCI_GROUP:
|
||||||
|
case PIPE_CAP_PCI_BUS:
|
||||||
|
case PIPE_CAP_PCI_DEVICE:
|
||||||
|
case PIPE_CAP_PCI_FUNCTION:
|
||||||
|
return 0; /* TODO: figure these out */
|
||||||
|
|
||||||
|
#if 0 /* TODO: Enable me */
|
||||||
|
case PIPE_CAP_CULL_DISTANCE:
|
||||||
|
return screen->feats.shaderCullDistance;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case PIPE_CAP_VIEWPORT_SUBPIXEL_BITS:
|
||||||
|
return screen->props.limits.viewportSubPixelBits;
|
||||||
|
|
||||||
|
case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:
|
||||||
|
return 0; /* not sure */
|
||||||
|
|
||||||
|
case PIPE_CAP_MAX_GS_INVOCATIONS:
|
||||||
|
return 0; /* not implemented */
|
||||||
|
|
||||||
|
case PIPE_CAP_MAX_COMBINED_SHADER_BUFFERS:
|
||||||
|
return screen->props.limits.maxDescriptorSetStorageBuffers;
|
||||||
|
|
||||||
|
case PIPE_CAP_MAX_SHADER_BUFFER_SIZE:
|
||||||
|
return screen->props.limits.maxStorageBufferRange; /* unsure */
|
||||||
|
|
||||||
|
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
|
||||||
|
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
|
||||||
|
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return u_pipe_screen_get_param_defaults(pscreen, param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static float
|
||||||
|
zink_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pscreen);
|
||||||
|
|
||||||
|
switch (param) {
|
||||||
|
case PIPE_CAPF_MAX_LINE_WIDTH:
|
||||||
|
case PIPE_CAPF_MAX_LINE_WIDTH_AA:
|
||||||
|
return screen->props.limits.lineWidthRange[1];
|
||||||
|
|
||||||
|
case PIPE_CAPF_MAX_POINT_WIDTH:
|
||||||
|
case PIPE_CAPF_MAX_POINT_WIDTH_AA:
|
||||||
|
return screen->props.limits.pointSizeRange[1];
|
||||||
|
|
||||||
|
case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
|
||||||
|
return screen->props.limits.maxSamplerAnisotropy;
|
||||||
|
|
||||||
|
case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
|
||||||
|
return screen->props.limits.maxSamplerLodBias;
|
||||||
|
|
||||||
|
case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:
|
||||||
|
case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:
|
||||||
|
case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:
|
||||||
|
return 0.0f; /* not implemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* should only get here on unhandled cases */
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
zink_get_shader_param(struct pipe_screen *pscreen,
|
||||||
|
enum pipe_shader_type shader,
|
||||||
|
enum pipe_shader_cap param)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pscreen);
|
||||||
|
|
||||||
|
switch (param) {
|
||||||
|
case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
|
||||||
|
case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
|
||||||
|
case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
|
||||||
|
case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
|
||||||
|
case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
|
||||||
|
if (shader == PIPE_SHADER_VERTEX ||
|
||||||
|
shader == PIPE_SHADER_FRAGMENT)
|
||||||
|
return INT_MAX;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_MAX_INPUTS:
|
||||||
|
switch (shader) {
|
||||||
|
case PIPE_SHADER_VERTEX:
|
||||||
|
return MIN2(screen->props.limits.maxVertexInputAttributes,
|
||||||
|
PIPE_MAX_SHADER_INPUTS);
|
||||||
|
case PIPE_SHADER_FRAGMENT:
|
||||||
|
return MIN2(screen->props.limits.maxFragmentInputComponents / 4,
|
||||||
|
PIPE_MAX_SHADER_INPUTS);
|
||||||
|
default:
|
||||||
|
return 0; /* unsupported stage */
|
||||||
|
}
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_MAX_OUTPUTS:
|
||||||
|
switch (shader) {
|
||||||
|
case PIPE_SHADER_VERTEX:
|
||||||
|
return MIN2(screen->props.limits.maxVertexOutputComponents / 4,
|
||||||
|
PIPE_MAX_SHADER_OUTPUTS);
|
||||||
|
case PIPE_SHADER_FRAGMENT:
|
||||||
|
return MIN2(screen->props.limits.maxColorAttachments,
|
||||||
|
PIPE_MAX_SHADER_OUTPUTS);
|
||||||
|
default:
|
||||||
|
return 0; /* unsupported stage */
|
||||||
|
}
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
|
||||||
|
/* this might be a bit simplistic... */
|
||||||
|
return MIN2(screen->props.limits.maxPerStageDescriptorSamplers,
|
||||||
|
PIPE_MAX_SAMPLERS);
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
|
||||||
|
return screen->props.limits.maxUniformBufferRange;
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
|
||||||
|
return screen->props.limits.maxPerStageDescriptorUniformBuffers;
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_MAX_TEMPS:
|
||||||
|
return INT_MAX;
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
|
||||||
|
case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
|
||||||
|
case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
|
||||||
|
case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
|
||||||
|
case PIPE_SHADER_CAP_SUBROUTINES:
|
||||||
|
case PIPE_SHADER_CAP_INTEGERS:
|
||||||
|
case PIPE_SHADER_CAP_INT64_ATOMICS:
|
||||||
|
case PIPE_SHADER_CAP_FP16:
|
||||||
|
return 0; /* not implemented */
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_PREFERRED_IR:
|
||||||
|
return PIPE_SHADER_IR_NIR;
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
|
||||||
|
return 0; /* not implemented */
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
|
||||||
|
return MIN2(screen->props.limits.maxPerStageDescriptorSampledImages,
|
||||||
|
PIPE_MAX_SHADER_SAMPLER_VIEWS);
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
|
||||||
|
case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
|
||||||
|
case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
|
||||||
|
return 0; /* not implemented */
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
|
||||||
|
return 0; /* no idea */
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
|
||||||
|
return 32; /* arbitrary */
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
|
||||||
|
/* TODO: this limitation is dumb, and will need some fixes in mesa */
|
||||||
|
return MIN2(screen->props.limits.maxPerStageDescriptorStorageBuffers, 8);
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_SUPPORTED_IRS:
|
||||||
|
return (1 << PIPE_SHADER_IR_NIR) | (1 << PIPE_SHADER_IR_TGSI);
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
|
||||||
|
return screen->props.limits.maxPerStageDescriptorStorageImages;
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
|
||||||
|
case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:
|
||||||
|
return 0; /* unsure */
|
||||||
|
|
||||||
|
case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:
|
||||||
|
case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
|
||||||
|
case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
|
||||||
|
case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
|
||||||
|
return 0; /* not implemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* should only get here on unhandled cases */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VkFormat formats[PIPE_FORMAT_COUNT] = {
|
||||||
|
#define MAP_FORMAT_NORM(FMT) \
|
||||||
|
[PIPE_FORMAT_ ## FMT ## _UNORM] = VK_FORMAT_ ## FMT ## _UNORM, \
|
||||||
|
[PIPE_FORMAT_ ## FMT ## _SNORM] = VK_FORMAT_ ## FMT ## _SNORM,
|
||||||
|
|
||||||
|
#define MAP_FORMAT_SCALED(FMT) \
|
||||||
|
[PIPE_FORMAT_ ## FMT ## _USCALED] = VK_FORMAT_ ## FMT ## _USCALED, \
|
||||||
|
[PIPE_FORMAT_ ## FMT ## _SSCALED] = VK_FORMAT_ ## FMT ## _SSCALED,
|
||||||
|
|
||||||
|
#define MAP_FORMAT_INT(FMT) \
|
||||||
|
[PIPE_FORMAT_ ## FMT ## _UINT] = VK_FORMAT_ ## FMT ## _UINT, \
|
||||||
|
[PIPE_FORMAT_ ## FMT ## _SINT] = VK_FORMAT_ ## FMT ## _SINT,
|
||||||
|
|
||||||
|
#define MAP_FORMAT_SRGB(FMT) \
|
||||||
|
[PIPE_FORMAT_ ## FMT ## _SRGB] = VK_FORMAT_ ## FMT ## _SRGB,
|
||||||
|
|
||||||
|
#define MAP_FORMAT_FLOAT(FMT) \
|
||||||
|
[PIPE_FORMAT_ ## FMT ## _FLOAT] = VK_FORMAT_ ## FMT ## _SFLOAT,
|
||||||
|
|
||||||
|
// one component
|
||||||
|
|
||||||
|
// 8-bits
|
||||||
|
MAP_FORMAT_NORM(R8)
|
||||||
|
MAP_FORMAT_SCALED(R8)
|
||||||
|
MAP_FORMAT_INT(R8)
|
||||||
|
// 16-bits
|
||||||
|
MAP_FORMAT_NORM(R16)
|
||||||
|
MAP_FORMAT_SCALED(R16)
|
||||||
|
MAP_FORMAT_INT(R16)
|
||||||
|
MAP_FORMAT_FLOAT(R16)
|
||||||
|
// 32-bits
|
||||||
|
MAP_FORMAT_INT(R32)
|
||||||
|
MAP_FORMAT_FLOAT(R32)
|
||||||
|
|
||||||
|
// two components
|
||||||
|
|
||||||
|
// 8-bits
|
||||||
|
MAP_FORMAT_NORM(R8G8)
|
||||||
|
MAP_FORMAT_SCALED(R8G8)
|
||||||
|
MAP_FORMAT_INT(R8G8)
|
||||||
|
// 16-bits
|
||||||
|
MAP_FORMAT_NORM(R16G16)
|
||||||
|
MAP_FORMAT_SCALED(R16G16)
|
||||||
|
MAP_FORMAT_INT(R16G16)
|
||||||
|
MAP_FORMAT_FLOAT(R16G16)
|
||||||
|
// 32-bits
|
||||||
|
MAP_FORMAT_INT(R32G32)
|
||||||
|
MAP_FORMAT_FLOAT(R32G32)
|
||||||
|
|
||||||
|
// three components
|
||||||
|
|
||||||
|
// 8-bits
|
||||||
|
MAP_FORMAT_NORM(R8G8B8)
|
||||||
|
MAP_FORMAT_SCALED(R8G8B8)
|
||||||
|
MAP_FORMAT_INT(R8G8B8)
|
||||||
|
MAP_FORMAT_SRGB(R8G8B8)
|
||||||
|
// 16-bits
|
||||||
|
MAP_FORMAT_NORM(R16G16B16)
|
||||||
|
MAP_FORMAT_SCALED(R16G16B16)
|
||||||
|
MAP_FORMAT_INT(R16G16B16)
|
||||||
|
MAP_FORMAT_FLOAT(R16G16B16)
|
||||||
|
// 32-bits
|
||||||
|
MAP_FORMAT_INT(R32G32B32)
|
||||||
|
MAP_FORMAT_FLOAT(R32G32B32)
|
||||||
|
|
||||||
|
// four components
|
||||||
|
|
||||||
|
// 8-bits
|
||||||
|
MAP_FORMAT_NORM(R8G8B8A8)
|
||||||
|
MAP_FORMAT_SCALED(R8G8B8A8)
|
||||||
|
MAP_FORMAT_INT(R8G8B8A8)
|
||||||
|
MAP_FORMAT_SRGB(R8G8B8A8)
|
||||||
|
[PIPE_FORMAT_B8G8R8A8_UNORM] = VK_FORMAT_B8G8R8A8_UNORM,
|
||||||
|
MAP_FORMAT_SRGB(B8G8R8A8)
|
||||||
|
[PIPE_FORMAT_A8B8G8R8_SRGB] = VK_FORMAT_A8B8G8R8_SRGB_PACK32,
|
||||||
|
// 16-bits
|
||||||
|
MAP_FORMAT_NORM(R16G16B16A16)
|
||||||
|
MAP_FORMAT_SCALED(R16G16B16A16)
|
||||||
|
MAP_FORMAT_INT(R16G16B16A16)
|
||||||
|
MAP_FORMAT_FLOAT(R16G16B16A16)
|
||||||
|
// 32-bits
|
||||||
|
MAP_FORMAT_INT(R32G32B32A32)
|
||||||
|
MAP_FORMAT_FLOAT(R32G32B32A32)
|
||||||
|
|
||||||
|
// other color formats
|
||||||
|
[PIPE_FORMAT_B5G6R5_UNORM] = VK_FORMAT_R5G6B5_UNORM_PACK16,
|
||||||
|
[PIPE_FORMAT_B5G5R5A1_UNORM] = VK_FORMAT_B5G5R5A1_UNORM_PACK16,
|
||||||
|
[PIPE_FORMAT_R11G11B10_FLOAT] = VK_FORMAT_B10G11R11_UFLOAT_PACK32,
|
||||||
|
[PIPE_FORMAT_R9G9B9E5_FLOAT] = VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
|
||||||
|
[PIPE_FORMAT_R10G10B10A2_UNORM] = VK_FORMAT_A2B10G10R10_UNORM_PACK32,
|
||||||
|
[PIPE_FORMAT_B10G10R10A2_UNORM] = VK_FORMAT_A2R10G10B10_UNORM_PACK32,
|
||||||
|
[PIPE_FORMAT_R10G10B10A2_UINT] = VK_FORMAT_A2B10G10R10_UINT_PACK32,
|
||||||
|
[PIPE_FORMAT_B10G10R10A2_UINT] = VK_FORMAT_A2R10G10B10_UINT_PACK32,
|
||||||
|
|
||||||
|
// depth/stencil formats
|
||||||
|
[PIPE_FORMAT_Z32_FLOAT] = VK_FORMAT_D32_SFLOAT,
|
||||||
|
[PIPE_FORMAT_Z32_FLOAT_S8X24_UINT] = VK_FORMAT_D32_SFLOAT_S8_UINT,
|
||||||
|
[PIPE_FORMAT_Z16_UNORM] = VK_FORMAT_D16_UNORM,
|
||||||
|
[PIPE_FORMAT_X8Z24_UNORM] = VK_FORMAT_X8_D24_UNORM_PACK32,
|
||||||
|
[PIPE_FORMAT_Z24_UNORM_S8_UINT] = VK_FORMAT_D24_UNORM_S8_UINT,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkFormat
|
||||||
|
zink_get_format(enum pipe_format format)
|
||||||
|
{
|
||||||
|
return formats[format];
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
zink_is_format_supported(struct pipe_screen *pscreen,
|
||||||
|
enum pipe_format format,
|
||||||
|
enum pipe_texture_target target,
|
||||||
|
unsigned sample_count,
|
||||||
|
unsigned storage_sample_count,
|
||||||
|
unsigned bind)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pscreen);
|
||||||
|
|
||||||
|
if (sample_count > 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
VkFormat vkformat = formats[format];
|
||||||
|
if (vkformat == VK_FORMAT_UNDEFINED)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
VkFormatProperties props;
|
||||||
|
vkGetPhysicalDeviceFormatProperties(screen->pdev, vkformat, &props);
|
||||||
|
|
||||||
|
if (target == PIPE_BUFFER) {
|
||||||
|
if (bind & PIPE_BIND_VERTEX_BUFFER &&
|
||||||
|
!(props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
/* all other targets are texture-targets */
|
||||||
|
if (bind & PIPE_BIND_RENDER_TARGET &&
|
||||||
|
!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (bind & PIPE_BIND_BLENDABLE &&
|
||||||
|
!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (bind & PIPE_BIND_SAMPLER_VIEW &&
|
||||||
|
!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (bind & PIPE_BIND_DEPTH_STENCIL &&
|
||||||
|
!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_destroy_screen(struct pipe_screen *pscreen)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pscreen);
|
||||||
|
slab_destroy_parent(&screen->transfer_pool);
|
||||||
|
FREE(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkInstance
|
||||||
|
create_instance()
|
||||||
|
{
|
||||||
|
VkApplicationInfo ai = {};
|
||||||
|
ai.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||||
|
|
||||||
|
char proc_name[128];
|
||||||
|
if (os_get_process_name(proc_name, ARRAY_SIZE(proc_name)))
|
||||||
|
ai.pApplicationName = proc_name;
|
||||||
|
else
|
||||||
|
ai.pApplicationName = "unknown";
|
||||||
|
|
||||||
|
ai.pEngineName = "mesa zink";
|
||||||
|
ai.apiVersion = VK_API_VERSION_1_0;
|
||||||
|
|
||||||
|
VkInstanceCreateInfo ici = {};
|
||||||
|
ici.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
|
ici.pApplicationInfo = &ai;
|
||||||
|
|
||||||
|
VkInstance instance = VK_NULL_HANDLE;
|
||||||
|
VkResult err = vkCreateInstance(&ici, NULL, &instance);
|
||||||
|
if (err != VK_SUCCESS)
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkPhysicalDevice
|
||||||
|
choose_pdev(const VkInstance instance)
|
||||||
|
{
|
||||||
|
uint32_t i, pdev_count;
|
||||||
|
VkPhysicalDevice *pdevs, pdev;
|
||||||
|
vkEnumeratePhysicalDevices(instance, &pdev_count, NULL);
|
||||||
|
assert(pdev_count > 0);
|
||||||
|
|
||||||
|
pdevs = malloc(sizeof(*pdevs) * pdev_count);
|
||||||
|
vkEnumeratePhysicalDevices(instance, &pdev_count, pdevs);
|
||||||
|
assert(pdev_count > 0);
|
||||||
|
|
||||||
|
pdev = pdevs[0];
|
||||||
|
for (i = 0; i < pdev_count; ++i) {
|
||||||
|
VkPhysicalDeviceProperties props;
|
||||||
|
vkGetPhysicalDeviceProperties(pdevs[i], &props);
|
||||||
|
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
|
||||||
|
pdev = pdevs[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(pdevs);
|
||||||
|
return pdev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
find_gfx_queue(const VkPhysicalDevice pdev)
|
||||||
|
{
|
||||||
|
uint32_t num_queues;
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(pdev, &num_queues, NULL);
|
||||||
|
assert(num_queues > 0);
|
||||||
|
|
||||||
|
VkQueueFamilyProperties *props = malloc(sizeof(*props) * num_queues);
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(pdev, &num_queues, props);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < num_queues; i++) {
|
||||||
|
if (props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||||
|
free(props);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_flush_frontbuffer(struct pipe_screen *pscreen,
|
||||||
|
struct pipe_resource *pres,
|
||||||
|
unsigned level, unsigned layer,
|
||||||
|
void *winsys_drawable_handle,
|
||||||
|
struct pipe_box *sub_box)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pscreen);
|
||||||
|
struct sw_winsys *winsys = screen->winsys;
|
||||||
|
struct zink_resource *res = zink_resource(pres);
|
||||||
|
|
||||||
|
void *map = winsys->displaytarget_map(winsys, res->dt, 0);
|
||||||
|
|
||||||
|
if (map) {
|
||||||
|
VkImageSubresource isr = {};
|
||||||
|
isr.aspectMask = res->aspect;
|
||||||
|
isr.mipLevel = level;
|
||||||
|
isr.arrayLayer = layer;
|
||||||
|
VkSubresourceLayout layout;
|
||||||
|
vkGetImageSubresourceLayout(screen->dev, res->image, &isr, &layout);
|
||||||
|
|
||||||
|
void *ptr;
|
||||||
|
VkResult result = vkMapMemory(screen->dev, res->mem, res->offset, res->size, 0, &ptr);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
debug_printf("failed to map memory for display\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < pres->height0; ++i) {
|
||||||
|
uint8_t *src = (uint8_t *)ptr + i * layout.rowPitch;
|
||||||
|
uint8_t *dst = (uint8_t *)map + i * res->dt_stride;
|
||||||
|
memcpy(dst, src, res->dt_stride);
|
||||||
|
}
|
||||||
|
vkUnmapMemory(screen->dev, res->mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
winsys->displaytarget_unmap(winsys, res->dt);
|
||||||
|
|
||||||
|
assert(res->dt);
|
||||||
|
if (res->dt)
|
||||||
|
winsys->displaytarget_display(winsys, res->dt, winsys_drawable_handle, sub_box);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pipe_screen *
|
||||||
|
zink_create_screen(struct sw_winsys *winsys)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = CALLOC_STRUCT(zink_screen);
|
||||||
|
if (!screen)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
zink_debug = debug_get_option_zink_debug();
|
||||||
|
|
||||||
|
screen->instance = create_instance();
|
||||||
|
screen->pdev = choose_pdev(screen->instance);
|
||||||
|
screen->gfx_queue = find_gfx_queue(screen->pdev);
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceProperties(screen->pdev, &screen->props);
|
||||||
|
vkGetPhysicalDeviceFeatures(screen->pdev, &screen->feats);
|
||||||
|
vkGetPhysicalDeviceMemoryProperties(screen->pdev, &screen->mem_props);
|
||||||
|
|
||||||
|
VkDeviceQueueCreateInfo qci = {};
|
||||||
|
float dummy = 0.0f;
|
||||||
|
qci.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
|
qci.queueFamilyIndex = screen->gfx_queue;
|
||||||
|
qci.queueCount = 1;
|
||||||
|
qci.pQueuePriorities = &dummy;
|
||||||
|
|
||||||
|
VkDeviceCreateInfo dci = {};
|
||||||
|
dci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
|
dci.queueCreateInfoCount = 1;
|
||||||
|
dci.pQueueCreateInfos = &qci;
|
||||||
|
dci.pEnabledFeatures = &screen->feats;
|
||||||
|
const char *extensions[] = {
|
||||||
|
VK_KHR_MAINTENANCE1_EXTENSION_NAME
|
||||||
|
};
|
||||||
|
dci.ppEnabledExtensionNames = extensions;
|
||||||
|
dci.enabledExtensionCount = ARRAY_SIZE(extensions);
|
||||||
|
if (vkCreateDevice(screen->pdev, &dci, NULL, &screen->dev) != VK_SUCCESS)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
screen->winsys = winsys;
|
||||||
|
|
||||||
|
screen->base.get_name = zink_get_name;
|
||||||
|
screen->base.get_vendor = zink_get_vendor;
|
||||||
|
screen->base.get_device_vendor = zink_get_device_vendor;
|
||||||
|
screen->base.get_param = zink_get_param;
|
||||||
|
screen->base.get_paramf = zink_get_paramf;
|
||||||
|
screen->base.get_shader_param = zink_get_shader_param;
|
||||||
|
screen->base.get_compiler_options = zink_get_compiler_options;
|
||||||
|
screen->base.is_format_supported = zink_is_format_supported;
|
||||||
|
screen->base.context_create = zink_context_create;
|
||||||
|
screen->base.flush_frontbuffer = zink_flush_frontbuffer;
|
||||||
|
screen->base.destroy = zink_destroy_screen;
|
||||||
|
|
||||||
|
zink_screen_resource_init(&screen->base);
|
||||||
|
zink_screen_fence_init(&screen->base);
|
||||||
|
|
||||||
|
slab_create_parent(&screen->transfer_pool, sizeof(struct zink_transfer), 16);
|
||||||
|
|
||||||
|
return &screen->base;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
FREE(screen);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
64
src/gallium/drivers/zink/zink_screen.h
Normal file
64
src/gallium/drivers/zink/zink_screen.h
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_SCREEN_H
|
||||||
|
#define ZINK_SCREEN_H
|
||||||
|
|
||||||
|
#include "pipe/p_screen.h"
|
||||||
|
#include "util/slab.h"
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
extern uint32_t zink_debug;
|
||||||
|
|
||||||
|
#define ZINK_DEBUG_NIR 0x1
|
||||||
|
#define ZINK_DEBUG_SPIRV 0x2
|
||||||
|
#define ZINK_DEBUG_TGSI 0x4
|
||||||
|
|
||||||
|
struct zink_screen {
|
||||||
|
struct pipe_screen base;
|
||||||
|
|
||||||
|
struct sw_winsys *winsys;
|
||||||
|
|
||||||
|
struct slab_parent_pool transfer_pool;
|
||||||
|
|
||||||
|
VkInstance instance;
|
||||||
|
VkPhysicalDevice pdev;
|
||||||
|
VkPhysicalDeviceProperties props;
|
||||||
|
VkPhysicalDeviceFeatures feats;
|
||||||
|
VkPhysicalDeviceMemoryProperties mem_props;
|
||||||
|
|
||||||
|
uint32_t gfx_queue;
|
||||||
|
VkDevice dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct zink_screen *
|
||||||
|
zink_screen(struct pipe_screen *pipe)
|
||||||
|
{
|
||||||
|
return (struct zink_screen *)pipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkFormat
|
||||||
|
zink_get_format(enum pipe_format format);
|
||||||
|
|
||||||
|
#endif
|
||||||
430
src/gallium/drivers/zink/zink_state.c
Normal file
430
src/gallium/drivers/zink/zink_state.c
Normal file
|
|
@ -0,0 +1,430 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zink_state.h"
|
||||||
|
|
||||||
|
#include "zink_context.h"
|
||||||
|
#include "zink_screen.h"
|
||||||
|
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
static void *
|
||||||
|
zink_create_vertex_elements_state(struct pipe_context *pctx,
|
||||||
|
unsigned num_elements,
|
||||||
|
const struct pipe_vertex_element *elements)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
struct zink_vertex_elements_state *ves = CALLOC_STRUCT(zink_vertex_elements_state);
|
||||||
|
if (!ves)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int buffer_map[PIPE_MAX_ATTRIBS];
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(buffer_map); ++i)
|
||||||
|
buffer_map[i] = -1;
|
||||||
|
|
||||||
|
int num_bindings = 0;
|
||||||
|
for (i = 0; i < num_elements; ++i) {
|
||||||
|
const struct pipe_vertex_element *elem = elements + i;
|
||||||
|
assert(!elem->instance_divisor);
|
||||||
|
|
||||||
|
int binding = elem->vertex_buffer_index;
|
||||||
|
if (buffer_map[binding] < 0) {
|
||||||
|
ves->binding_map[num_bindings] = binding;
|
||||||
|
buffer_map[binding] = num_bindings++;
|
||||||
|
}
|
||||||
|
binding = buffer_map[binding];
|
||||||
|
|
||||||
|
|
||||||
|
ves->bindings[binding].binding = binding;
|
||||||
|
ves->bindings[binding].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
|
||||||
|
ves->attribs[i].binding = binding;
|
||||||
|
ves->attribs[i].location = i; // TODO: unsure
|
||||||
|
ves->attribs[i].format = zink_get_format(elem->src_format);
|
||||||
|
assert(ves->attribs[i].format != VK_FORMAT_UNDEFINED);
|
||||||
|
ves->attribs[i].offset = elem->src_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
ves->num_bindings = num_bindings;
|
||||||
|
ves->num_attribs = num_elements;
|
||||||
|
return ves;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_bind_vertex_elements_state(struct pipe_context *pctx,
|
||||||
|
void *cso)
|
||||||
|
{
|
||||||
|
struct zink_gfx_pipeline_state *state = &zink_context(pctx)->gfx_pipeline_state;
|
||||||
|
state->element_state = cso;
|
||||||
|
if (cso) {
|
||||||
|
struct zink_vertex_elements_state *ves = cso;
|
||||||
|
for (int i = 0; i < ves->num_bindings; ++i) {
|
||||||
|
state->bindings[i].binding = ves->bindings[i].binding;
|
||||||
|
state->bindings[i].inputRate = ves->bindings[i].inputRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_delete_vertex_elements_state(struct pipe_context *pctx,
|
||||||
|
void *ves)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkBlendFactor
|
||||||
|
blend_factor(enum pipe_blendfactor factor)
|
||||||
|
{
|
||||||
|
switch (factor) {
|
||||||
|
case PIPE_BLENDFACTOR_ONE: return VK_BLEND_FACTOR_ONE;
|
||||||
|
case PIPE_BLENDFACTOR_SRC_COLOR: return VK_BLEND_FACTOR_SRC_COLOR;
|
||||||
|
case PIPE_BLENDFACTOR_SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA;
|
||||||
|
case PIPE_BLENDFACTOR_DST_ALPHA: return VK_BLEND_FACTOR_DST_ALPHA;
|
||||||
|
case PIPE_BLENDFACTOR_DST_COLOR: return VK_BLEND_FACTOR_DST_COLOR;
|
||||||
|
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
|
||||||
|
return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
|
||||||
|
case PIPE_BLENDFACTOR_CONST_COLOR: return VK_BLEND_FACTOR_CONSTANT_COLOR;
|
||||||
|
case PIPE_BLENDFACTOR_CONST_ALPHA: return VK_BLEND_FACTOR_CONSTANT_ALPHA;
|
||||||
|
case PIPE_BLENDFACTOR_SRC1_COLOR: return VK_BLEND_FACTOR_SRC1_COLOR;
|
||||||
|
case PIPE_BLENDFACTOR_SRC1_ALPHA: return VK_BLEND_FACTOR_SRC1_ALPHA;
|
||||||
|
|
||||||
|
case PIPE_BLENDFACTOR_ZERO: return VK_BLEND_FACTOR_ZERO;
|
||||||
|
|
||||||
|
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
|
||||||
|
return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
|
||||||
|
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
|
||||||
|
return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||||
|
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
|
||||||
|
return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
|
||||||
|
case PIPE_BLENDFACTOR_INV_DST_COLOR:
|
||||||
|
return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
|
||||||
|
|
||||||
|
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
|
||||||
|
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
|
||||||
|
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
|
||||||
|
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
|
||||||
|
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
|
||||||
|
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
|
||||||
|
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
|
||||||
|
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
|
||||||
|
}
|
||||||
|
unreachable("unexpected blend factor");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
need_blend_constants(enum pipe_blendfactor factor)
|
||||||
|
{
|
||||||
|
switch (factor) {
|
||||||
|
case PIPE_BLENDFACTOR_CONST_COLOR:
|
||||||
|
case PIPE_BLENDFACTOR_CONST_ALPHA:
|
||||||
|
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
|
||||||
|
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkBlendOp
|
||||||
|
blend_op(enum pipe_blend_func func)
|
||||||
|
{
|
||||||
|
switch (func) {
|
||||||
|
case PIPE_BLEND_ADD: return VK_BLEND_OP_ADD;
|
||||||
|
case PIPE_BLEND_SUBTRACT: return VK_BLEND_OP_SUBTRACT;
|
||||||
|
case PIPE_BLEND_REVERSE_SUBTRACT: return VK_BLEND_OP_REVERSE_SUBTRACT;
|
||||||
|
case PIPE_BLEND_MIN: return VK_BLEND_OP_MIN;
|
||||||
|
case PIPE_BLEND_MAX: return VK_BLEND_OP_MAX;
|
||||||
|
}
|
||||||
|
unreachable("unexpected blend function");
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkLogicOp
|
||||||
|
logic_op(enum pipe_logicop func)
|
||||||
|
{
|
||||||
|
switch (func) {
|
||||||
|
case PIPE_LOGICOP_CLEAR: return VK_LOGIC_OP_CLEAR;
|
||||||
|
case PIPE_LOGICOP_NOR: return VK_LOGIC_OP_NOR;
|
||||||
|
case PIPE_LOGICOP_AND_INVERTED: return VK_LOGIC_OP_AND_INVERTED;
|
||||||
|
case PIPE_LOGICOP_COPY_INVERTED: return VK_LOGIC_OP_COPY_INVERTED;
|
||||||
|
case PIPE_LOGICOP_AND_REVERSE: return VK_LOGIC_OP_AND_REVERSE;
|
||||||
|
case PIPE_LOGICOP_INVERT: return VK_LOGIC_OP_INVERT;
|
||||||
|
case PIPE_LOGICOP_XOR: return VK_LOGIC_OP_XOR;
|
||||||
|
case PIPE_LOGICOP_NAND: return VK_LOGIC_OP_NAND;
|
||||||
|
case PIPE_LOGICOP_AND: return VK_LOGIC_OP_AND;
|
||||||
|
case PIPE_LOGICOP_EQUIV: return VK_LOGIC_OP_EQUIVALENT;
|
||||||
|
case PIPE_LOGICOP_NOOP: return VK_LOGIC_OP_NO_OP;
|
||||||
|
case PIPE_LOGICOP_OR_INVERTED: return VK_LOGIC_OP_OR_INVERTED;
|
||||||
|
case PIPE_LOGICOP_COPY: return VK_LOGIC_OP_COPY;
|
||||||
|
case PIPE_LOGICOP_OR_REVERSE: return VK_LOGIC_OP_OR_REVERSE;
|
||||||
|
case PIPE_LOGICOP_OR: return VK_LOGIC_OP_OR;
|
||||||
|
case PIPE_LOGICOP_SET: return VK_LOGIC_OP_SET;
|
||||||
|
}
|
||||||
|
unreachable("unexpected logicop function");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
zink_create_blend_state(struct pipe_context *pctx,
|
||||||
|
const struct pipe_blend_state *blend_state)
|
||||||
|
{
|
||||||
|
struct zink_blend_state *cso = CALLOC_STRUCT(zink_blend_state);
|
||||||
|
if (!cso)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (blend_state->logicop_enable) {
|
||||||
|
cso->logicop_enable = VK_TRUE;
|
||||||
|
cso->logicop_func = logic_op(blend_state->logicop_func);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: figure out what to do with dither (nothing is probably "OK" for now,
|
||||||
|
* as dithering is undefined in GL
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO: these are multisampling-state, and should be set there instead of
|
||||||
|
* here, as that's closer tied to the update-frequency
|
||||||
|
*/
|
||||||
|
cso->alpha_to_coverage = blend_state->alpha_to_coverage;
|
||||||
|
cso->alpha_to_one = blend_state->alpha_to_one;
|
||||||
|
|
||||||
|
cso->need_blend_constants = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < PIPE_MAX_COLOR_BUFS; ++i) {
|
||||||
|
const struct pipe_rt_blend_state *rt = blend_state->rt;
|
||||||
|
if (blend_state->independent_blend_enable)
|
||||||
|
rt = blend_state->rt + i;
|
||||||
|
|
||||||
|
VkPipelineColorBlendAttachmentState att = { };
|
||||||
|
|
||||||
|
if (rt->blend_enable) {
|
||||||
|
att.blendEnable = VK_TRUE;
|
||||||
|
att.srcColorBlendFactor = blend_factor(rt->rgb_src_factor);
|
||||||
|
att.dstColorBlendFactor = blend_factor(rt->rgb_dst_factor);
|
||||||
|
att.colorBlendOp = blend_op(rt->rgb_func);
|
||||||
|
att.srcAlphaBlendFactor = blend_factor(rt->alpha_src_factor);
|
||||||
|
att.dstAlphaBlendFactor = blend_factor(rt->alpha_dst_factor);
|
||||||
|
att.alphaBlendOp = blend_op(rt->alpha_func);
|
||||||
|
|
||||||
|
if (need_blend_constants(rt->rgb_src_factor) ||
|
||||||
|
need_blend_constants(rt->rgb_dst_factor) ||
|
||||||
|
need_blend_constants(rt->alpha_src_factor) ||
|
||||||
|
need_blend_constants(rt->alpha_dst_factor))
|
||||||
|
cso->need_blend_constants = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rt->colormask & PIPE_MASK_R)
|
||||||
|
att.colorWriteMask |= VK_COLOR_COMPONENT_R_BIT;
|
||||||
|
if (rt->colormask & PIPE_MASK_G)
|
||||||
|
att.colorWriteMask |= VK_COLOR_COMPONENT_G_BIT;
|
||||||
|
if (rt->colormask & PIPE_MASK_B)
|
||||||
|
att.colorWriteMask |= VK_COLOR_COMPONENT_B_BIT;
|
||||||
|
if (rt->colormask & PIPE_MASK_A)
|
||||||
|
att.colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;
|
||||||
|
|
||||||
|
cso->attachments[i] = att;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cso;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_bind_blend_state(struct pipe_context *pctx, void *cso)
|
||||||
|
{
|
||||||
|
zink_context(pctx)->gfx_pipeline_state.blend_state = cso;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_delete_blend_state(struct pipe_context *pctx, void *blend_state)
|
||||||
|
{
|
||||||
|
FREE(blend_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkCompareOp
|
||||||
|
compare_op(enum pipe_compare_func func)
|
||||||
|
{
|
||||||
|
switch (func) {
|
||||||
|
case PIPE_FUNC_NEVER: return VK_COMPARE_OP_NEVER;
|
||||||
|
case PIPE_FUNC_LESS: return VK_COMPARE_OP_LESS;
|
||||||
|
case PIPE_FUNC_EQUAL: return VK_COMPARE_OP_EQUAL;
|
||||||
|
case PIPE_FUNC_LEQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL;
|
||||||
|
case PIPE_FUNC_GREATER: return VK_COMPARE_OP_GREATER;
|
||||||
|
case PIPE_FUNC_NOTEQUAL: return VK_COMPARE_OP_NOT_EQUAL;
|
||||||
|
case PIPE_FUNC_GEQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL;
|
||||||
|
case PIPE_FUNC_ALWAYS: return VK_COMPARE_OP_ALWAYS;
|
||||||
|
}
|
||||||
|
unreachable("unexpected func");
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkStencilOp
|
||||||
|
stencil_op(enum pipe_stencil_op op)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case PIPE_STENCIL_OP_KEEP: return VK_STENCIL_OP_KEEP;
|
||||||
|
case PIPE_STENCIL_OP_ZERO: return VK_STENCIL_OP_ZERO;
|
||||||
|
case PIPE_STENCIL_OP_REPLACE: return VK_STENCIL_OP_REPLACE;
|
||||||
|
case PIPE_STENCIL_OP_INCR: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
|
||||||
|
case PIPE_STENCIL_OP_DECR: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
|
||||||
|
case PIPE_STENCIL_OP_INCR_WRAP: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
|
||||||
|
case PIPE_STENCIL_OP_DECR_WRAP: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
|
||||||
|
case PIPE_STENCIL_OP_INVERT: return VK_STENCIL_OP_INVERT;
|
||||||
|
}
|
||||||
|
unreachable("unexpected op");
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkStencilOpState
|
||||||
|
stencil_op_state(const struct pipe_stencil_state *src)
|
||||||
|
{
|
||||||
|
VkStencilOpState ret;
|
||||||
|
ret.failOp = stencil_op(src->fail_op);
|
||||||
|
ret.passOp = stencil_op(src->zpass_op);
|
||||||
|
ret.depthFailOp = stencil_op(src->zfail_op);
|
||||||
|
ret.compareOp = compare_op(src->func);
|
||||||
|
ret.compareMask = src->valuemask;
|
||||||
|
ret.writeMask = src->writemask;
|
||||||
|
ret.reference = 0; // not used: we'll use a dynamic state for this
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
zink_create_depth_stencil_alpha_state(struct pipe_context *pctx,
|
||||||
|
const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha)
|
||||||
|
{
|
||||||
|
struct zink_depth_stencil_alpha_state *cso = CALLOC_STRUCT(zink_depth_stencil_alpha_state);
|
||||||
|
if (!cso)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (depth_stencil_alpha->depth.enabled) {
|
||||||
|
cso->depth_test = VK_TRUE;
|
||||||
|
cso->depth_compare_op = compare_op(depth_stencil_alpha->depth.func);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth_stencil_alpha->depth.bounds_test) {
|
||||||
|
cso->depth_bounds_test = VK_TRUE;
|
||||||
|
cso->min_depth_bounds = depth_stencil_alpha->depth.bounds_min;
|
||||||
|
cso->max_depth_bounds = depth_stencil_alpha->depth.bounds_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth_stencil_alpha->stencil[0].enabled) {
|
||||||
|
cso->stencil_test = VK_TRUE;
|
||||||
|
cso->stencil_front = stencil_op_state(depth_stencil_alpha->stencil);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth_stencil_alpha->stencil[0].enabled)
|
||||||
|
cso->stencil_back = stencil_op_state(depth_stencil_alpha->stencil + 1);
|
||||||
|
else
|
||||||
|
cso->stencil_back = cso->stencil_front;
|
||||||
|
|
||||||
|
cso->depth_write = depth_stencil_alpha->depth.writemask;
|
||||||
|
|
||||||
|
return cso;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *cso)
|
||||||
|
{
|
||||||
|
zink_context(pctx)->gfx_pipeline_state.depth_stencil_alpha_state = cso;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_delete_depth_stencil_alpha_state(struct pipe_context *pctx,
|
||||||
|
void *depth_stencil_alpha)
|
||||||
|
{
|
||||||
|
FREE(depth_stencil_alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float
|
||||||
|
round_to_granularity(float value, float granularity)
|
||||||
|
{
|
||||||
|
return (float)(round(value / granularity) * granularity);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
zink_create_rasterizer_state(struct pipe_context *pctx,
|
||||||
|
const struct pipe_rasterizer_state *rs_state)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pctx->screen);
|
||||||
|
|
||||||
|
struct zink_rasterizer_state *state = CALLOC_STRUCT(zink_rasterizer_state);
|
||||||
|
if (!state)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
state->base = *rs_state;
|
||||||
|
|
||||||
|
assert(rs_state->depth_clip_far == rs_state->depth_clip_near);
|
||||||
|
state->depth_clamp = rs_state->depth_clip_near == 0;
|
||||||
|
state->rasterizer_discard = rs_state->rasterizer_discard;
|
||||||
|
|
||||||
|
assert(rs_state->fill_front <= PIPE_POLYGON_MODE_POINT);
|
||||||
|
if (rs_state->fill_back != rs_state->fill_front)
|
||||||
|
debug_printf("BUG: vulkan doesn't support different front and back fill modes\n");
|
||||||
|
state->polygon_mode = (VkPolygonMode)rs_state->fill_front; // same values
|
||||||
|
state->cull_mode = (VkCullModeFlags)rs_state->cull_face; // same bits
|
||||||
|
|
||||||
|
state->front_face = rs_state->front_ccw ? VK_FRONT_FACE_COUNTER_CLOCKWISE
|
||||||
|
: VK_FRONT_FACE_CLOCKWISE;
|
||||||
|
|
||||||
|
state->offset_point = rs_state->offset_point;
|
||||||
|
state->offset_line = rs_state->offset_line;
|
||||||
|
state->offset_tri = rs_state->offset_tri;
|
||||||
|
state->offset_units = rs_state->offset_units;
|
||||||
|
state->offset_clamp = rs_state->offset_clamp;
|
||||||
|
state->offset_scale = rs_state->offset_scale;
|
||||||
|
|
||||||
|
state->line_width = round_to_granularity(rs_state->line_width,
|
||||||
|
screen->props.limits.lineWidthGranularity);
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
|
||||||
|
{
|
||||||
|
zink_context(pctx)->gfx_pipeline_state.rast_state = cso;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_delete_rasterizer_state(struct pipe_context *pctx, void *rs_state)
|
||||||
|
{
|
||||||
|
FREE(rs_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_context_state_init(struct pipe_context *pctx)
|
||||||
|
{
|
||||||
|
pctx->create_vertex_elements_state = zink_create_vertex_elements_state;
|
||||||
|
pctx->bind_vertex_elements_state = zink_bind_vertex_elements_state;
|
||||||
|
pctx->delete_vertex_elements_state = zink_delete_vertex_elements_state;
|
||||||
|
|
||||||
|
pctx->create_blend_state = zink_create_blend_state;
|
||||||
|
pctx->bind_blend_state = zink_bind_blend_state;
|
||||||
|
pctx->delete_blend_state = zink_delete_blend_state;
|
||||||
|
|
||||||
|
pctx->create_depth_stencil_alpha_state = zink_create_depth_stencil_alpha_state;
|
||||||
|
pctx->bind_depth_stencil_alpha_state = zink_bind_depth_stencil_alpha_state;
|
||||||
|
pctx->delete_depth_stencil_alpha_state = zink_delete_depth_stencil_alpha_state;
|
||||||
|
|
||||||
|
pctx->create_rasterizer_state = zink_create_rasterizer_state;
|
||||||
|
pctx->bind_rasterizer_state = zink_bind_rasterizer_state;
|
||||||
|
pctx->delete_rasterizer_state = zink_delete_rasterizer_state;
|
||||||
|
}
|
||||||
84
src/gallium/drivers/zink/zink_state.h
Normal file
84
src/gallium/drivers/zink/zink_state.h
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_STATE_H
|
||||||
|
#define ZINK_STATE_H
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
#include "pipe/p_state.h"
|
||||||
|
|
||||||
|
struct zink_vertex_elements_state {
|
||||||
|
struct {
|
||||||
|
uint32_t binding;
|
||||||
|
VkVertexInputRate inputRate;
|
||||||
|
} bindings[PIPE_MAX_ATTRIBS];
|
||||||
|
VkVertexInputAttributeDescription attribs[PIPE_MAX_ATTRIBS];
|
||||||
|
uint32_t num_bindings, num_attribs;
|
||||||
|
uint8_t binding_map[PIPE_MAX_ATTRIBS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zink_rasterizer_state {
|
||||||
|
struct pipe_rasterizer_state base;
|
||||||
|
|
||||||
|
VkBool32 depth_clamp;
|
||||||
|
VkBool32 rasterizer_discard;
|
||||||
|
VkFrontFace front_face;
|
||||||
|
VkPolygonMode polygon_mode;
|
||||||
|
VkCullModeFlags cull_mode;
|
||||||
|
|
||||||
|
bool offset_point, offset_line, offset_tri;
|
||||||
|
float offset_units, offset_clamp, offset_scale;
|
||||||
|
float line_width;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zink_blend_state {
|
||||||
|
VkPipelineColorBlendAttachmentState attachments[PIPE_MAX_COLOR_BUFS];
|
||||||
|
|
||||||
|
VkBool32 logicop_enable;
|
||||||
|
VkLogicOp logicop_func;
|
||||||
|
|
||||||
|
VkBool32 alpha_to_coverage;
|
||||||
|
VkBool32 alpha_to_one;
|
||||||
|
|
||||||
|
bool need_blend_constants;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zink_depth_stencil_alpha_state {
|
||||||
|
VkBool32 depth_test;
|
||||||
|
VkCompareOp depth_compare_op;
|
||||||
|
|
||||||
|
VkBool32 depth_bounds_test;
|
||||||
|
float min_depth_bounds, max_depth_bounds;
|
||||||
|
|
||||||
|
VkBool32 stencil_test;
|
||||||
|
VkStencilOpState stencil_front;
|
||||||
|
VkStencilOpState stencil_back;
|
||||||
|
|
||||||
|
VkBool32 depth_write;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_context_state_init(struct pipe_context *pctx);
|
||||||
|
|
||||||
|
#endif
|
||||||
138
src/gallium/drivers/zink/zink_surface.c
Normal file
138
src/gallium/drivers/zink/zink_surface.c
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zink_context.h"
|
||||||
|
#include "zink_resource.h"
|
||||||
|
#include "zink_screen.h"
|
||||||
|
#include "zink_surface.h"
|
||||||
|
|
||||||
|
#include "util/u_format.h"
|
||||||
|
#include "util/u_inlines.h"
|
||||||
|
#include "util/u_memory.h"
|
||||||
|
|
||||||
|
static struct pipe_surface *
|
||||||
|
zink_create_surface(struct pipe_context *pctx,
|
||||||
|
struct pipe_resource *pres,
|
||||||
|
const struct pipe_surface *templ)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pctx->screen);
|
||||||
|
unsigned int level = templ->u.tex.level;
|
||||||
|
|
||||||
|
struct zink_surface *surface = CALLOC_STRUCT(zink_surface);
|
||||||
|
if (!surface)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pipe_resource_reference(&surface->base.texture, pres);
|
||||||
|
pipe_reference_init(&surface->base.reference, 1);
|
||||||
|
surface->base.context = pctx;
|
||||||
|
surface->base.format = templ->format;
|
||||||
|
surface->base.width = u_minify(pres->width0, level);
|
||||||
|
surface->base.height = u_minify(pres->height0, level);
|
||||||
|
surface->base.u.tex.level = level;
|
||||||
|
surface->base.u.tex.first_layer = templ->u.tex.first_layer;
|
||||||
|
surface->base.u.tex.last_layer = templ->u.tex.last_layer;
|
||||||
|
|
||||||
|
struct zink_resource *res = zink_resource(pres);
|
||||||
|
|
||||||
|
VkImageViewCreateInfo ivci = {};
|
||||||
|
ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
ivci.image = res->image;
|
||||||
|
|
||||||
|
switch (pres->target) {
|
||||||
|
case PIPE_TEXTURE_1D:
|
||||||
|
ivci.viewType = VK_IMAGE_VIEW_TYPE_1D;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIPE_TEXTURE_1D_ARRAY:
|
||||||
|
ivci.viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIPE_TEXTURE_2D:
|
||||||
|
case PIPE_TEXTURE_RECT:
|
||||||
|
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIPE_TEXTURE_2D_ARRAY:
|
||||||
|
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIPE_TEXTURE_CUBE:
|
||||||
|
ivci.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIPE_TEXTURE_CUBE_ARRAY:
|
||||||
|
ivci.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIPE_TEXTURE_3D:
|
||||||
|
ivci.viewType = VK_IMAGE_VIEW_TYPE_3D;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
unreachable("unsupported target");
|
||||||
|
}
|
||||||
|
|
||||||
|
ivci.format = zink_get_format(templ->format);
|
||||||
|
|
||||||
|
// TODO: format swizzles
|
||||||
|
ivci.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||||
|
ivci.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||||
|
ivci.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||||
|
ivci.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||||
|
|
||||||
|
ivci.subresourceRange.aspectMask = res->aspect;
|
||||||
|
ivci.subresourceRange.baseMipLevel = templ->u.tex.level;
|
||||||
|
ivci.subresourceRange.levelCount = 1;
|
||||||
|
ivci.subresourceRange.baseArrayLayer = templ->u.tex.first_layer;
|
||||||
|
ivci.subresourceRange.layerCount = 1 + templ->u.tex.last_layer - templ->u.tex.first_layer;
|
||||||
|
|
||||||
|
if (pres->target == PIPE_TEXTURE_CUBE ||
|
||||||
|
pres->target == PIPE_TEXTURE_CUBE_ARRAY)
|
||||||
|
ivci.subresourceRange.layerCount *= 6;
|
||||||
|
|
||||||
|
if (vkCreateImageView(screen->dev, &ivci, NULL,
|
||||||
|
&surface->image_view) != VK_SUCCESS) {
|
||||||
|
FREE(surface);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &surface->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zink_surface_destroy(struct pipe_context *pctx,
|
||||||
|
struct pipe_surface *psurface)
|
||||||
|
{
|
||||||
|
struct zink_screen *screen = zink_screen(pctx->screen);
|
||||||
|
struct zink_surface *surface = zink_surface(psurface);
|
||||||
|
pipe_resource_reference(&psurface->texture, NULL);
|
||||||
|
vkDestroyImageView(screen->dev, surface->image_view, NULL);
|
||||||
|
FREE(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_context_surface_init(struct pipe_context *context)
|
||||||
|
{
|
||||||
|
context->create_surface = zink_create_surface;
|
||||||
|
context->surface_destroy = zink_surface_destroy;
|
||||||
|
}
|
||||||
47
src/gallium/drivers/zink/zink_surface.h
Normal file
47
src/gallium/drivers/zink/zink_surface.h
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZINK_SURFACE_H
|
||||||
|
#define ZINK_SURFACE_H
|
||||||
|
|
||||||
|
#include "pipe/p_state.h"
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
struct pipe_context;
|
||||||
|
|
||||||
|
struct zink_surface {
|
||||||
|
struct pipe_surface base;
|
||||||
|
VkImageView image_view;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct zink_surface *
|
||||||
|
zink_surface(struct pipe_surface *pipe)
|
||||||
|
{
|
||||||
|
return (struct zink_surface *)pipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zink_context_surface_init(struct pipe_context *context);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -156,6 +156,13 @@ if with_gallium_lima
|
||||||
else
|
else
|
||||||
driver_lima = declare_dependency()
|
driver_lima = declare_dependency()
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if with_gallium_zink
|
||||||
|
subdir('drivers/zink')
|
||||||
|
else
|
||||||
|
driver_zink = declare_dependency()
|
||||||
|
endif
|
||||||
|
|
||||||
if with_gallium_opencl
|
if with_gallium_opencl
|
||||||
# TODO: this isn't really clover specific, but ATM clover is the only
|
# TODO: this isn't really clover specific, but ATM clover is the only
|
||||||
# consumer
|
# consumer
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ libgallium_dri = shared_library(
|
||||||
driver_swrast, driver_r300, driver_r600, driver_radeonsi, driver_nouveau,
|
driver_swrast, driver_r300, driver_r600, driver_radeonsi, driver_nouveau,
|
||||||
driver_kmsro, driver_v3d, driver_vc4, driver_freedreno, driver_etnaviv,
|
driver_kmsro, driver_v3d, driver_vc4, driver_freedreno, driver_etnaviv,
|
||||||
driver_tegra, driver_i915, driver_svga, driver_virgl,
|
driver_tegra, driver_i915, driver_svga, driver_virgl,
|
||||||
driver_swr, driver_panfrost, driver_iris, driver_lima
|
driver_swr, driver_panfrost, driver_iris, driver_lima, driver_zink
|
||||||
],
|
],
|
||||||
# Will be deleted during installation, see install_megadrivers.py
|
# Will be deleted during installation, see install_megadrivers.py
|
||||||
install : true,
|
install : true,
|
||||||
|
|
@ -100,7 +100,8 @@ foreach d : [[with_gallium_kmsro, [
|
||||||
[with_gallium_r600, 'r600_dri.so'],
|
[with_gallium_r600, 'r600_dri.so'],
|
||||||
[with_gallium_svga, 'vmwgfx_dri.so'],
|
[with_gallium_svga, 'vmwgfx_dri.so'],
|
||||||
[with_gallium_virgl, 'virtio_gpu_dri.so'],
|
[with_gallium_virgl, 'virtio_gpu_dri.so'],
|
||||||
[with_gallium_lima, 'lima_dri.so']]
|
[with_gallium_lima, 'lima_dri.so'],
|
||||||
|
[with_gallium_zink, 'zink_dri.so']]
|
||||||
if d[0]
|
if d[0]
|
||||||
gallium_dri_drivers += d[1]
|
gallium_dri_drivers += d[1]
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue