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_swr = gallium_drivers.contains('swr')
|
||||
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')
|
||||
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')
|
||||
endif
|
||||
|
||||
if with_gallium_zink
|
||||
dep_vulkan = dependency('vulkan')
|
||||
endif
|
||||
|
||||
_xvmc = get_option('gallium-xvmc')
|
||||
if not system_has_kms_drm
|
||||
if _xvmc == 'true'
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ option(
|
|||
choices : [
|
||||
'', 'auto', 'kmsro', 'radeonsi', 'r300', 'r600', 'nouveau', 'freedreno',
|
||||
'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'
|
||||
)
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@ sw_screen_create_named(struct sw_winsys *winsys, const char *driver)
|
|||
screen = swr_create_screen(winsys);
|
||||
#endif
|
||||
|
||||
#if defined(GALLIUM_ZINK)
|
||||
if (screen == NULL && strcmp(driver, "zink") == 0)
|
||||
screen = zink_create_screen(winsys);
|
||||
#endif
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
|
|
@ -71,6 +76,8 @@ sw_screen_create(struct sw_winsys *winsys)
|
|||
default_driver = "softpipe";
|
||||
#elif defined(GALLIUM_SWR)
|
||||
default_driver = "swr";
|
||||
#elif defined(GALLIUM_ZINK)
|
||||
default_driver = "zink";
|
||||
#else
|
||||
default_driver = "";
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@
|
|||
* llvmpipe, softpipe, swr.
|
||||
*/
|
||||
|
||||
#ifdef GALLIUM_ZINK
|
||||
#include "zink/zink_public.h"
|
||||
#endif
|
||||
|
||||
#ifdef GALLIUM_SOFTPIPE
|
||||
#include "softpipe/sp_public.h"
|
||||
#endif
|
||||
|
|
@ -57,6 +61,11 @@ sw_screen_create_named(struct sw_winsys *winsys, const char *driver)
|
|||
screen = swr_create_screen(winsys);
|
||||
#endif
|
||||
|
||||
#if defined(GALLIUM_ZINK)
|
||||
if (screen == NULL && strcmp(driver, "zink") == 0)
|
||||
screen = zink_create_screen(winsys);
|
||||
#endif
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
|
|
@ -73,6 +82,8 @@ sw_screen_create(struct sw_winsys *winsys)
|
|||
default_driver = "softpipe";
|
||||
#elif defined(GALLIUM_SWR)
|
||||
default_driver = "swr";
|
||||
#elif defined(GALLIUM_SWR)
|
||||
default_driver = "zink";
|
||||
#else
|
||||
default_driver = "";
|
||||
#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
|
||||
driver_lima = declare_dependency()
|
||||
endif
|
||||
|
||||
if with_gallium_zink
|
||||
subdir('drivers/zink')
|
||||
else
|
||||
driver_zink = declare_dependency()
|
||||
endif
|
||||
|
||||
if with_gallium_opencl
|
||||
# TODO: this isn't really clover specific, but ATM clover is the only
|
||||
# consumer
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ libgallium_dri = shared_library(
|
|||
driver_swrast, driver_r300, driver_r600, driver_radeonsi, driver_nouveau,
|
||||
driver_kmsro, driver_v3d, driver_vc4, driver_freedreno, driver_etnaviv,
|
||||
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
|
||||
install : true,
|
||||
|
|
@ -100,7 +100,8 @@ foreach d : [[with_gallium_kmsro, [
|
|||
[with_gallium_r600, 'r600_dri.so'],
|
||||
[with_gallium_svga, 'vmwgfx_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]
|
||||
gallium_dri_drivers += d[1]
|
||||
endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue