=?UTF-8?Q?J=C3=B3zef=20Kucia=20?=: vkd3d-shader: Add basic support for transform feedback.
Alexandre Julliard
julliard at winehq.org
Mon Jan 14 16:21:23 CST 2019
Module: vkd3d
Branch: master
Commit: 3d80b3f4bd84a190c6db6ca40790e17427b1619a
URL: https://source.winehq.org/git/vkd3d.git/?a=commit;h=3d80b3f4bd84a190c6db6ca40790e17427b1619a
Author: Józef Kucia <jkucia at codeweavers.com>
Date: Mon Jan 14 17:05:43 2019 +0100
vkd3d-shader: Add basic support for transform feedback.
Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
include/vkd3d_shader.h | 24 +++++++++++++
libs/vkd3d-shader/spirv.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 115 insertions(+)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h
index 946defb..2ac8e0f 100644
--- a/include/vkd3d_shader.h
+++ b/include/vkd3d_shader.h
@@ -20,6 +20,7 @@
#define __VKD3D_SHADER_H
#include <stdbool.h>
+#include <stdint.h>
#include <vkd3d_types.h>
#ifdef __cplusplus
@@ -31,6 +32,7 @@ enum vkd3d_shader_structure_type
VKD3D_SHADER_STRUCTURE_TYPE_SHADER_INTERFACE,
VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_ARGUMENTS,
VKD3D_SHADER_STRUCTURE_TYPE_SCAN_INFO,
+ VKD3D_SHADER_STRUCTURE_TYPE_TRANSFORM_FEEDBACK_INFO,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE),
};
@@ -151,6 +153,28 @@ struct vkd3d_shader_interface
unsigned int uav_counter_count;
};
+struct vkd3d_shader_transform_feedback_element
+{
+ unsigned int stream_index;
+ const char *semantic_name;
+ unsigned int semantic_index;
+ uint8_t component_index;
+ uint8_t component_count;
+ uint8_t output_slot;
+};
+
+/* Extends vkd3d_shader_interface. */
+struct vkd3d_shader_transform_feedback_info
+{
+ enum vkd3d_shader_structure_type type;
+ const void *next;
+
+ const struct vkd3d_shader_transform_feedback_element *elements;
+ unsigned int element_count;
+ const unsigned int *buffer_strides;
+ unsigned int buffer_stride_count;
+};
+
enum vkd3d_shader_target
{
VKD3D_SHADER_TARGET_NONE,
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 538c44f..9d1a0df 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -108,6 +108,27 @@ static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, enum vkd
#endif /* HAVE_SPIRV_TOOLS */
+struct vkd3d_struct
+{
+ enum vkd3d_shader_structure_type type;
+ const void *next;
+};
+
+#define vkd3d_find_struct(c, t) vkd3d_find_struct_(c, VKD3D_SHADER_STRUCTURE_TYPE_##t)
+static const void *vkd3d_find_struct_(const struct vkd3d_struct *chain,
+ enum vkd3d_shader_structure_type type)
+{
+ while (chain)
+ {
+ if (chain->type == type)
+ return chain;
+
+ chain = chain->next;
+ }
+
+ return NULL;
+}
+
#define VKD3D_SPIRV_VERSION 0x00010000
#define VKD3D_SPIRV_GENERATOR_ID 18
#define VKD3D_SPIRV_GENERATOR_VERSION 1
@@ -1884,6 +1905,7 @@ struct vkd3d_dxbc_compiler
bool after_declarations_section;
const struct vkd3d_shader_signature *input_signature;
const struct vkd3d_shader_signature *output_signature;
+ const struct vkd3d_shader_transform_feedback_info *xfb_info;
struct vkd3d_shader_output_info
{
uint32_t id;
@@ -1934,6 +1956,8 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
if (shader_interface)
{
+ compiler->xfb_info = vkd3d_find_struct(shader_interface->next, TRANSFORM_FEEDBACK_INFO);
+
compiler->shader_interface = *shader_interface;
if (shader_interface->push_constant_buffer_count)
{
@@ -3178,6 +3202,64 @@ static unsigned int vkd3d_count_signature_elements_for_reg(
return count;
}
+static void vkd3d_dxbc_compiler_decorate_xfb_output(struct vkd3d_dxbc_compiler *compiler,
+ uint32_t id, unsigned int component_count, const struct vkd3d_shader_signature_element *signature_element)
+{
+ const struct vkd3d_shader_transform_feedback_info *xfb_info = compiler->xfb_info;
+ const struct vkd3d_shader_transform_feedback_element *xfb_element;
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ unsigned int offset, stride, i;
+
+ if (!xfb_info)
+ return;
+
+ offset = 0;
+ xfb_element = NULL;
+ for (i = 0; i < xfb_info->element_count; ++i)
+ {
+ const struct vkd3d_shader_transform_feedback_element *e = &xfb_info->elements[i];
+
+ if (e->stream_index == signature_element->stream_index
+ && !strcasecmp(e->semantic_name, signature_element->semantic_name)
+ && e->semantic_index == signature_element->semantic_index)
+ {
+ xfb_element = e;
+ break;
+ }
+
+ offset += 4 * e->component_count;
+ }
+
+ if (!xfb_element)
+ return;
+
+ if (xfb_element->component_index || xfb_element->component_count > component_count)
+ {
+ FIXME("Unhandled component range %u, %u.\n", xfb_element->component_index, xfb_element->component_count);
+ return;
+ }
+
+ if (xfb_element->output_slot < xfb_info->buffer_stride_count)
+ {
+ stride = xfb_info->buffer_strides[xfb_element->output_slot];
+ }
+ else
+ {
+ stride = 0;
+ for (i = 0; i < xfb_info->element_count; ++i)
+ {
+ const struct vkd3d_shader_transform_feedback_element *e = &xfb_info->elements[i];
+
+ if (e->stream_index == xfb_element->stream_index && e->output_slot == xfb_element->output_slot)
+ stride += 4 * e->component_count;
+ }
+ }
+
+ vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationXfbBuffer, xfb_element->output_slot);
+ vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationXfbStride, stride);
+ vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationOffset, offset);
+}
+
static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_input_sysval_semantic sysval)
{
@@ -3541,6 +3623,8 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler
if (component_idx)
vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationComponent, component_idx);
}
+
+ vkd3d_dxbc_compiler_decorate_xfb_output(compiler, id, output_component_count, signature_element);
}
compiler->output_info[signature_idx].id = id;
@@ -3583,6 +3667,7 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler
static void vkd3d_dxbc_compiler_emit_initial_declarations(struct vkd3d_dxbc_compiler *compiler)
{
+ const struct vkd3d_shader_transform_feedback_info *xfb_info = compiler->xfb_info;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
switch (compiler->shader_type)
@@ -3610,6 +3695,12 @@ static void vkd3d_dxbc_compiler_emit_initial_declarations(struct vkd3d_dxbc_comp
ERR("Invalid shader type %#x.\n", compiler->shader_type);
}
+ if (xfb_info && xfb_info->element_count)
+ {
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityTransformFeedback);
+ vkd3d_dxbc_compiler_emit_execution_mode(compiler, SpvExecutionModeXfb, NULL, 0);
+ }
+
vkd3d_dxbc_compiler_emit_shader_signature_outputs(compiler);
}
More information about the wine-cvs
mailing list