Discussion:
[Mesa-dev] [RFC PATCH 00/65] ARB_bindless_texture for RadeonSI
Samuel Pitoiset
2017-05-19 16:52:05 UTC
Permalink
Hi,

This series implements ARB_bindless_texture for RadeonSI.

Reminder: the GLSL compiler part is already upstream.

This series has been mainly tested with Feral games, here's the list of
existing games that use ARB_bindless_texture (though not by default):

- DXMD
- Hitman
- Dirt Rally
- Mad Max

Today, Feral announced "Warhammer 40,000: Dawn of War III" (called DOW3) which
is going to be released next month. This game *requires* ARB_bindless_texture,
that now explains why I did all this work. :-) So, we have ~3 weeks for merging
this whole series. It would be very nice to have DOW3 support at day one!

=== Tracking bindless problems ===

The following games have been successfully tested:

- Dirt Rally
- Hitman
- Mad Max
- DOW3

For these:

- No rendering issues
- No VM faults (ie. amdgpu.vm_debug=1)

However, DXMD is currently broken because the bindless_sampler layout qualifier
is missing, which ends up by reporting a ton of INVALID_OPERATION errors. Note
that Feral implemented bindless support against NV_bindless_texture and not
ARB_bindless_texture. The main difference is that bindless_sampler is implicit
for NV_* while it's required for ARB_*. Feral plan to fix this soon.

All ARB_bindless_texture piglit tests pass with this series.

=== Tracking regressions/changes ===

- No regressions with the Intel CI system
- One piglit regression that needs to be fixed
(arb_texture_multisample-sample-position)
- No shader-db changes
- No CPU overhead (glxgears and Heaven in low)

=== Performance results for DOW3 ===

DOW3 exposes two bindless texture modes:
- mode 1: all bindless (ie. no bound samplers)
- mode 2: bound/bindless (ie. only bindless when the limit is reached)

CPU: Intel(R) Core(TM) i5-4460 CPU @ 3.20GHz
NVIDIA blob: 381.22

== GTX 1060 ==

LOW:
- mode 1: 89 FPS
- mode 2: 51 FPS

MEDIUM:
- mode 1: 49 FPS
- mode 2: 28 FPS

HIGH:
- mode 1: 32 FPS
- mode 2: 19 FPS

The GTX 1060 performs very well with the all bindless mode (default), while
the bound/bindless mode is not good at all.

== RX480 ==

LOW:
- mode 1: 67 FPS (-32%)
- mode 2: 75 FPS (+32%)

MEDIUM:
- mode 1: 38 FPS (-28%)
- mode 2: 44 FPS (+57%)

HIGH:
- mode 1: 26 FPS (-23%)
- mode 2: 29 FPS (+52%)

The RX 480 performs very well with the bound/bindless mode (default), while
the all bindless mode still has to be improved.

The most important bottleneck with the all bindless mode is the number of
buffers that have to be added for every command stream. The overhead in the
winsys and in the kernel (amdgpu_cs_ioctl) becomes important in this situation.
This mode is still clearly CPU bound and should be improved (see the "Future
work" section).

Btw, without any optimisations, it was around 35FPS in low (mode 1).

=== Performance results for other Feral titles ===

I didn't record any numbers because these games have been initially
developed/tested against the NVIDIA blob which it's unaffected by a VERY huge
number of resident handles. While the AMD stack is really slow in this
situation. Though, as I said, all Feral games that use bindless work fine, we
just need to improve perf on both sides.

=== Future work ===

I have some ideas to try in order to improve performance with RadeonSI. I will
work on this once this series is upstream.

Please review,
Thanks!

Samuel Pitoiset (65):
mapi: add GL_ARB_bindless_texture entry points
mesa: implement ARB_bindless_texture
mesa: add support for unsigned 64-bit vertex attributes
mesa: add support for glUniformHandleui64*ARB()
mesa: refuse to update sampler parameters when a handle is allocated
mesa: refuse to update tex parameters when a handle is allocated
mesa: refuse to change textures when a handle is allocated
mesa: refuse to change tex buffers when a handle is allocated
mesa: keep track of the current variable in add_uniform_to_shader
mesa: store bindless samplers as PROGRAM_UNIFORM
mesa: add infrastructure for bindless samplers/images bound to units
glsl: process uniform samplers declared bindless
glsl: process uniform images declared bindless
glsl: pass the ir_variable object to set_opaque_binding()
glsl: set the explicit binding value for bindless samplers/images
glsl: add ir_variable::is_bindless()
mesa: add update_single_shader_texture_used() helper
mesa: add update_single_program_texture_state() helper
mesa: update textures for bindless samplers bound to texture units
mesa: pass gl_program to _mesa_associate_uniform_storage()
mesa: associate uniform storage to bindless samplers/images
mesa: handle bindless uniforms bound to texture/image units
mesa: get rid of a workaround for bindless in _mesa_get_uniform()
gallium: add PIPE_CAP_BINDLESS_TEXTURE
gallium: add ARB_bindless_texture interface
ddebug: add ARB_bindless_texture support
trace: add ARB_bindless_texture support
tc: add ARB_bindless_texture support
tgsi: add new Bindless flag to tgsi_instruction_texture
tgsi: add new Bindless flag to tgsi_instruction_memory
tgsi/ureg: accept TGSI_FILE_{CONSTANT,INPUT} for dst registers
st/glsl_to_tgsi: add support for bindless samplers
st/glsl_to_tgsi: add support for bindless images
st/glsl_to_tgsi: add support for bindless pack/unpack operations
st/glsl_to_tgsi: teach the DCE pass about bindless samplers/images
st/glsl_to_tgsi: teach rename_temp_registers() about bindless samplers
tgsi/scan: record bindless samplers/images usage
st/mesa: implement ARB_bindless_texture
st/mesa: make update_single_texture() non-static
st/mesa: make convert_sampler_from_unit() non-static
st/mesa: add st_convert_image_from_unit() helper
st/mesa: add st_create_{texture,image}_handle_from_unit() helper
st/mesa: add infrastructure for storing bound texture/image handles
st/mesa: make bindless samplers/images bound to units resident
st/mesa: do not release sampler views for resident textures
st/mesa: disable per-context seamless cubemap when using texture
handles
st/mesa: enable ARB_bindless_texture
radeonsi: add a slab allocator for resident descriptors
radeonsi: add si_init_descriptor_list() helper
radeonsi: add si_set_sampler_view_desc() helper
radeonsi: add si_set_shader_image_desc() helper
radeonsi: implement ARB_bindless_texture
radeonsi: add all resident buffers to the current CS
radeonsi: only add descriptors in presence of resident handles
radeonsi: add si_update_check_render_feedback() helper
radeonsi: decompress DCC for resident textures/images
radeonsi: decompress resident textures/images before graphics/compute
radeonsi: isolate real framebuffer changes from the decompression
passes
radeonsi: track use of bindless samplers/images from tgsi_shader_info
radeonsi: only decompress resident textures/images when used
radeonsi: upload new descriptors when resident buffers are invalidated
radeonsi: invalidate buffers which are made resident if needed
radeonsi: add support for loading bindless samplers
radeonsi: add support for loading bindless images
radeonsi: enable ARB_bindless_texture

docs/features.txt | 2 +-
docs/relnotes/17.2.0.html | 1 +
src/compiler/glsl/ir.h | 11 +
src/compiler/glsl/ir_uniform.h | 12 +
src/compiler/glsl/link_uniform_initializers.cpp | 42 +-
src/compiler/glsl/link_uniforms.cpp | 156 +++-
src/compiler/glsl/shader_cache.cpp | 47 +
src/gallium/auxiliary/tgsi/tgsi_build.c | 8 +
src/gallium/auxiliary/tgsi/tgsi_scan.c | 37 +
src/gallium/auxiliary/tgsi/tgsi_scan.h | 2 +
src/gallium/auxiliary/tgsi/tgsi_ureg.c | 21 +-
src/gallium/auxiliary/tgsi/tgsi_ureg.h | 16 +-
src/gallium/auxiliary/util/u_threaded_context.c | 147 ++++
.../auxiliary/util/u_threaded_context_calls.h | 4 +
src/gallium/docs/source/screen.rst | 2 +
src/gallium/drivers/ddebug/dd_context.c | 61 ++
src/gallium/drivers/etnaviv/etnaviv_screen.c | 1 +
src/gallium/drivers/freedreno/freedreno_screen.c | 1 +
src/gallium/drivers/i915/i915_screen.c | 1 +
src/gallium/drivers/llvmpipe/lp_screen.c | 1 +
src/gallium/drivers/nouveau/nv30/nv30_screen.c | 1 +
src/gallium/drivers/nouveau/nv50/nv50_screen.c | 1 +
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 1 +
src/gallium/drivers/r300/r300_screen.c | 1 +
src/gallium/drivers/r600/r600_pipe.c | 1 +
src/gallium/drivers/radeon/r600_pipe_common.h | 4 +
src/gallium/drivers/radeonsi/si_blit.c | 131 ++-
src/gallium/drivers/radeonsi/si_compute.c | 2 +
src/gallium/drivers/radeonsi/si_compute.h | 14 +
src/gallium/drivers/radeonsi/si_descriptors.c | 943 +++++++++++++++++++--
src/gallium/drivers/radeonsi/si_hw_context.c | 1 +
src/gallium/drivers/radeonsi/si_pipe.c | 25 +
src/gallium/drivers/radeonsi/si_pipe.h | 68 ++
src/gallium/drivers/radeonsi/si_shader.h | 12 +
src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c | 48 +-
src/gallium/drivers/radeonsi/si_state.c | 10 +-
src/gallium/drivers/radeonsi/si_state.h | 9 +
src/gallium/drivers/softpipe/sp_screen.c | 1 +
src/gallium/drivers/svga/svga_screen.c | 1 +
src/gallium/drivers/swr/swr_screen.cpp | 1 +
src/gallium/drivers/trace/tr_context.c | 114 +++
src/gallium/drivers/vc4/vc4_screen.c | 1 +
src/gallium/drivers/virgl/virgl_screen.c | 1 +
src/gallium/include/pipe/p_context.h | 16 +
src/gallium/include/pipe/p_defines.h | 1 +
src/gallium/include/pipe/p_shader_tokens.h | 6 +-
src/mapi/glapi/gen/ARB_bindless_texture.xml | 100 +++
src/mapi/glapi/gen/Makefile.am | 1 +
src/mapi/glapi/gen/apiexec.py | 3 +
src/mapi/glapi/gen/gl_API.xml | 4 +-
src/mapi/glapi/gen/gl_genexec.py | 1 +
src/mesa/Makefile.sources | 2 +
src/mesa/main/api_loopback.c | 18 +
src/mesa/main/api_loopback.h | 6 +
src/mesa/main/bufferobj.c | 4 +-
src/mesa/main/context.c | 3 +
src/mesa/main/dd.h | 19 +
src/mesa/main/mtypes.h | 86 ++
src/mesa/main/samplerobj.c | 48 ++
src/mesa/main/shared.c | 12 +
src/mesa/main/tests/dispatch_sanity.cpp | 18 +
src/mesa/main/teximage.c | 25 +-
src/mesa/main/texobj.c | 12 +
src/mesa/main/texparam.c | 61 ++
src/mesa/main/texstate.c | 52 +-
src/mesa/main/texturebindless.c | 902 ++++++++++++++++++++
src/mesa/main/texturebindless.h | 96 +++
src/mesa/main/uniform_query.cpp | 208 ++++-
src/mesa/main/uniforms.c | 119 ++-
src/mesa/main/uniforms.h | 16 +
src/mesa/main/varray.c | 23 +
src/mesa/main/varray.h | 3 +
src/mesa/main/vtxfmt.c | 4 +
src/mesa/program/ir_to_mesa.cpp | 36 +-
src/mesa/program/ir_to_mesa.h | 4 +-
src/mesa/program/program.c | 8 +
src/mesa/state_tracker/st_atifs_to_tgsi.c | 2 +-
src/mesa/state_tracker/st_atom_constbuf.c | 6 +
src/mesa/state_tracker/st_atom_image.c | 33 +-
src/mesa/state_tracker/st_atom_sampler.c | 32 +-
src/mesa/state_tracker/st_atom_texture.c | 15 +-
src/mesa/state_tracker/st_cb_texture.c | 84 ++
src/mesa/state_tracker/st_context.c | 2 +
src/mesa/state_tracker/st_context.h | 11 +
src/mesa/state_tracker/st_extensions.c | 1 +
src/mesa/state_tracker/st_glsl_to_nir.cpp | 3 +-
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 138 ++-
src/mesa/state_tracker/st_mesa_to_tgsi.c | 2 +-
src/mesa/state_tracker/st_pbo.c | 2 +-
src/mesa/state_tracker/st_sampler_view.c | 6 +
src/mesa/state_tracker/st_shader_cache.c | 3 +-
src/mesa/state_tracker/st_texture.c | 213 +++++
src/mesa/state_tracker/st_texture.h | 28 +
src/mesa/vbo/vbo_attrib_tmp.h | 28 +
src/mesa/vbo/vbo_context.h | 2 +
src/mesa/vbo/vbo_exec_api.c | 15 +-
src/mesa/vbo/vbo_save_api.c | 3 +
97 files changed, 4250 insertions(+), 260 deletions(-)
create mode 100644 src/mapi/glapi/gen/ARB_bindless_texture.xml
create mode 100644 src/mesa/main/texturebindless.c
create mode 100644 src/mesa/main/texturebindless.h
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:06 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mapi/glapi/gen/ARB_bindless_texture.xml | 100 ++++++++++++++++++++++++++++
src/mapi/glapi/gen/Makefile.am | 1 +
src/mapi/glapi/gen/gl_API.xml | 4 +-
src/mapi/glapi/gen/gl_genexec.py | 1 +
src/mesa/Makefile.sources | 2 +
src/mesa/main/api_loopback.c | 14 ++++
src/mesa/main/api_loopback.h | 6 ++
src/mesa/main/dd.h | 2 +
src/mesa/main/tests/dispatch_sanity.cpp | 18 +++++
src/mesa/main/texturebindless.c | 85 +++++++++++++++++++++++
src/mesa/main/texturebindless.h | 68 +++++++++++++++++++
src/mesa/main/uniforms.c | 24 +++++++
src/mesa/main/uniforms.h | 12 ++++
src/mesa/main/varray.c | 5 ++
src/mesa/main/varray.h | 3 +
src/mesa/main/vtxfmt.c | 4 ++
src/mesa/vbo/vbo_attrib_tmp.h | 9 +++
src/mesa/vbo/vbo_exec_api.c | 3 +
src/mesa/vbo/vbo_save_api.c | 3 +
19 files changed, 363 insertions(+), 1 deletion(-)
create mode 100644 src/mapi/glapi/gen/ARB_bindless_texture.xml
create mode 100644 src/mesa/main/texturebindless.c
create mode 100644 src/mesa/main/texturebindless.h

diff --git a/src/mapi/glapi/gen/ARB_bindless_texture.xml b/src/mapi/glapi/gen/ARB_bindless_texture.xml
new file mode 100644
index 0000000000..bfad45651c
--- /dev/null
+++ b/src/mapi/glapi/gen/ARB_bindless_texture.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_ARB_bindless_texture" number="152">
+
+ <enum name="UNSIGNED_INT64_ARB" value="0x140F" />
+ <type name="uint64EXT" unsigned="true" size="8"/>
+
+ <function name="GetTextureHandleARB" offset="assign">
+ <return type="GLuint64"/>
+ <param name="texture" type="GLuint" />
+ </function>
+
+ <function name="GetTextureSamplerHandleARB" offset="assign">
+ <return type="GLuint64"/>
+ <param name="texture" type="GLuint" />
+ <param name="sampler" type="GLuint" />
+ </function>
+
+ <function name="MakeTextureHandleResidentARB" offset="assign">
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="MakeTextureHandleNonResidentARB" offset="assign">
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="GetImageHandleARB" offset="assign">
+ <return type="GLuint64"/>
+ <param name="texture" type="GLuint" />
+ <param name="level" type="GLint" />
+ <param name="layered" type="GLboolean" />
+ <param name="layer" type="GLint" />
+ <param name="format" type="GLenum" />
+ </function>
+
+ <function name="MakeImageHandleResidentARB" offset="assign">
+ <param name="handle" type="GLuint64" />
+ <param name="access" type="GLenum" />
+ </function>
+
+ <function name="MakeImageHandleNonResidentARB" offset="assign">
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="UniformHandleui64ARB" offset="assign">
+ <param name="location" type="GLint" />
+ <param name="value" type="GLuint64" />
+ </function>
+
+ <function name="UniformHandleui64vARB" offset="assign">
+ <param name="location" type="GLint" />
+ <param name="count" type="GLsizei" />
+ <param name="value" type="const GLuint64 *" />
+ </function>
+
+ <function name="ProgramUniformHandleui64ARB" offset="assign">
+ <param name="program" type="GLuint" />
+ <param name="location" type="GLint" />
+ <param name="value" type="GLuint64" />
+ </function>
+
+ <function name="ProgramUniformHandleui64vARB" offset="assign">
+ <param name="program" type="GLuint" />
+ <param name="location" type="GLint" />
+ <param name="count" type="GLsizei" />
+ <param name="value" type="const GLuint64 *" />
+ </function>
+
+ <function name="IsTextureHandleResidentARB" offset="assign">
+ <return type="GLboolean"/>
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="IsImageHandleResidentARB" offset="assign">
+ <return type="GLboolean"/>
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="VertexAttribL1ui64ARB" offset="assign" exec="dynamic">
+ <param name="index" type="GLuint" />
+ <param name="x" type="GLuint64EXT" />
+ </function>
+
+ <function name="VertexAttribL1ui64vARB" offset="assign" exec="dynamic">
+ <param name="index" type="GLuint" />
+ <param name="v" type="const GLuint64EXT *" />
+ </function>
+
+ <function name="GetVertexAttribLui64vARB">
+ <param name="index" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="params" type="GLuint64EXT *" />
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mapi/glapi/gen/Makefile.am b/src/mapi/glapi/gen/Makefile.am
index ecd1c71175..80f9139e5d 100644
--- a/src/mapi/glapi/gen/Makefile.am
+++ b/src/mapi/glapi/gen/Makefile.am
@@ -119,6 +119,7 @@ API_XML = \
gl_and_glX_API.xml \
ARB_base_instance.xml \
ARB_blend_func_extended.xml \
+ ARB_bindless_texture.xml \
ARB_clear_buffer_object.xml \
ARB_clear_texture.xml \
ARB_clip_control.xml \
diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
index 762fb5a676..278fe14bb6 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -8284,7 +8284,9 @@
<enum name="QUERY_BUFFER_BARRIER_BIT" value="0x00008000"/>
</category>

-<!-- ARB extensions 149 - 152 -->
+<!-- ARB extensions 149 - 151 -->
+
+<xi:include href="ARB_bindless_texture.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>

<xi:include href="ARB_compute_variable_group_size.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>

diff --git a/src/mapi/glapi/gen/gl_genexec.py b/src/mapi/glapi/gen/gl_genexec.py
index 37b1cc6be0..57e155bd1f 100644
--- a/src/mapi/glapi/gen/gl_genexec.py
+++ b/src/mapi/glapi/gen/gl_genexec.py
@@ -113,6 +113,7 @@ header = """/**
#include "main/texstate.h"
#include "main/texstorage.h"
#include "main/barrier.h"
+#include "main/texturebindless.h"
#include "main/textureview.h"
#include "main/transformfeedback.h"
#include "main/mtypes.h"
diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources
index 8a65fbe663..b80882fb8d 100644
--- a/src/mesa/Makefile.sources
+++ b/src/mesa/Makefile.sources
@@ -240,6 +240,8 @@ MAIN_FILES = \
main/texstorage.h \
main/texstore.c \
main/texstore.h \
+ main/texturebindless.c \
+ main/texturebindless.h \
main/textureview.c \
main/textureview.h \
main/transformfeedback.c \
diff --git a/src/mesa/main/api_loopback.c b/src/mesa/main/api_loopback.c
index 59b59d3a9e..36e5194b93 100644
--- a/src/mesa/main/api_loopback.c
+++ b/src/mesa/main/api_loopback.c
@@ -1529,6 +1529,16 @@ _mesa_VertexAttribL1dv(GLuint index, const GLdouble *v)
}

void GLAPIENTRY
+_mesa_VertexAttribL1ui64ARB(GLuint index, GLuint64EXT x)
+{
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL1ui64vARB(GLuint index, const GLuint64EXT *v)
+{
+}
+
+void GLAPIENTRY
_mesa_VertexAttribL2dv(GLuint index, const GLdouble *v)
{
ATTRIB2_D(index, v[0], v[1]);
@@ -1789,5 +1799,9 @@ _mesa_loopback_init_api_table(const struct gl_context *ctx,
SET_VertexAttribL2dv(dest, _mesa_VertexAttribL2dv);
SET_VertexAttribL3dv(dest, _mesa_VertexAttribL3dv);
SET_VertexAttribL4dv(dest, _mesa_VertexAttribL4dv);
+
+ /* GL_ARB_bindless_texture */
+ SET_VertexAttribL1ui64ARB(dest, _mesa_VertexAttribL1ui64ARB);
+ SET_VertexAttribL1ui64vARB(dest, _mesa_VertexAttribL1ui64vARB);
}
}
diff --git a/src/mesa/main/api_loopback.h b/src/mesa/main/api_loopback.h
index 026bfd68e1..c1e7b24f09 100644
--- a/src/mesa/main/api_loopback.h
+++ b/src/mesa/main/api_loopback.h
@@ -481,4 +481,10 @@ void GLAPIENTRY
_mesa_VertexAttribL3dv(GLuint index, const GLdouble *v);
void GLAPIENTRY
_mesa_VertexAttribL4dv(GLuint index, const GLdouble *v);
+
+void GLAPIENTRY
+_mesa_VertexAttribL1ui64ARB(GLuint index, GLuint64EXT x);
+void GLAPIENTRY
+_mesa_VertexAttribL1ui64vARB(GLuint index, const GLuint64EXT *v);
+
#endif /* API_LOOPBACK_H */
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 3f3102546d..a9ca43d69e 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -1225,6 +1225,8 @@ typedef struct {
void (GLAPIENTRYP VertexAttribL3dv)( GLuint index, const GLdouble *v);
void (GLAPIENTRYP VertexAttribL4dv)( GLuint index, const GLdouble *v);

+ void (GLAPIENTRYP VertexAttribL1ui64ARB)( GLuint index, GLuint64EXT x);
+ void (GLAPIENTRYP VertexAttribL1ui64vARB)( GLuint index, const GLuint64EXT *v);
} GLvertexformat;


diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp
index b33043ed28..47d0aa63bf 100644
--- a/src/mesa/main/tests/dispatch_sanity.cpp
+++ b/src/mesa/main/tests/dispatch_sanity.cpp
@@ -2374,6 +2374,24 @@ const struct function gles2_functions_possible[] = {
/* GL_KHR_blend_equation_advanced */
{ "glBlendBarrierKHR", 20, -1 },

+ /* GL_ARB_bindless_texture */
+ { "glGetTextureHandleARB", 40, -1 },
+ { "glGetTextureSamplerHandleARB", 40, -1 },
+ { "glMakeTextureHandleResidentARB", 40, -1 },
+ { "glMakeTextureHandleNonResidentARB", 40, -1 },
+ { "glIsTextureHandleResidentARB", 40, -1 },
+ { "glGetImageHandleARB", 40, -1 },
+ { "glMakeImageHandleResidentARB", 40, -1 },
+ { "glMakeImageHandleNonResidentARB", 40, -1 },
+ { "glIsImageHandleResidentARB", 40, -1 },
+ { "glUniformHandleui64ARB", 40, -1 },
+ { "glUniformHandleui64vARB", 40, -1 },
+ { "glProgramUniformHandleui64ARB", 40, -1 },
+ { "glProgramUniformHandleui64vARB", 40, -1 },
+ { "glVertexAttribL1ui64ARB", 40, -1 },
+ { "glVertexAttribL1ui64vARB", 40, -1 },
+ { "glGetVertexAttribLui64vARB", 40, -1 },
+
{ NULL, 0, -1 }
};

diff --git a/src/mesa/main/texturebindless.c b/src/mesa/main/texturebindless.c
new file mode 100644
index 0000000000..4d9c22d428
--- /dev/null
+++ b/src/mesa/main/texturebindless.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2017 Valve Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "enums.h"
+#include "imports.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "texobj.h"
+#include "texturebindless.h"
+
+#include "util/set.h"
+#include "util/hash_table.h"
+
+GLuint64 GLAPIENTRY
+_mesa_GetTextureHandleARB(GLuint texture)
+{
+ return 0;
+}
+
+GLuint64 GLAPIENTRY
+_mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler)
+{
+ return 0;
+}
+
+void GLAPIENTRY
+_mesa_MakeTextureHandleResidentARB(GLuint64 handle)
+{
+}
+
+void GLAPIENTRY
+_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle)
+{
+}
+
+GLuint64 GLAPIENTRY
+_mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
+ GLint layer, GLenum format)
+{
+ return 0;
+}
+
+void GLAPIENTRY
+_mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access)
+{
+}
+
+void GLAPIENTRY
+_mesa_MakeImageHandleNonResidentARB(GLuint64 handle)
+{
+}
+
+GLboolean GLAPIENTRY
+_mesa_IsTextureHandleResidentARB(GLuint64 handle)
+{
+ return GL_FALSE;
+}
+
+GLboolean GLAPIENTRY
+_mesa_IsImageHandleResidentARB(GLuint64 handle)
+{
+ return GL_FALSE;
+}
diff --git a/src/mesa/main/texturebindless.h b/src/mesa/main/texturebindless.h
new file mode 100644
index 0000000000..88b84ce275
--- /dev/null
+++ b/src/mesa/main/texturebindless.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2017 Valve Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef TEXTUREBINDLESS_H
+#define TEXTUREBINDLESS_H
+
+#include "mtypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name API functions
+ */
+/*@{*/
+
+GLuint64 GLAPIENTRY
+_mesa_GetTextureHandleARB(GLuint texture);
+GLuint64 GLAPIENTRY
+_mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler);
+
+void GLAPIENTRY
+_mesa_MakeTextureHandleResidentARB(GLuint64 handle);
+void GLAPIENTRY
+_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle);
+
+GLuint64 GLAPIENTRY
+_mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
+ GLint layer, GLenum format);
+
+void GLAPIENTRY
+_mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access);
+void GLAPIENTRY
+_mesa_MakeImageHandleNonResidentARB(GLuint64 handle);
+
+GLboolean GLAPIENTRY
+_mesa_IsTextureHandleResidentARB(GLuint64 handle);
+GLboolean GLAPIENTRY
+_mesa_IsImageHandleResidentARB(GLuint64 handle);
+
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index 8869b6eb22..a9e7cda17c 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c
@@ -294,6 +294,18 @@ _mesa_Uniform4iv(GLint location, GLsizei count, const GLint * value)
_mesa_uniform(location, count, value, ctx, ctx->_Shader->ActiveProgram, GLSL_TYPE_INT, 4);
}

+void GLAPIENTRY
+_mesa_UniformHandleui64ARB(GLint location, GLuint64 value)
+{
+}
+
+void GLAPIENTRY
+_mesa_UniformHandleui64vARB(GLint location, GLsizei count,
+ const GLuint64 *value)
+{
+}
+
+
/** Same as above with direct state access **/
void GLAPIENTRY
_mesa_ProgramUniform1f(GLuint program, GLint location, GLfloat v0)
@@ -485,6 +497,18 @@ _mesa_ProgramUniform4iv(GLuint program, GLint location, GLsizei count,
_mesa_uniform(location, count, value, ctx, shProg, GLSL_TYPE_INT, 4);
}

+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64ARB(GLuint program, GLint location,
+ GLuint64 value)
+{
+}
+
+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64vARB(GLuint program, GLint location,
+ GLsizei count, const GLuint64 *values)
+{
+}
+

/** OpenGL 3.0 GLuint-valued functions **/
void GLAPIENTRY
diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h
index 21d857107d..553e8717ba 100644
--- a/src/mesa/main/uniforms.h
+++ b/src/mesa/main/uniforms.h
@@ -113,6 +113,18 @@ _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
const GLfloat *value);

void GLAPIENTRY
+_mesa_UniformHandleui64ARB(GLint location, GLuint64 value);
+void GLAPIENTRY
+_mesa_UniformHandleui64vARB(GLint location, GLsizei count,
+ const GLuint64 *value);
+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64ARB(GLuint program, GLint location,
+ GLuint64 value);
+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64vARB(GLuint program, GLint location,
+ GLsizei count, const GLuint64 *values);
+
+void GLAPIENTRY
_mesa_ProgramUniform1f(GLuint program, GLint, GLfloat);
void GLAPIENTRY
_mesa_ProgramUniform2f(GLuint program, GLint, GLfloat, GLfloat);
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
index 0eb8e623dc..fcb53d3986 100644
--- a/src/mesa/main/varray.c
+++ b/src/mesa/main/varray.c
@@ -1353,6 +1353,11 @@ _mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
}
}

+void GLAPIENTRY
+_mesa_GetVertexAttribLui64vARB(GLuint index, GLenum pname, GLuint64EXT *params)
+{
+}
+

/** GL 3.0 */
void GLAPIENTRY
diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h
index 2d184adf8b..00c18b619e 100644
--- a/src/mesa/main/varray.h
+++ b/src/mesa/main/varray.h
@@ -248,6 +248,9 @@ _mesa_GetVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params);
extern void GLAPIENTRY
_mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params);

+extern void GLAPIENTRY
+_mesa_GetVertexAttribLui64vARB(GLuint index, GLenum pname, GLuint64EXT *params);
+

extern void GLAPIENTRY
_mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params);
diff --git a/src/mesa/main/vtxfmt.c b/src/mesa/main/vtxfmt.c
index 81bf4c589e..d3c83e5eb3 100644
--- a/src/mesa/main/vtxfmt.c
+++ b/src/mesa/main/vtxfmt.c
@@ -217,6 +217,10 @@ install_vtxfmt(struct gl_context *ctx, struct _glapi_table *tab,
SET_VertexAttribL2dv(tab, vfmt->VertexAttribL2dv);
SET_VertexAttribL3dv(tab, vfmt->VertexAttribL3dv);
SET_VertexAttribL4dv(tab, vfmt->VertexAttribL4dv);
+
+ /* GL_ARB_bindless_texture */
+ SET_VertexAttribL1ui64ARB(tab, vfmt->VertexAttribL1ui64ARB);
+ SET_VertexAttribL1ui64vARB(tab, vfmt->VertexAttribL1ui64vARB);
}
}

diff --git a/src/mesa/vbo/vbo_attrib_tmp.h b/src/mesa/vbo/vbo_attrib_tmp.h
index 4e2c874ef3..08b441aafb 100644
--- a/src/mesa/vbo/vbo_attrib_tmp.h
+++ b/src/mesa/vbo/vbo_attrib_tmp.h
@@ -1302,6 +1302,15 @@ TAG(VertexAttribL4dv)(GLuint index, const GLdouble * v)
ERROR(GL_INVALID_VALUE);
}

+static void GLAPIENTRY
+TAG(VertexAttribL1ui64ARB)(GLuint index, GLuint64EXT x)
+{
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL1ui64vARB)(GLuint index, const GLuint64EXT *v)
+{
+}

#undef ATTR1FV
#undef ATTR2FV
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index f08fd4c32c..4db4eef3b6 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -1089,6 +1089,9 @@ vbo_exec_vtxfmt_init(struct vbo_exec_context *exec)
vfmt->VertexAttribL2dv = vbo_VertexAttribL2dv;
vfmt->VertexAttribL3dv = vbo_VertexAttribL3dv;
vfmt->VertexAttribL4dv = vbo_VertexAttribL4dv;
+
+ vfmt->VertexAttribL1ui64ARB = vbo_VertexAttribL1ui64ARB;
+ vfmt->VertexAttribL1ui64vARB = vbo_VertexAttribL1ui64vARB;
}


diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index ad54c3b38b..a0735f63f2 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -1490,6 +1490,9 @@ _save_vtxfmt_init(struct gl_context *ctx)
vfmt->VertexAttribL3dv = _save_VertexAttribL3dv;
vfmt->VertexAttribL4dv = _save_VertexAttribL4dv;

+ vfmt->VertexAttribL1ui64ARB = _save_VertexAttribL1ui64ARB;
+ vfmt->VertexAttribL1ui64vARB = _save_VertexAttribL1ui64vARB;
+
/* This will all require us to fallback to saving the list as opcodes:
*/
vfmt->CallList = _save_CallList;
--
2.13.0
Nicolai Hähnle
2017-05-22 09:46:46 UTC
Permalink
Post by Samuel Pitoiset
---
src/mapi/glapi/gen/ARB_bindless_texture.xml | 100 ++++++++++++++++++++++++++++
src/mapi/glapi/gen/Makefile.am | 1 +
src/mapi/glapi/gen/gl_API.xml | 4 +-
src/mapi/glapi/gen/gl_genexec.py | 1 +
src/mesa/Makefile.sources | 2 +
src/mesa/main/api_loopback.c | 14 ++++
src/mesa/main/api_loopback.h | 6 ++
src/mesa/main/dd.h | 2 +
src/mesa/main/tests/dispatch_sanity.cpp | 18 +++++
src/mesa/main/texturebindless.c | 85 +++++++++++++++++++++++
src/mesa/main/texturebindless.h | 68 +++++++++++++++++++
src/mesa/main/uniforms.c | 24 +++++++
src/mesa/main/uniforms.h | 12 ++++
src/mesa/main/varray.c | 5 ++
src/mesa/main/varray.h | 3 +
src/mesa/main/vtxfmt.c | 4 ++
src/mesa/vbo/vbo_attrib_tmp.h | 9 +++
src/mesa/vbo/vbo_exec_api.c | 3 +
src/mesa/vbo/vbo_save_api.c | 3 +
19 files changed, 363 insertions(+), 1 deletion(-)
create mode 100644 src/mapi/glapi/gen/ARB_bindless_texture.xml
create mode 100644 src/mesa/main/texturebindless.c
create mode 100644 src/mesa/main/texturebindless.h
diff --git a/src/mapi/glapi/gen/ARB_bindless_texture.xml b/src/mapi/glapi/gen/ARB_bindless_texture.xml
new file mode 100644
index 0000000000..bfad45651c
--- /dev/null
+++ b/src/mapi/glapi/gen/ARB_bindless_texture.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_ARB_bindless_texture" number="152">
+
+ <enum name="UNSIGNED_INT64_ARB" value="0x140F" />
+ <type name="uint64EXT" unsigned="true" size="8"/>
+
+ <function name="GetTextureHandleARB" offset="assign">
What's the offset="assign"?

Cheers,
Nicolai
Post by Samuel Pitoiset
+ <return type="GLuint64"/>
+ <param name="texture" type="GLuint" />
+ </function>
+
+ <function name="GetTextureSamplerHandleARB" offset="assign">
+ <return type="GLuint64"/>
+ <param name="texture" type="GLuint" />
+ <param name="sampler" type="GLuint" />
+ </function>
+
+ <function name="MakeTextureHandleResidentARB" offset="assign">
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="MakeTextureHandleNonResidentARB" offset="assign">
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="GetImageHandleARB" offset="assign">
+ <return type="GLuint64"/>
+ <param name="texture" type="GLuint" />
+ <param name="level" type="GLint" />
+ <param name="layered" type="GLboolean" />
+ <param name="layer" type="GLint" />
+ <param name="format" type="GLenum" />
+ </function>
+
+ <function name="MakeImageHandleResidentARB" offset="assign">
+ <param name="handle" type="GLuint64" />
+ <param name="access" type="GLenum" />
+ </function>
+
+ <function name="MakeImageHandleNonResidentARB" offset="assign">
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="UniformHandleui64ARB" offset="assign">
+ <param name="location" type="GLint" />
+ <param name="value" type="GLuint64" />
+ </function>
+
+ <function name="UniformHandleui64vARB" offset="assign">
+ <param name="location" type="GLint" />
+ <param name="count" type="GLsizei" />
+ <param name="value" type="const GLuint64 *" />
+ </function>
+
+ <function name="ProgramUniformHandleui64ARB" offset="assign">
+ <param name="program" type="GLuint" />
+ <param name="location" type="GLint" />
+ <param name="value" type="GLuint64" />
+ </function>
+
+ <function name="ProgramUniformHandleui64vARB" offset="assign">
+ <param name="program" type="GLuint" />
+ <param name="location" type="GLint" />
+ <param name="count" type="GLsizei" />
+ <param name="value" type="const GLuint64 *" />
+ </function>
+
+ <function name="IsTextureHandleResidentARB" offset="assign">
+ <return type="GLboolean"/>
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="IsImageHandleResidentARB" offset="assign">
+ <return type="GLboolean"/>
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="VertexAttribL1ui64ARB" offset="assign" exec="dynamic">
+ <param name="index" type="GLuint" />
+ <param name="x" type="GLuint64EXT" />
+ </function>
+
+ <function name="VertexAttribL1ui64vARB" offset="assign" exec="dynamic">
+ <param name="index" type="GLuint" />
+ <param name="v" type="const GLuint64EXT *" />
+ </function>
+
+ <function name="GetVertexAttribLui64vARB">
+ <param name="index" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="params" type="GLuint64EXT *" />
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mapi/glapi/gen/Makefile.am b/src/mapi/glapi/gen/Makefile.am
index ecd1c71175..80f9139e5d 100644
--- a/src/mapi/glapi/gen/Makefile.am
+++ b/src/mapi/glapi/gen/Makefile.am
@@ -119,6 +119,7 @@ API_XML = \
gl_and_glX_API.xml \
ARB_base_instance.xml \
ARB_blend_func_extended.xml \
+ ARB_bindless_texture.xml \
ARB_clear_buffer_object.xml \
ARB_clear_texture.xml \
ARB_clip_control.xml \
diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
index 762fb5a676..278fe14bb6 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -8284,7 +8284,9 @@
<enum name="QUERY_BUFFER_BARRIER_BIT" value="0x00008000"/>
</category>
-<!-- ARB extensions 149 - 152 -->
+<!-- ARB extensions 149 - 151 -->
+
+<xi:include href="ARB_bindless_texture.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="ARB_compute_variable_group_size.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
diff --git a/src/mapi/glapi/gen/gl_genexec.py b/src/mapi/glapi/gen/gl_genexec.py
index 37b1cc6be0..57e155bd1f 100644
--- a/src/mapi/glapi/gen/gl_genexec.py
+++ b/src/mapi/glapi/gen/gl_genexec.py
@@ -113,6 +113,7 @@ header = """/**
#include "main/texstate.h"
#include "main/texstorage.h"
#include "main/barrier.h"
+#include "main/texturebindless.h"
#include "main/textureview.h"
#include "main/transformfeedback.h"
#include "main/mtypes.h"
diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources
index 8a65fbe663..b80882fb8d 100644
--- a/src/mesa/Makefile.sources
+++ b/src/mesa/Makefile.sources
@@ -240,6 +240,8 @@ MAIN_FILES = \
main/texstorage.h \
main/texstore.c \
main/texstore.h \
+ main/texturebindless.c \
+ main/texturebindless.h \
main/textureview.c \
main/textureview.h \
main/transformfeedback.c \
diff --git a/src/mesa/main/api_loopback.c b/src/mesa/main/api_loopback.c
index 59b59d3a9e..36e5194b93 100644
--- a/src/mesa/main/api_loopback.c
+++ b/src/mesa/main/api_loopback.c
@@ -1529,6 +1529,16 @@ _mesa_VertexAttribL1dv(GLuint index, const GLdouble *v)
}
void GLAPIENTRY
+_mesa_VertexAttribL1ui64ARB(GLuint index, GLuint64EXT x)
+{
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL1ui64vARB(GLuint index, const GLuint64EXT *v)
+{
+}
+
+void GLAPIENTRY
_mesa_VertexAttribL2dv(GLuint index, const GLdouble *v)
{
ATTRIB2_D(index, v[0], v[1]);
@@ -1789,5 +1799,9 @@ _mesa_loopback_init_api_table(const struct gl_context *ctx,
SET_VertexAttribL2dv(dest, _mesa_VertexAttribL2dv);
SET_VertexAttribL3dv(dest, _mesa_VertexAttribL3dv);
SET_VertexAttribL4dv(dest, _mesa_VertexAttribL4dv);
+
+ /* GL_ARB_bindless_texture */
+ SET_VertexAttribL1ui64ARB(dest, _mesa_VertexAttribL1ui64ARB);
+ SET_VertexAttribL1ui64vARB(dest, _mesa_VertexAttribL1ui64vARB);
}
}
diff --git a/src/mesa/main/api_loopback.h b/src/mesa/main/api_loopback.h
index 026bfd68e1..c1e7b24f09 100644
--- a/src/mesa/main/api_loopback.h
+++ b/src/mesa/main/api_loopback.h
@@ -481,4 +481,10 @@ void GLAPIENTRY
_mesa_VertexAttribL3dv(GLuint index, const GLdouble *v);
void GLAPIENTRY
_mesa_VertexAttribL4dv(GLuint index, const GLdouble *v);
+
+void GLAPIENTRY
+_mesa_VertexAttribL1ui64ARB(GLuint index, GLuint64EXT x);
+void GLAPIENTRY
+_mesa_VertexAttribL1ui64vARB(GLuint index, const GLuint64EXT *v);
+
#endif /* API_LOOPBACK_H */
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 3f3102546d..a9ca43d69e 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -1225,6 +1225,8 @@ typedef struct {
void (GLAPIENTRYP VertexAttribL3dv)( GLuint index, const GLdouble *v);
void (GLAPIENTRYP VertexAttribL4dv)( GLuint index, const GLdouble *v);
+ void (GLAPIENTRYP VertexAttribL1ui64ARB)( GLuint index, GLuint64EXT x);
+ void (GLAPIENTRYP VertexAttribL1ui64vARB)( GLuint index, const GLuint64EXT *v);
} GLvertexformat;
diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp
index b33043ed28..47d0aa63bf 100644
--- a/src/mesa/main/tests/dispatch_sanity.cpp
+++ b/src/mesa/main/tests/dispatch_sanity.cpp
@@ -2374,6 +2374,24 @@ const struct function gles2_functions_possible[] = {
/* GL_KHR_blend_equation_advanced */
{ "glBlendBarrierKHR", 20, -1 },
+ /* GL_ARB_bindless_texture */
+ { "glGetTextureHandleARB", 40, -1 },
+ { "glGetTextureSamplerHandleARB", 40, -1 },
+ { "glMakeTextureHandleResidentARB", 40, -1 },
+ { "glMakeTextureHandleNonResidentARB", 40, -1 },
+ { "glIsTextureHandleResidentARB", 40, -1 },
+ { "glGetImageHandleARB", 40, -1 },
+ { "glMakeImageHandleResidentARB", 40, -1 },
+ { "glMakeImageHandleNonResidentARB", 40, -1 },
+ { "glIsImageHandleResidentARB", 40, -1 },
+ { "glUniformHandleui64ARB", 40, -1 },
+ { "glUniformHandleui64vARB", 40, -1 },
+ { "glProgramUniformHandleui64ARB", 40, -1 },
+ { "glProgramUniformHandleui64vARB", 40, -1 },
+ { "glVertexAttribL1ui64ARB", 40, -1 },
+ { "glVertexAttribL1ui64vARB", 40, -1 },
+ { "glGetVertexAttribLui64vARB", 40, -1 },
+
{ NULL, 0, -1 }
};
diff --git a/src/mesa/main/texturebindless.c b/src/mesa/main/texturebindless.c
new file mode 100644
index 0000000000..4d9c22d428
--- /dev/null
+++ b/src/mesa/main/texturebindless.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2017 Valve Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "enums.h"
+#include "imports.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "texobj.h"
+#include "texturebindless.h"
+
+#include "util/set.h"
+#include "util/hash_table.h"
+
+GLuint64 GLAPIENTRY
+_mesa_GetTextureHandleARB(GLuint texture)
+{
+ return 0;
+}
+
+GLuint64 GLAPIENTRY
+_mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler)
+{
+ return 0;
+}
+
+void GLAPIENTRY
+_mesa_MakeTextureHandleResidentARB(GLuint64 handle)
+{
+}
+
+void GLAPIENTRY
+_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle)
+{
+}
+
+GLuint64 GLAPIENTRY
+_mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
+ GLint layer, GLenum format)
+{
+ return 0;
+}
+
+void GLAPIENTRY
+_mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access)
+{
+}
+
+void GLAPIENTRY
+_mesa_MakeImageHandleNonResidentARB(GLuint64 handle)
+{
+}
+
+GLboolean GLAPIENTRY
+_mesa_IsTextureHandleResidentARB(GLuint64 handle)
+{
+ return GL_FALSE;
+}
+
+GLboolean GLAPIENTRY
+_mesa_IsImageHandleResidentARB(GLuint64 handle)
+{
+ return GL_FALSE;
+}
diff --git a/src/mesa/main/texturebindless.h b/src/mesa/main/texturebindless.h
new file mode 100644
index 0000000000..88b84ce275
--- /dev/null
+++ b/src/mesa/main/texturebindless.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2017 Valve Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef TEXTUREBINDLESS_H
+#define TEXTUREBINDLESS_H
+
+#include "mtypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name API functions
+ */
+
+GLuint64 GLAPIENTRY
+_mesa_GetTextureHandleARB(GLuint texture);
+GLuint64 GLAPIENTRY
+_mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler);
+
+void GLAPIENTRY
+_mesa_MakeTextureHandleResidentARB(GLuint64 handle);
+void GLAPIENTRY
+_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle);
+
+GLuint64 GLAPIENTRY
+_mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
+ GLint layer, GLenum format);
+
+void GLAPIENTRY
+_mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access);
+void GLAPIENTRY
+_mesa_MakeImageHandleNonResidentARB(GLuint64 handle);
+
+GLboolean GLAPIENTRY
+_mesa_IsTextureHandleResidentARB(GLuint64 handle);
+GLboolean GLAPIENTRY
+_mesa_IsImageHandleResidentARB(GLuint64 handle);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index 8869b6eb22..a9e7cda17c 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c
@@ -294,6 +294,18 @@ _mesa_Uniform4iv(GLint location, GLsizei count, const GLint * value)
_mesa_uniform(location, count, value, ctx, ctx->_Shader->ActiveProgram, GLSL_TYPE_INT, 4);
}
+void GLAPIENTRY
+_mesa_UniformHandleui64ARB(GLint location, GLuint64 value)
+{
+}
+
+void GLAPIENTRY
+_mesa_UniformHandleui64vARB(GLint location, GLsizei count,
+ const GLuint64 *value)
+{
+}
+
+
/** Same as above with direct state access **/
void GLAPIENTRY
_mesa_ProgramUniform1f(GLuint program, GLint location, GLfloat v0)
@@ -485,6 +497,18 @@ _mesa_ProgramUniform4iv(GLuint program, GLint location, GLsizei count,
_mesa_uniform(location, count, value, ctx, shProg, GLSL_TYPE_INT, 4);
}
+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64ARB(GLuint program, GLint location,
+ GLuint64 value)
+{
+}
+
+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64vARB(GLuint program, GLint location,
+ GLsizei count, const GLuint64 *values)
+{
+}
+
/** OpenGL 3.0 GLuint-valued functions **/
void GLAPIENTRY
diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h
index 21d857107d..553e8717ba 100644
--- a/src/mesa/main/uniforms.h
+++ b/src/mesa/main/uniforms.h
@@ -113,6 +113,18 @@ _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
const GLfloat *value);
void GLAPIENTRY
+_mesa_UniformHandleui64ARB(GLint location, GLuint64 value);
+void GLAPIENTRY
+_mesa_UniformHandleui64vARB(GLint location, GLsizei count,
+ const GLuint64 *value);
+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64ARB(GLuint program, GLint location,
+ GLuint64 value);
+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64vARB(GLuint program, GLint location,
+ GLsizei count, const GLuint64 *values);
+
+void GLAPIENTRY
_mesa_ProgramUniform1f(GLuint program, GLint, GLfloat);
void GLAPIENTRY
_mesa_ProgramUniform2f(GLuint program, GLint, GLfloat, GLfloat);
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
index 0eb8e623dc..fcb53d3986 100644
--- a/src/mesa/main/varray.c
+++ b/src/mesa/main/varray.c
@@ -1353,6 +1353,11 @@ _mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
}
}
+void GLAPIENTRY
+_mesa_GetVertexAttribLui64vARB(GLuint index, GLenum pname, GLuint64EXT *params)
+{
+}
+
/** GL 3.0 */
void GLAPIENTRY
diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h
index 2d184adf8b..00c18b619e 100644
--- a/src/mesa/main/varray.h
+++ b/src/mesa/main/varray.h
@@ -248,6 +248,9 @@ _mesa_GetVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params);
extern void GLAPIENTRY
_mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
+extern void GLAPIENTRY
+_mesa_GetVertexAttribLui64vARB(GLuint index, GLenum pname, GLuint64EXT *params);
+
extern void GLAPIENTRY
_mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params);
diff --git a/src/mesa/main/vtxfmt.c b/src/mesa/main/vtxfmt.c
index 81bf4c589e..d3c83e5eb3 100644
--- a/src/mesa/main/vtxfmt.c
+++ b/src/mesa/main/vtxfmt.c
@@ -217,6 +217,10 @@ install_vtxfmt(struct gl_context *ctx, struct _glapi_table *tab,
SET_VertexAttribL2dv(tab, vfmt->VertexAttribL2dv);
SET_VertexAttribL3dv(tab, vfmt->VertexAttribL3dv);
SET_VertexAttribL4dv(tab, vfmt->VertexAttribL4dv);
+
+ /* GL_ARB_bindless_texture */
+ SET_VertexAttribL1ui64ARB(tab, vfmt->VertexAttribL1ui64ARB);
+ SET_VertexAttribL1ui64vARB(tab, vfmt->VertexAttribL1ui64vARB);
}
}
diff --git a/src/mesa/vbo/vbo_attrib_tmp.h b/src/mesa/vbo/vbo_attrib_tmp.h
index 4e2c874ef3..08b441aafb 100644
--- a/src/mesa/vbo/vbo_attrib_tmp.h
+++ b/src/mesa/vbo/vbo_attrib_tmp.h
@@ -1302,6 +1302,15 @@ TAG(VertexAttribL4dv)(GLuint index, const GLdouble * v)
ERROR(GL_INVALID_VALUE);
}
+static void GLAPIENTRY
+TAG(VertexAttribL1ui64ARB)(GLuint index, GLuint64EXT x)
+{
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL1ui64vARB)(GLuint index, const GLuint64EXT *v)
+{
+}
#undef ATTR1FV
#undef ATTR2FV
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index f08fd4c32c..4db4eef3b6 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -1089,6 +1089,9 @@ vbo_exec_vtxfmt_init(struct vbo_exec_context *exec)
vfmt->VertexAttribL2dv = vbo_VertexAttribL2dv;
vfmt->VertexAttribL3dv = vbo_VertexAttribL3dv;
vfmt->VertexAttribL4dv = vbo_VertexAttribL4dv;
+
+ vfmt->VertexAttribL1ui64ARB = vbo_VertexAttribL1ui64ARB;
+ vfmt->VertexAttribL1ui64vARB = vbo_VertexAttribL1ui64vARB;
}
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index ad54c3b38b..a0735f63f2 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -1490,6 +1490,9 @@ _save_vtxfmt_init(struct gl_context *ctx)
vfmt->VertexAttribL3dv = _save_VertexAttribL3dv;
vfmt->VertexAttribL4dv = _save_VertexAttribL4dv;
+ vfmt->VertexAttribL1ui64ARB = _save_VertexAttribL1ui64ARB;
+ vfmt->VertexAttribL1ui64vARB = _save_VertexAttribL1ui64vARB;
+
*/
vfmt->CallList = _save_CallList;
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
Samuel Pitoiset
2017-05-23 11:54:56 UTC
Permalink
Post by Nicolai Hähnle
Post by Samuel Pitoiset
---
src/mapi/glapi/gen/ARB_bindless_texture.xml | 100
++++++++++++++++++++++++++++
src/mapi/glapi/gen/Makefile.am | 1 +
src/mapi/glapi/gen/gl_API.xml | 4 +-
src/mapi/glapi/gen/gl_genexec.py | 1 +
src/mesa/Makefile.sources | 2 +
src/mesa/main/api_loopback.c | 14 ++++
src/mesa/main/api_loopback.h | 6 ++
src/mesa/main/dd.h | 2 +
src/mesa/main/tests/dispatch_sanity.cpp | 18 +++++
src/mesa/main/texturebindless.c | 85
+++++++++++++++++++++++
src/mesa/main/texturebindless.h | 68 +++++++++++++++++++
src/mesa/main/uniforms.c | 24 +++++++
src/mesa/main/uniforms.h | 12 ++++
src/mesa/main/varray.c | 5 ++
src/mesa/main/varray.h | 3 +
src/mesa/main/vtxfmt.c | 4 ++
src/mesa/vbo/vbo_attrib_tmp.h | 9 +++
src/mesa/vbo/vbo_exec_api.c | 3 +
src/mesa/vbo/vbo_save_api.c | 3 +
19 files changed, 363 insertions(+), 1 deletion(-)
create mode 100644 src/mapi/glapi/gen/ARB_bindless_texture.xml
create mode 100644 src/mesa/main/texturebindless.c
create mode 100644 src/mesa/main/texturebindless.h
diff --git a/src/mapi/glapi/gen/ARB_bindless_texture.xml
b/src/mapi/glapi/gen/ARB_bindless_texture.xml
new file mode 100644
index 0000000000..bfad45651c
--- /dev/null
+++ b/src/mapi/glapi/gen/ARB_bindless_texture.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_ARB_bindless_texture" number="152">
+
+ <enum name="UNSIGNED_INT64_ARB" value="0x140F" />
+ <type name="uint64EXT" unsigned="true" size="8"/>
+
+ <function name="GetTextureHandleARB" offset="assign">
What's the offset="assign"?
It's a relic from previous rebases, it's useless, I will drop it.
Post by Nicolai Hähnle
Cheers,
Nicolai
Post by Samuel Pitoiset
+ <return type="GLuint64"/>
+ <param name="texture" type="GLuint" />
+ </function>
+
+ <function name="GetTextureSamplerHandleARB" offset="assign">
+ <return type="GLuint64"/>
+ <param name="texture" type="GLuint" />
+ <param name="sampler" type="GLuint" />
+ </function>
+
+ <function name="MakeTextureHandleResidentARB" offset="assign">
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="MakeTextureHandleNonResidentARB" offset="assign">
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="GetImageHandleARB" offset="assign">
+ <return type="GLuint64"/>
+ <param name="texture" type="GLuint" />
+ <param name="level" type="GLint" />
+ <param name="layered" type="GLboolean" />
+ <param name="layer" type="GLint" />
+ <param name="format" type="GLenum" />
+ </function>
+
+ <function name="MakeImageHandleResidentARB" offset="assign">
+ <param name="handle" type="GLuint64" />
+ <param name="access" type="GLenum" />
+ </function>
+
+ <function name="MakeImageHandleNonResidentARB" offset="assign">
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="UniformHandleui64ARB" offset="assign">
+ <param name="location" type="GLint" />
+ <param name="value" type="GLuint64" />
+ </function>
+
+ <function name="UniformHandleui64vARB" offset="assign">
+ <param name="location" type="GLint" />
+ <param name="count" type="GLsizei" />
+ <param name="value" type="const GLuint64 *" />
+ </function>
+
+ <function name="ProgramUniformHandleui64ARB" offset="assign">
+ <param name="program" type="GLuint" />
+ <param name="location" type="GLint" />
+ <param name="value" type="GLuint64" />
+ </function>
+
+ <function name="ProgramUniformHandleui64vARB" offset="assign">
+ <param name="program" type="GLuint" />
+ <param name="location" type="GLint" />
+ <param name="count" type="GLsizei" />
+ <param name="value" type="const GLuint64 *" />
+ </function>
+
+ <function name="IsTextureHandleResidentARB" offset="assign">
+ <return type="GLboolean"/>
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="IsImageHandleResidentARB" offset="assign">
+ <return type="GLboolean"/>
+ <param name="handle" type="GLuint64" />
+ </function>
+
+ <function name="VertexAttribL1ui64ARB" offset="assign"
exec="dynamic">
+ <param name="index" type="GLuint" />
+ <param name="x" type="GLuint64EXT" />
+ </function>
+
+ <function name="VertexAttribL1ui64vARB" offset="assign"
exec="dynamic">
+ <param name="index" type="GLuint" />
+ <param name="v" type="const GLuint64EXT *" />
+ </function>
+
+ <function name="GetVertexAttribLui64vARB">
+ <param name="index" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="params" type="GLuint64EXT *" />
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mapi/glapi/gen/Makefile.am
b/src/mapi/glapi/gen/Makefile.am
index ecd1c71175..80f9139e5d 100644
--- a/src/mapi/glapi/gen/Makefile.am
+++ b/src/mapi/glapi/gen/Makefile.am
@@ -119,6 +119,7 @@ API_XML = \
gl_and_glX_API.xml \
ARB_base_instance.xml \
ARB_blend_func_extended.xml \
+ ARB_bindless_texture.xml \
ARB_clear_buffer_object.xml \
ARB_clear_texture.xml \
ARB_clip_control.xml \
diff --git a/src/mapi/glapi/gen/gl_API.xml
b/src/mapi/glapi/gen/gl_API.xml
index 762fb5a676..278fe14bb6 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -8284,7 +8284,9 @@
<enum name="QUERY_BUFFER_BARRIER_BIT" value="0x00008000"/>
</category>
-<!-- ARB extensions 149 - 152 -->
+<!-- ARB extensions 149 - 151 -->
+
+<xi:include href="ARB_bindless_texture.xml"
xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="ARB_compute_variable_group_size.xml"
xmlns:xi="http://www.w3.org/2001/XInclude"/>
diff --git a/src/mapi/glapi/gen/gl_genexec.py
b/src/mapi/glapi/gen/gl_genexec.py
index 37b1cc6be0..57e155bd1f 100644
--- a/src/mapi/glapi/gen/gl_genexec.py
+++ b/src/mapi/glapi/gen/gl_genexec.py
@@ -113,6 +113,7 @@ header = """/**
#include "main/texstate.h"
#include "main/texstorage.h"
#include "main/barrier.h"
+#include "main/texturebindless.h"
#include "main/textureview.h"
#include "main/transformfeedback.h"
#include "main/mtypes.h"
diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources
index 8a65fbe663..b80882fb8d 100644
--- a/src/mesa/Makefile.sources
+++ b/src/mesa/Makefile.sources
@@ -240,6 +240,8 @@ MAIN_FILES = \
main/texstorage.h \
main/texstore.c \
main/texstore.h \
+ main/texturebindless.c \
+ main/texturebindless.h \
main/textureview.c \
main/textureview.h \
main/transformfeedback.c \
diff --git a/src/mesa/main/api_loopback.c b/src/mesa/main/api_loopback.c
index 59b59d3a9e..36e5194b93 100644
--- a/src/mesa/main/api_loopback.c
+++ b/src/mesa/main/api_loopback.c
@@ -1529,6 +1529,16 @@ _mesa_VertexAttribL1dv(GLuint index, const GLdouble *v)
}
void GLAPIENTRY
+_mesa_VertexAttribL1ui64ARB(GLuint index, GLuint64EXT x)
+{
+}
+
+void GLAPIENTRY
+_mesa_VertexAttribL1ui64vARB(GLuint index, const GLuint64EXT *v)
+{
+}
+
+void GLAPIENTRY
_mesa_VertexAttribL2dv(GLuint index, const GLdouble *v)
{
ATTRIB2_D(index, v[0], v[1]);
@@ -1789,5 +1799,9 @@ _mesa_loopback_init_api_table(const struct gl_context *ctx,
SET_VertexAttribL2dv(dest, _mesa_VertexAttribL2dv);
SET_VertexAttribL3dv(dest, _mesa_VertexAttribL3dv);
SET_VertexAttribL4dv(dest, _mesa_VertexAttribL4dv);
+
+ /* GL_ARB_bindless_texture */
+ SET_VertexAttribL1ui64ARB(dest, _mesa_VertexAttribL1ui64ARB);
+ SET_VertexAttribL1ui64vARB(dest, _mesa_VertexAttribL1ui64vARB);
}
}
diff --git a/src/mesa/main/api_loopback.h b/src/mesa/main/api_loopback.h
index 026bfd68e1..c1e7b24f09 100644
--- a/src/mesa/main/api_loopback.h
+++ b/src/mesa/main/api_loopback.h
@@ -481,4 +481,10 @@ void GLAPIENTRY
_mesa_VertexAttribL3dv(GLuint index, const GLdouble *v);
void GLAPIENTRY
_mesa_VertexAttribL4dv(GLuint index, const GLdouble *v);
+
+void GLAPIENTRY
+_mesa_VertexAttribL1ui64ARB(GLuint index, GLuint64EXT x);
+void GLAPIENTRY
+_mesa_VertexAttribL1ui64vARB(GLuint index, const GLuint64EXT *v);
+
#endif /* API_LOOPBACK_H */
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 3f3102546d..a9ca43d69e 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -1225,6 +1225,8 @@ typedef struct {
void (GLAPIENTRYP VertexAttribL3dv)( GLuint index, const GLdouble *v);
void (GLAPIENTRYP VertexAttribL4dv)( GLuint index, const GLdouble *v);
+ void (GLAPIENTRYP VertexAttribL1ui64ARB)( GLuint index,
GLuint64EXT x);
+ void (GLAPIENTRYP VertexAttribL1ui64vARB)( GLuint index, const GLuint64EXT *v);
} GLvertexformat;
diff --git a/src/mesa/main/tests/dispatch_sanity.cpp
b/src/mesa/main/tests/dispatch_sanity.cpp
index b33043ed28..47d0aa63bf 100644
--- a/src/mesa/main/tests/dispatch_sanity.cpp
+++ b/src/mesa/main/tests/dispatch_sanity.cpp
@@ -2374,6 +2374,24 @@ const struct function
gles2_functions_possible[] = {
/* GL_KHR_blend_equation_advanced */
{ "glBlendBarrierKHR", 20, -1 },
+ /* GL_ARB_bindless_texture */
+ { "glGetTextureHandleARB", 40, -1 },
+ { "glGetTextureSamplerHandleARB", 40, -1 },
+ { "glMakeTextureHandleResidentARB", 40, -1 },
+ { "glMakeTextureHandleNonResidentARB", 40, -1 },
+ { "glIsTextureHandleResidentARB", 40, -1 },
+ { "glGetImageHandleARB", 40, -1 },
+ { "glMakeImageHandleResidentARB", 40, -1 },
+ { "glMakeImageHandleNonResidentARB", 40, -1 },
+ { "glIsImageHandleResidentARB", 40, -1 },
+ { "glUniformHandleui64ARB", 40, -1 },
+ { "glUniformHandleui64vARB", 40, -1 },
+ { "glProgramUniformHandleui64ARB", 40, -1 },
+ { "glProgramUniformHandleui64vARB", 40, -1 },
+ { "glVertexAttribL1ui64ARB", 40, -1 },
+ { "glVertexAttribL1ui64vARB", 40, -1 },
+ { "glGetVertexAttribLui64vARB", 40, -1 },
+
{ NULL, 0, -1 }
};
diff --git a/src/mesa/main/texturebindless.c
b/src/mesa/main/texturebindless.c
new file mode 100644
index 0000000000..4d9c22d428
--- /dev/null
+++ b/src/mesa/main/texturebindless.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2017 Valve Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "enums.h"
+#include "imports.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "texobj.h"
+#include "texturebindless.h"
+
+#include "util/set.h"
+#include "util/hash_table.h"
+
+GLuint64 GLAPIENTRY
+_mesa_GetTextureHandleARB(GLuint texture)
+{
+ return 0;
+}
+
+GLuint64 GLAPIENTRY
+_mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler)
+{
+ return 0;
+}
+
+void GLAPIENTRY
+_mesa_MakeTextureHandleResidentARB(GLuint64 handle)
+{
+}
+
+void GLAPIENTRY
+_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle)
+{
+}
+
+GLuint64 GLAPIENTRY
+_mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
+ GLint layer, GLenum format)
+{
+ return 0;
+}
+
+void GLAPIENTRY
+_mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access)
+{
+}
+
+void GLAPIENTRY
+_mesa_MakeImageHandleNonResidentARB(GLuint64 handle)
+{
+}
+
+GLboolean GLAPIENTRY
+_mesa_IsTextureHandleResidentARB(GLuint64 handle)
+{
+ return GL_FALSE;
+}
+
+GLboolean GLAPIENTRY
+_mesa_IsImageHandleResidentARB(GLuint64 handle)
+{
+ return GL_FALSE;
+}
diff --git a/src/mesa/main/texturebindless.h
b/src/mesa/main/texturebindless.h
new file mode 100644
index 0000000000..88b84ce275
--- /dev/null
+++ b/src/mesa/main/texturebindless.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2017 Valve Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef TEXTUREBINDLESS_H
+#define TEXTUREBINDLESS_H
+
+#include "mtypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name API functions
+ */
+
+GLuint64 GLAPIENTRY
+_mesa_GetTextureHandleARB(GLuint texture);
+GLuint64 GLAPIENTRY
+_mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler);
+
+void GLAPIENTRY
+_mesa_MakeTextureHandleResidentARB(GLuint64 handle);
+void GLAPIENTRY
+_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle);
+
+GLuint64 GLAPIENTRY
+_mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
+ GLint layer, GLenum format);
+
+void GLAPIENTRY
+_mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access);
+void GLAPIENTRY
+_mesa_MakeImageHandleNonResidentARB(GLuint64 handle);
+
+GLboolean GLAPIENTRY
+_mesa_IsTextureHandleResidentARB(GLuint64 handle);
+GLboolean GLAPIENTRY
+_mesa_IsImageHandleResidentARB(GLuint64 handle);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index 8869b6eb22..a9e7cda17c 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c
@@ -294,6 +294,18 @@ _mesa_Uniform4iv(GLint location, GLsizei count, const GLint * value)
_mesa_uniform(location, count, value, ctx,
ctx->_Shader->ActiveProgram, GLSL_TYPE_INT, 4);
}
+void GLAPIENTRY
+_mesa_UniformHandleui64ARB(GLint location, GLuint64 value)
+{
+}
+
+void GLAPIENTRY
+_mesa_UniformHandleui64vARB(GLint location, GLsizei count,
+ const GLuint64 *value)
+{
+}
+
+
/** Same as above with direct state access **/
void GLAPIENTRY
_mesa_ProgramUniform1f(GLuint program, GLint location, GLfloat v0)
@@ -485,6 +497,18 @@ _mesa_ProgramUniform4iv(GLuint program, GLint
location, GLsizei count,
_mesa_uniform(location, count, value, ctx, shProg, GLSL_TYPE_INT, 4);
}
+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64ARB(GLuint program, GLint location,
+ GLuint64 value)
+{
+}
+
+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64vARB(GLuint program, GLint location,
+ GLsizei count, const GLuint64 *values)
+{
+}
+
/** OpenGL 3.0 GLuint-valued functions **/
void GLAPIENTRY
diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h
index 21d857107d..553e8717ba 100644
--- a/src/mesa/main/uniforms.h
+++ b/src/mesa/main/uniforms.h
@@ -113,6 +113,18 @@ _mesa_UniformMatrix4x3fv(GLint location, GLsizei
count, GLboolean transpose,
const GLfloat *value);
void GLAPIENTRY
+_mesa_UniformHandleui64ARB(GLint location, GLuint64 value);
+void GLAPIENTRY
+_mesa_UniformHandleui64vARB(GLint location, GLsizei count,
+ const GLuint64 *value);
+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64ARB(GLuint program, GLint location,
+ GLuint64 value);
+void GLAPIENTRY
+_mesa_ProgramUniformHandleui64vARB(GLuint program, GLint location,
+ GLsizei count, const GLuint64 *values);
+
+void GLAPIENTRY
_mesa_ProgramUniform1f(GLuint program, GLint, GLfloat);
void GLAPIENTRY
_mesa_ProgramUniform2f(GLuint program, GLint, GLfloat, GLfloat);
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
index 0eb8e623dc..fcb53d3986 100644
--- a/src/mesa/main/varray.c
+++ b/src/mesa/main/varray.c
@@ -1353,6 +1353,11 @@ _mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
}
}
+void GLAPIENTRY
+_mesa_GetVertexAttribLui64vARB(GLuint index, GLenum pname,
GLuint64EXT *params)
+{
+}
+
/** GL 3.0 */
void GLAPIENTRY
diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h
index 2d184adf8b..00c18b619e 100644
--- a/src/mesa/main/varray.h
+++ b/src/mesa/main/varray.h
@@ -248,6 +248,9 @@ _mesa_GetVertexAttribLdv(GLuint index, GLenum
pname, GLdouble *params);
extern void GLAPIENTRY
_mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
+extern void GLAPIENTRY
+_mesa_GetVertexAttribLui64vARB(GLuint index, GLenum pname,
GLuint64EXT *params);
+
extern void GLAPIENTRY
_mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params);
diff --git a/src/mesa/main/vtxfmt.c b/src/mesa/main/vtxfmt.c
index 81bf4c589e..d3c83e5eb3 100644
--- a/src/mesa/main/vtxfmt.c
+++ b/src/mesa/main/vtxfmt.c
@@ -217,6 +217,10 @@ install_vtxfmt(struct gl_context *ctx, struct _glapi_table *tab,
SET_VertexAttribL2dv(tab, vfmt->VertexAttribL2dv);
SET_VertexAttribL3dv(tab, vfmt->VertexAttribL3dv);
SET_VertexAttribL4dv(tab, vfmt->VertexAttribL4dv);
+
+ /* GL_ARB_bindless_texture */
+ SET_VertexAttribL1ui64ARB(tab, vfmt->VertexAttribL1ui64ARB);
+ SET_VertexAttribL1ui64vARB(tab, vfmt->VertexAttribL1ui64vARB);
}
}
diff --git a/src/mesa/vbo/vbo_attrib_tmp.h
b/src/mesa/vbo/vbo_attrib_tmp.h
index 4e2c874ef3..08b441aafb 100644
--- a/src/mesa/vbo/vbo_attrib_tmp.h
+++ b/src/mesa/vbo/vbo_attrib_tmp.h
@@ -1302,6 +1302,15 @@ TAG(VertexAttribL4dv)(GLuint index, const GLdouble * v)
ERROR(GL_INVALID_VALUE);
}
+static void GLAPIENTRY
+TAG(VertexAttribL1ui64ARB)(GLuint index, GLuint64EXT x)
+{
+}
+
+static void GLAPIENTRY
+TAG(VertexAttribL1ui64vARB)(GLuint index, const GLuint64EXT *v)
+{
+}
#undef ATTR1FV
#undef ATTR2FV
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index f08fd4c32c..4db4eef3b6 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -1089,6 +1089,9 @@ vbo_exec_vtxfmt_init(struct vbo_exec_context *exec)
vfmt->VertexAttribL2dv = vbo_VertexAttribL2dv;
vfmt->VertexAttribL3dv = vbo_VertexAttribL3dv;
vfmt->VertexAttribL4dv = vbo_VertexAttribL4dv;
+
+ vfmt->VertexAttribL1ui64ARB = vbo_VertexAttribL1ui64ARB;
+ vfmt->VertexAttribL1ui64vARB = vbo_VertexAttribL1ui64vARB;
}
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index ad54c3b38b..a0735f63f2 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -1490,6 +1490,9 @@ _save_vtxfmt_init(struct gl_context *ctx)
vfmt->VertexAttribL3dv = _save_VertexAttribL3dv;
vfmt->VertexAttribL4dv = _save_VertexAttribL4dv;
+ vfmt->VertexAttribL1ui64ARB = _save_VertexAttribL1ui64ARB;
+ vfmt->VertexAttribL1ui64vARB = _save_VertexAttribL1ui64vARB;
+
*/
vfmt->CallList = _save_CallList;
Samuel Pitoiset
2017-05-19 16:52:09 UTC
Permalink
Bindless sampler/image handles are represented using 64-bit
unsigned integers.

The ARB_bindless_texture spec says:

"The error INVALID_OPERATION is generated by UniformHandleui64{v}ARB
if the sampler or image uniform being updated has the "bound_sampler"
or "bound_image" layout qualifier"."

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/compiler/glsl/ir_uniform.h | 6 ++++
src/compiler/glsl/link_uniforms.cpp | 1 +
src/compiler/glsl/shader_cache.cpp | 2 ++
src/mesa/main/uniform_query.cpp | 64 +++++++++++++++++++++++++++++++++++++
src/mesa/main/uniforms.c | 15 +++++++++
src/mesa/main/uniforms.h | 4 +++
6 files changed, 92 insertions(+)

diff --git a/src/compiler/glsl/ir_uniform.h b/src/compiler/glsl/ir_uniform.h
index b6aec7fc4a..9841df8cde 100644
--- a/src/compiler/glsl/ir_uniform.h
+++ b/src/compiler/glsl/ir_uniform.h
@@ -201,6 +201,12 @@ struct gl_uniform_storage {
* top-level shader storage block member. (GL_TOP_LEVEL_ARRAY_STRIDE).
*/
unsigned top_level_array_stride;
+
+ /**
+ * Whether this uniform variable has the bindless_sampler or bindless_image
+ * layout qualifier as specified by ARB_bindless_texture.
+ */
+ bool is_bindless;
};

#ifdef __cplusplus
diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp
index b11739ce78..7c3ca75416 100644
--- a/src/compiler/glsl/link_uniforms.cpp
+++ b/src/compiler/glsl/link_uniforms.cpp
@@ -754,6 +754,7 @@ private:

this->uniforms[id].is_shader_storage =
current_var->is_in_shader_storage_block();
+ this->uniforms[id].is_bindless = current_var->data.bindless;

/* Do not assign storage if the uniform is a builtin or buffer object */
if (!this->uniforms[id].builtin &&
diff --git a/src/compiler/glsl/shader_cache.cpp b/src/compiler/glsl/shader_cache.cpp
index 800d3a2913..2bfddebcd7 100644
--- a/src/compiler/glsl/shader_cache.cpp
+++ b/src/compiler/glsl/shader_cache.cpp
@@ -578,6 +578,7 @@ write_uniforms(struct blob *metadata, struct gl_shader_program *prog)
blob_write_uint32(metadata, prog->data->UniformStorage[i].is_shader_storage);
blob_write_uint32(metadata, prog->data->UniformStorage[i].matrix_stride);
blob_write_uint32(metadata, prog->data->UniformStorage[i].row_major);
+ blob_write_uint32(metadata, prog->data->UniformStorage[i].is_bindless);
blob_write_uint32(metadata,
prog->data->UniformStorage[i].num_compatible_subroutines);
blob_write_uint32(metadata,
@@ -642,6 +643,7 @@ read_uniforms(struct blob_reader *metadata, struct gl_shader_program *prog)
uniforms[i].is_shader_storage = blob_read_uint32(metadata);
uniforms[i].matrix_stride = blob_read_uint32(metadata);
uniforms[i].row_major = blob_read_uint32(metadata);
+ uniforms[i].is_bindless = blob_read_uint32(metadata);
uniforms[i].num_compatible_subroutines = blob_read_uint32(metadata);
uniforms[i].top_level_array_size = blob_read_uint32(metadata);
uniforms[i].top_level_array_stride = blob_read_uint32(metadata);
diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp
index 16e3fe3d52..cc145f29e9 100644
--- a/src/mesa/main/uniform_query.cpp
+++ b/src/mesa/main/uniform_query.cpp
@@ -1173,6 +1173,70 @@ _mesa_uniform_matrix(GLint location, GLsizei count,
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
}

+/**
+ * Called via glUniformHandleui64*ARB() functions.
+ */
+extern "C" void
+_mesa_uniform_handle(GLint location, GLsizei count, const GLvoid *values,
+ struct gl_context *ctx, struct gl_shader_program *shProg)
+{
+ unsigned offset;
+ struct gl_uniform_storage *const uni =
+ validate_uniform_parameters(location, count, &offset,
+ ctx, shProg, "glUniformHandleui64*ARB");
+ if (uni == NULL)
+ return;
+
+ if (!uni->is_bindless) {
+ /* From section "Errors" of the ARB_bindless_texture spec:
+ *
+ * "The error INVALID_OPERATION is generated by
+ * UniformHandleui64{v}ARB if the sampler or image uniform being
+ * updated has the "bound_sampler" or "bound_image" layout qualifier."
+ *
+ * From section 4.4.6 of the ARB_bindless_texture spec:
+ *
+ * "In the absence of these qualifiers, sampler and image uniforms are
+ * considered "bound". Additionally, if GL_ARB_bindless_texture is not
+ * enabled, these uniforms are considered "bound"."
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUniformHandleui64*ARB(non-bindless sampler/image uniform)");
+ return;
+ }
+
+ const unsigned components = uni->type->vector_elements;
+ const int size_mul = 2;
+
+ if (unlikely(ctx->_Shader->Flags & GLSL_UNIFORMS)) {
+ log_uniform(values, GLSL_TYPE_UINT64, components, 1, count,
+ false, shProg, location, uni);
+ }
+
+ /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says:
+ *
+ * "When loading N elements starting at an arbitrary position k in a
+ * uniform declared as an array, elements k through k + N - 1 in the
+ * array will be replaced with the new values. Values for any array
+ * element that exceeds the highest array element index used, as
+ * reported by GetActiveUniform, will be ignored by the GL."
+ *
+ * Clamp 'count' to a valid value. Note that for non-arrays a count > 1
+ * will have already generated an error.
+ */
+ if (uni->array_elements != 0) {
+ count = MIN2(count, (int) (uni->array_elements - offset));
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
+
+ /* Store the data in the "actual type" backing storage for the uniform.
+ */
+ memcpy(&uni->storage[size_mul * components * offset], values,
+ sizeof(uni->storage[0]) * components * count * size_mul);
+
+ _mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
+}

extern "C" bool
_mesa_sampler_uniforms_are_valid(const struct gl_shader_program *shProg,
diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index a9e7cda17c..67c238e4f3 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c
@@ -297,12 +297,17 @@ _mesa_Uniform4iv(GLint location, GLsizei count, const GLint * value)
void GLAPIENTRY
_mesa_UniformHandleui64ARB(GLint location, GLuint64 value)
{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_uniform_handle(location, 1, &value, ctx, ctx->_Shader->ActiveProgram);
}

void GLAPIENTRY
_mesa_UniformHandleui64vARB(GLint location, GLsizei count,
const GLuint64 *value)
{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_uniform_handle(location, count, value, ctx,
+ ctx->_Shader->ActiveProgram);
}


@@ -501,12 +506,22 @@ void GLAPIENTRY
_mesa_ProgramUniformHandleui64ARB(GLuint program, GLint location,
GLuint64 value)
{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program,
+ "glProgramUniformHandleui64ARB");
+ _mesa_uniform_handle(location, 1, &value, ctx, shProg);
}

void GLAPIENTRY
_mesa_ProgramUniformHandleui64vARB(GLuint program, GLint location,
GLsizei count, const GLuint64 *values)
{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program,
+ "glProgramUniformHandleui64vARB");
+ _mesa_uniform_handle(location, count, values, ctx, shProg);
}


diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h
index 553e8717ba..bd42b4f036 100644
--- a/src/mesa/main/uniforms.h
+++ b/src/mesa/main/uniforms.h
@@ -453,6 +453,10 @@ _mesa_uniform_matrix(GLint location, GLsizei count,
GLuint cols, GLuint rows, enum glsl_base_type basicType);

void
+_mesa_uniform_handle(GLint location, GLsizei count, const GLvoid *values,
+ struct gl_context *, struct gl_shader_program *);
+
+void
_mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
GLsizei bufSize, enum glsl_base_type returnType,
GLvoid *paramsOut);
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:07 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/main/context.c | 3 +
src/mesa/main/dd.h | 17 +
src/mesa/main/mtypes.h | 34 ++
src/mesa/main/samplerobj.c | 6 +
src/mesa/main/shared.c | 12 +
src/mesa/main/texobj.c | 12 +
src/mesa/main/texturebindless.c | 827 +++++++++++++++++++++++++++++++++++++++-
src/mesa/main/texturebindless.h | 28 ++
8 files changed, 934 insertions(+), 5 deletions(-)

diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 3570f94f5a..5321886a95 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -133,6 +133,7 @@
#include "varray.h"
#include "version.h"
#include "viewport.h"
+#include "texturebindless.h"
#include "program/program.h"
#include "math/m_matrix.h"
#include "main/dispatch.h" /* for _gloffset_COUNT */
@@ -855,6 +856,7 @@ init_attrib_groups(struct gl_context *ctx)
_mesa_init_transform_feedback( ctx );
_mesa_init_varray( ctx );
_mesa_init_viewport( ctx );
+ _mesa_init_resident_handles( ctx );

if (!_mesa_init_texture( ctx ))
return GL_FALSE;
@@ -1339,6 +1341,7 @@ _mesa_free_context_data( struct gl_context *ctx )
_mesa_free_transform_feedback(ctx);
_mesa_free_performance_monitors(ctx);
_mesa_free_performance_queries(ctx);
+ _mesa_free_resident_handles(ctx);

_mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
_mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index a9ca43d69e..d830f5184d 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -1050,6 +1050,23 @@ struct dd_function_table {
GLintptr offset, GLsizeiptr size,
GLboolean commit);
/*@}*/
+
+ /**
+ * \name GL_ARB_bindless_texture interface
+ */
+ /*@{*/
+ GLuint64 (*NewTextureHandle)(struct gl_context *ctx,
+ struct gl_texture_object *texObj,
+ struct gl_sampler_object *sampObj);
+ void (*DeleteTextureHandle)(struct gl_context *ctx, GLuint64 handle);
+ void (*MakeTextureHandleResident)(struct gl_context *ctx, GLuint64 handle,
+ bool resident);
+ GLuint64 (*NewImageHandle)(struct gl_context *ctx,
+ struct gl_image_unit *imgObj);
+ void (*DeleteImageHandle)(struct gl_context *ctx, GLuint64 handle);
+ void (*MakeImageHandleResident)(struct gl_context *ctx, GLuint64 handle,
+ GLenum access, bool resident);
+ /*@}*/
};


diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index efc6920254..70865b373d 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -987,6 +987,9 @@ struct gl_sampler_object
GLenum CompareFunc; /**< GL_ARB_shadow */
GLenum sRGBDecode; /**< GL_DECODE_EXT or GL_SKIP_DECODE_EXT */
GLboolean CubeMapSeamless; /**< GL_AMD_seamless_cubemap_per_texture */
+ bool HandleAllocated; /**< GL_ARB_bindless_texture */
+
+ struct hash_table *Handles;
};


@@ -1034,6 +1037,8 @@ struct gl_texture_object
GLuint NumLevels; /**< GL_ARB_texture_view */
GLuint NumLayers; /**< GL_ARB_texture_view */

+ GLboolean HandleAllocated; /**< GL_ARB_bindless_texture */
+
/** Actual texture images, indexed by [cube face] and [mipmap level] */
struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS];

@@ -1051,6 +1056,10 @@ struct gl_texture_object

/** GL_ARB_shader_image_load_store */
GLenum ImageFormatCompatibilityType;
+
+ /** GL_ARB_bindless_texture */
+ struct hash_table *SamplerHandles;
+ struct hash_table *ImageHandles;
};


@@ -1390,6 +1399,7 @@ struct gl_buffer_object
GLboolean Written; /**< Ever written to? (for debugging) */
GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
GLboolean Immutable; /**< GL_ARB_buffer_storage */
+ GLboolean HandleAllocated; /**< GL_ARB_bindless_texture */
gl_buffer_usage UsageHistory; /**< How has this buffer been used so far? */

/** Counters used for buffer usage warnings */
@@ -3203,6 +3213,11 @@ struct gl_shared_state
/** GL_ARB_sampler_objects */
struct _mesa_HashTable *SamplerObjects;

+ /* GL_ARB_bindless_texture */
+ struct hash_table *TextureHandles;
+ struct hash_table *ImageHandles;
+ mtx_t HandlesMutex; /**< For texture/image handles safety */
+
/**
* Some context in this share group was affected by a GPU reset
*
@@ -4488,6 +4503,17 @@ struct gl_subroutine_index_binding
GLuint *IndexPtr;
};

+struct gl_texture_handle_object
+{
+ struct gl_texture_object *texObj;
+ struct gl_sampler_object *sampObj;
+};
+
+struct gl_image_handle_object
+{
+ struct gl_image_unit imgObj;
+};
+
/**
* Mesa rendering context.
*
@@ -4842,6 +4868,14 @@ struct gl_context
GLfloat PrimitiveBoundingBox[8];

struct disk_cache *Cache;
+
+ /**
+ * \name GL_ARB_bindless_texture
+ */
+ /*@{*/
+ struct hash_table *ResidentTextureHandles;
+ struct hash_table *ResidentImageHandles;
+ /*@}*/
};

/**
diff --git a/src/mesa/main/samplerobj.c b/src/mesa/main/samplerobj.c
index 63beaf1abb..ee15c68b4f 100644
--- a/src/mesa/main/samplerobj.c
+++ b/src/mesa/main/samplerobj.c
@@ -38,6 +38,7 @@
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/samplerobj.h"
+#include "main/texturebindless.h"


struct gl_sampler_object *
@@ -61,6 +62,7 @@ static void
delete_sampler_object(struct gl_context *ctx,
struct gl_sampler_object *sampObj)
{
+ _mesa_delete_sampler_handles(ctx, sampObj);
mtx_destroy(&sampObj->Mutex);
free(sampObj->Label);
free(sampObj);
@@ -132,6 +134,10 @@ _mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name)
sampObj->CompareFunc = GL_LEQUAL;
sampObj->sRGBDecode = GL_DECODE_EXT;
sampObj->CubeMapSeamless = GL_FALSE;
+ sampObj->HandleAllocated = GL_FALSE;
+
+ /* GL_ARB_bindless_texture */
+ _mesa_init_sampler_handles(sampObj);
}

/**
diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c
index 5344812738..b188287a08 100644
--- a/src/mesa/main/shared.c
+++ b/src/mesa/main/shared.c
@@ -84,6 +84,13 @@ _mesa_alloc_shared_state(struct gl_context *ctx)
/* GL_ARB_sampler_objects */
shared->SamplerObjects = _mesa_NewHashTable();

+ /* GL_ARB_bindless_texture */
+ shared->TextureHandles = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ shared->ImageHandles = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ mtx_init(&shared->HandlesMutex, mtx_recursive);
+
/* Allocate the default buffer object */
shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0);

@@ -373,6 +380,11 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared)
_mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx);
_mesa_DeleteHashTable(shared->TexObjects);

+ /* Bindless texture/image handles */
+ _mesa_hash_table_destroy(shared->TextureHandles, NULL);
+ _mesa_hash_table_destroy(shared->ImageHandles, NULL);
+ mtx_destroy(&shared->HandlesMutex);
+
mtx_destroy(&shared->Mutex);
mtx_destroy(&shared->TexMutex);

diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index 868e4eb7a2..13a24f6deb 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -43,6 +43,7 @@
#include "texstate.h"
#include "mtypes.h"
#include "program/prog_instruction.h"
+#include "texturebindless.h"



@@ -311,6 +312,7 @@ _mesa_initialize_texture_object( struct gl_context *ctx,
obj->DepthMode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE;
obj->StencilSampling = false;
obj->Sampler.CubeMapSeamless = GL_FALSE;
+ obj->Sampler.HandleAllocated = GL_FALSE;
obj->Swizzle[0] = GL_RED;
obj->Swizzle[1] = GL_GREEN;
obj->Swizzle[2] = GL_BLUE;
@@ -320,6 +322,9 @@ _mesa_initialize_texture_object( struct gl_context *ctx,
obj->BufferObjectFormat = GL_R8;
obj->_BufferObjectFormat = MESA_FORMAT_R_UNORM8;
obj->ImageFormatCompatibilityType = GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE;
+
+ /* GL_ARB_bindless_texture */
+ _mesa_init_texture_handles(obj);
}


@@ -397,6 +402,9 @@ _mesa_delete_texture_object(struct gl_context *ctx,
}
}

+ /* Delete all texture/image handles. */
+ _mesa_delete_texture_handles(ctx, texObj);
+
_mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL);

/* destroy the mutex -- it may have allocated memory (eg on bsd) */
@@ -1461,6 +1469,10 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
*/
unbind_texobj_from_image_units(ctx, delObj);

+ /* Make all handles that reference this texture object non-resident
+ * in the current context. */
+ _mesa_make_texture_handles_non_resident(ctx, delObj);
+
_mesa_unlock_texture(ctx, delObj);

ctx->NewState |= _NEW_TEXTURE_OBJECT;
diff --git a/src/mesa/main/texturebindless.c b/src/mesa/main/texturebindless.c
index 4d9c22d428..0c6f9c3fc9 100644
--- a/src/mesa/main/texturebindless.c
+++ b/src/mesa/main/texturebindless.c
@@ -29,57 +29,874 @@
#include "mtypes.h"
#include "texobj.h"
#include "texturebindless.h"
+#include "shaderimage.h"
+#include "teximage.h"
+#include "hash.h"

#include "util/set.h"
#include "util/hash_table.h"

+/**
+ * Return the gl_texture_handle_object for a given 64bit handle.
+ */
+static struct gl_texture_handle_object *
+lookup_texture_handle(struct gl_context *ctx, GLuint64 id)
+{
+ struct hash_entry *entry;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(ctx->Shared->TextureHandles, (void *)id);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return entry ? (struct gl_texture_handle_object *)entry->data : NULL;
+}
+
+/**
+ * Return the gl_image_handle_object for a given 64bit handle.
+ */
+static struct gl_image_handle_object *
+lookup_image_handle(struct gl_context *ctx, GLuint64 id)
+{
+ struct hash_entry *entry;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(ctx->Shared->ImageHandles, (void *)id);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return entry ? (struct gl_image_handle_object *)entry->data : NULL;
+}
+
+/**
+ * Delete a texture handle in the shared state.
+ */
+static void
+delete_texture_handle(struct gl_context *ctx, GLuint64 id)
+{
+ struct hash_entry *entry;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(ctx->Shared->TextureHandles, (void *)id);
+ _mesa_hash_table_remove(ctx->Shared->TextureHandles, entry);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+}
+
+/**
+ * Delete an image handle in the shared state.
+ */
+static void
+delete_image_handle(struct gl_context *ctx, GLuint64 id)
+{
+ struct hash_entry *entry;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(ctx->Shared->ImageHandles, (void *)id);
+ _mesa_hash_table_remove(ctx->Shared->ImageHandles, entry);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+}
+
+/**
+ * Return TRUE if the texture handle is resident in the current context.
+ */
+static inline bool
+is_texture_handle_resident(struct gl_context *ctx, GLuint64 handle)
+{
+ return _mesa_hash_table_search(ctx->ResidentTextureHandles,
+ (void *)handle) != NULL;
+}
+
+/**
+ * Return TRUE if the image handle is resident in the current context.
+ */
+static inline bool
+is_image_handle_resident(struct gl_context *ctx, GLuint64 handle)
+{
+ return _mesa_hash_table_search(ctx->ResidentImageHandles,
+ (void *)handle) != NULL;
+}
+
+/**
+ * Set a texture handle resident/non-resident in the current context.
+ */
+static void
+make_texture_handle_resident(struct gl_context *ctx,
+ struct gl_texture_handle_object *handleObj,
+ GLuint64 handle, bool resident)
+{
+ if (resident) {
+ struct gl_sampler_object *sampObj = NULL;
+ struct gl_texture_object *texObj = NULL;
+
+ _mesa_hash_table_insert(ctx->ResidentTextureHandles,
+ (void *)handle, handleObj);
+
+ ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_TRUE);
+
+ /* Reference the texture object (and the separate sampler if needed) to
+ * be sure it won't be deleted until it is not bound anywhere and there
+ * are no handles using the object that are resident in any context. */
+ _mesa_reference_texobj(&texObj, handleObj->texObj);
+ if (handleObj->sampObj)
+ _mesa_reference_sampler_object(ctx, &sampObj, handleObj->sampObj);
+ } else {
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(ctx->ResidentTextureHandles,
+ (void *)handle);
+ _mesa_hash_table_remove(ctx->ResidentTextureHandles, entry);
+
+ ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_FALSE);
+
+ /* Unreference the texture object (and the separate sampler if needed),
+ * if refcount hits zero, the texture and all handles will be deleted. */
+ _mesa_reference_texobj(&handleObj->texObj, NULL);
+ if (handleObj->sampObj)
+ _mesa_reference_sampler_object(ctx, &handleObj->sampObj, NULL);
+ }
+}
+
+/**
+ * Set an image handle resident/non-resident in the current context.
+ */
+static void
+make_image_handle_resident(struct gl_context *ctx,
+ struct gl_image_handle_object *handleObj,
+ GLuint64 handle, GLenum access, bool resident)
+{
+ if (resident) {
+ struct gl_texture_object *texObj = NULL;
+
+ _mesa_hash_table_insert(ctx->ResidentImageHandles,
+ (void *)handle, handleObj);
+
+ ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_TRUE);
+
+ /* Reference the texture object to be sure it won't be deleted until it
+ * is not bound anywhere and there are no handles using the object that
+ * are resident in any context. */
+ _mesa_reference_texobj(&texObj, handleObj->imgObj.TexObj);
+ } else {
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(ctx->ResidentImageHandles,
+ (void *)handle);
+ _mesa_hash_table_remove(ctx->ResidentImageHandles, entry);
+
+ ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_FALSE);
+
+ /* Unreference the texture object, if refcount hits zero, the texture and
+ * all handles will be deleted. */
+ _mesa_reference_texobj(&handleObj->imgObj.TexObj, NULL);
+ }
+}
+
+static GLuint64
+get_texture_handle(struct gl_context *ctx, struct gl_texture_object *texObj,
+ struct gl_sampler_object *sampObj)
+{
+ struct gl_texture_handle_object *handleObj;
+ struct hash_entry *entry;
+ GLuint64 handle;
+
+ handleObj = CALLOC_STRUCT(gl_texture_handle_object);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
+ return 0;
+ }
+
+ handleObj->texObj = texObj;
+ if (&texObj->Sampler != sampObj)
+ handleObj->sampObj = sampObj;
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The handle for each texture or texture/sampler pair is unique; the same
+ * handle will be returned if GetTextureHandleARB is called multiple times
+ * for the same texture or if GetTextureSamplerHandleARB is called multiple
+ * times for the same texture/sampler pair."
+ */
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(texObj->SamplerHandles, handleObj);
+ if (entry) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ return (uint64_t)entry->data;
+ }
+
+ /* Ask the driver for a new handle and store it. */
+ handle = ctx->Driver.NewTextureHandle(ctx, texObj, sampObj);
+ if (!handle) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
+ return 0;
+ }
+
+ _mesa_hash_table_insert(texObj->SamplerHandles, handleObj, (void *)handle);
+
+ if (&texObj->Sampler != sampObj) {
+ _mesa_hash_table_insert(sampObj->Handles, handleObj,
+ (void *)handle);
+ }
+
+ /* When referenced by one or more handles, texture objects are immutable. */
+ texObj->HandleAllocated = true;
+ sampObj->HandleAllocated = true;
+ if (texObj->Target == GL_TEXTURE_BUFFER)
+ texObj->BufferObject->HandleAllocated = true;
+
+ /* Store the handle in the shared state for all contexts. */
+ _mesa_hash_table_insert(ctx->Shared->TextureHandles,
+ (void *)handle, handleObj);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return (GLuint64)handle;
+}
+
+static GLuint64
+get_image_handle(struct gl_context *ctx, struct gl_texture_object *texObj,
+ GLint level, GLboolean layered, GLint layer, GLenum format)
+{
+ struct gl_image_handle_object *handleObj;
+ struct gl_image_unit *imgObj;
+ struct hash_entry *entry;
+ GLuint64 handle;
+
+ handleObj = CALLOC_STRUCT(gl_image_handle_object);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
+ return 0;
+ }
+
+ imgObj = &handleObj->imgObj;
+ imgObj->TexObj = texObj; /* weak reference */
+ imgObj->Level = level;
+ imgObj->Access = GL_READ_WRITE;
+ imgObj->Format = format;
+ imgObj->_ActualFormat = _mesa_get_shader_image_format(format);
+
+ if (_mesa_tex_target_is_layered(texObj->Target)) {
+ imgObj->Layered = layered;
+ imgObj->Layer = layer;
+ imgObj->_Layer = (imgObj->Layered ? 0 : imgObj->Layer);
+ } else {
+ imgObj->Layered = GL_FALSE;
+ imgObj->Layer = 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The handle returned for each combination of <texture>, <level>,
+ * <layered>, <layer>, and <format> is unique; the same handle will be
+ * returned if GetImageHandleARB is called multiple times with the same
+ * parameters."
+ */
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(texObj->ImageHandles, handleObj);
+ if (entry) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ return (uint64_t)entry->data;
+ }
+
+ /* Ask the driver for a new handle and store it. */
+ handle = ctx->Driver.NewImageHandle(ctx, &handleObj->imgObj);
+ if (!handle) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
+ return 0;
+ }
+
+ _mesa_hash_table_insert(texObj->ImageHandles, handleObj, (void *)handle);
+
+ /* When referenced by one or more handles, texture objects are immutable. */
+ texObj->HandleAllocated = true;
+ if (texObj->Target == GL_TEXTURE_BUFFER)
+ texObj->BufferObject->HandleAllocated = true;
+ texObj->Sampler.HandleAllocated = true;
+
+ /* Store the handle in the shared state for all contexts. */
+ _mesa_hash_table_insert(ctx->Shared->ImageHandles,
+ (void *)handle, handleObj);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return (GLuint64)handle;
+}
+
+void
+_mesa_init_resident_handles(struct gl_context *ctx)
+{
+ ctx->ResidentTextureHandles =
+ _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ ctx->ResidentImageHandles =
+ _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+}
+
+void
+_mesa_free_resident_handles(struct gl_context *ctx)
+{
+ _mesa_hash_table_destroy(ctx->ResidentTextureHandles, NULL);
+ _mesa_hash_table_destroy(ctx->ResidentImageHandles, NULL);
+}
+
+static uint32_t
+texture_handle_key_hash(const void *key)
+{
+ return _mesa_hash_data(key, sizeof(struct gl_texture_handle_object));
+}
+
+static bool
+texture_handle_key_equals(const void *a, const void *b)
+{
+ struct gl_texture_handle_object *aa = (struct gl_texture_handle_object *)a;
+ struct gl_texture_handle_object *bb = (struct gl_texture_handle_object *)b;
+
+ return !memcmp(aa, bb, sizeof(struct gl_texture_handle_object));
+}
+
+static uint32_t
+image_handle_key_hash(const void *key)
+{
+ return _mesa_hash_data(key, sizeof(struct gl_image_handle_object));
+}
+
+static bool
+image_handle_key_equals(const void *a, const void *b)
+{
+ struct gl_image_handle_object *aa = (struct gl_image_handle_object *)a;
+ struct gl_image_handle_object *bb = (struct gl_image_handle_object *)b;
+
+ return !memcmp(aa, bb, sizeof(struct gl_image_handle_object));
+}
+
+void
+_mesa_init_texture_handles(struct gl_texture_object *texObj)
+{
+ texObj->SamplerHandles =
+ _mesa_hash_table_create(NULL, texture_handle_key_hash,
+ texture_handle_key_equals);
+ texObj->ImageHandles =
+ _mesa_hash_table_create(NULL, image_handle_key_hash,
+ image_handle_key_equals);
+}
+
+void
+_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
+{
+ struct hash_entry *entry;
+ GLuint64 handle;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+
+ hash_table_foreach(texObj->SamplerHandles, entry) {
+ struct gl_texture_handle_object *handleObj =
+ (struct gl_texture_handle_object *)entry->key;
+
+ handle = (uint64_t)entry->data;
+ if (is_texture_handle_resident(ctx, handle))
+ make_texture_handle_resident(ctx, handleObj, handle, false);
+ }
+
+ hash_table_foreach(texObj->ImageHandles, entry) {
+ struct gl_image_handle_object *handleObj =
+ (struct gl_image_handle_object *)entry->key;
+
+ handle = (uint64_t)entry->data;
+ if (is_image_handle_resident(ctx, handle))
+ make_image_handle_resident(ctx, handleObj, handle, GL_READ_ONLY, false);
+ }
+
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+}
+
+void
+_mesa_delete_texture_handles(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
+{
+ struct hash_entry *entry;
+
+ hash_table_foreach(texObj->SamplerHandles, entry) {
+ struct gl_texture_handle_object *handleObj =
+ (struct gl_texture_handle_object *)entry->key;
+ GLuint64 handle = (GLuint64)entry->data;
+
+ ctx->Driver.DeleteTextureHandle(ctx, handle);
+
+ delete_texture_handle(ctx, handle);
+ free(handleObj);
+ }
+
+ hash_table_foreach(texObj->ImageHandles, entry) {
+ struct gl_image_handle_object *handleObj =
+ (struct gl_image_handle_object *)entry->key;
+ GLuint64 handle = (GLuint64)entry->data;
+
+ ctx->Driver.DeleteImageHandle(ctx, handle);
+
+ delete_image_handle(ctx, handle);
+ free(handleObj);
+ }
+
+ _mesa_hash_table_destroy(texObj->SamplerHandles, NULL);
+ _mesa_hash_table_destroy(texObj->ImageHandles, NULL);
+}
+
+void
+_mesa_init_sampler_handles(struct gl_sampler_object *sampObj)
+{
+ sampObj->Handles = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+}
+
+void
+_mesa_delete_sampler_handles(struct gl_context *ctx,
+ struct gl_sampler_object *sampObj)
+{
+ struct hash_entry *entry;
+
+ hash_table_foreach(sampObj->Handles, entry) {
+ GLuint64 handle = (GLuint64)entry->data;
+
+ ctx->Driver.DeleteTextureHandle(ctx, handle);
+
+ delete_texture_handle(ctx, handle);
+ }
+
+ _mesa_hash_table_destroy(sampObj->Handles, NULL);
+}
+
+static GLboolean
+is_sampler_border_color_valid(struct gl_sampler_object *samp)
+{
+ static const GLfloat valid_float_border_colors[4][4] = {
+ { 0.0, 0.0, 0.0, 0.0 },
+ { 0.0, 0.0, 0.0, 1.0 },
+ { 1.0, 1.0, 1.0, 0.0 },
+ { 1.0, 1.0, 1.0, 1.0 },
+ };
+ static const GLint valid_integer_border_colors[4][4] = {
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 1 },
+ { 1, 1, 1, 0 },
+ { 1, 1, 1, 1 },
+ };
+ size_t size = sizeof(samp->BorderColor.ui);
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated if the border color (taken from
+ * the embedded sampler for GetTextureHandleARB or from the <sampler> for
+ * GetTextureSamplerHandleARB) is not one of the following allowed values.
+ * If the texture's base internal format is signed or unsigned integer,
+ * allowed values are (0,0,0,0), (0,0,0,1), (1,1,1,0), and (1,1,1,1). If
+ * the base internal format is not integer, allowed values are
+ * (0.0,0.0,0.0,0.0), (0.0,0.0,0.0,1.0), (1.0,1.0,1.0,0.0), and
+ * (1.0,1.0,1.0,1.0)."
+ */
+ if (!memcmp(samp->BorderColor.f, valid_float_border_colors[0], size) ||
+ !memcmp(samp->BorderColor.f, valid_float_border_colors[1], size) ||
+ !memcmp(samp->BorderColor.f, valid_float_border_colors[2], size) ||
+ !memcmp(samp->BorderColor.f, valid_float_border_colors[3], size))
+ return GL_TRUE;
+
+ if (!memcmp(samp->BorderColor.ui, valid_integer_border_colors[0], size) ||
+ !memcmp(samp->BorderColor.ui, valid_integer_border_colors[1], size) ||
+ !memcmp(samp->BorderColor.ui, valid_integer_border_colors[2], size) ||
+ !memcmp(samp->BorderColor.ui, valid_integer_border_colors[3], size))
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
GLuint64 GLAPIENTRY
_mesa_GetTextureHandleARB(GLuint texture)
{
- return 0;
+ struct gl_texture_object *texObj = NULL;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureHandleARB(unsupported)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_VALUE is generated by GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if <texture> is zero or not the name of an
+ * existing texture object."
+ */
+ if (texture > 0)
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetTextureHandleARB(texture)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if the texture object specified by <texture>
+ * is not complete."
+ */
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureHandleARB(incomplete texture)");
+ return 0;
+ }
+ }
+
+ if (!is_sampler_border_color_valid(&texObj->Sampler)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureHandleARB(invalid border color)");
+ return 0;
+ }
+
+ return get_texture_handle(ctx, texObj, &texObj->Sampler);
}

GLuint64 GLAPIENTRY
_mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler)
{
- return 0;
+ struct gl_texture_object *texObj = NULL;
+ struct gl_sampler_object *sampObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureSamplerHandleARB(unsupported)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_VALUE is generated by GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if <texture> is zero or not the name of an
+ * existing texture object."
+ */
+ if (texture > 0)
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetTextureSamplerHandleARB(texture)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_VALUE is generated by GetTextureSamplerHandleARB if
+ * <sampler> is zero or is not the name of an existing sampler object."
+ */
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetTextureSamplerHandleARB(sampler)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if the texture object specified by <texture>
+ * is not complete."
+ */
+ if (!_mesa_is_texture_complete(texObj, sampObj)) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (!_mesa_is_texture_complete(texObj, sampObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureSamplerHandleARB(incomplete texture)");
+ return 0;
+ }
+ }
+
+ if (!is_sampler_border_color_valid(sampObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureSamplerHandleARB(invalid border color)");
+ return 0;
+ }
+
+ return get_texture_handle(ctx, texObj, sampObj);
}

void GLAPIENTRY
_mesa_MakeTextureHandleResidentARB(GLuint64 handle)
{
+ struct gl_texture_handle_object *handleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleResidentARB(unsupported)");
+ return;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by MakeTextureHandleResidentARB
+ * if <handle> is not a valid texture handle, or if <handle> is already
+ * resident in the current GL context."
+ */
+ handleObj = lookup_texture_handle(ctx, handle);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleResidentARB(handle)");
+ return;
+ }
+
+ if (is_texture_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleResidentARB(already resident)");
+ return;
+ }
+
+ make_texture_handle_resident(ctx, handleObj, handle, true);
}

void GLAPIENTRY
_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle)
{
+ struct gl_texture_handle_object *handleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleNonResidentARB(unsupported)");
+ return;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by
+ * MakeTextureHandleNonResidentARB if <handle> is not a valid texture
+ * handle, or if <handle> is not resident in the current GL context."
+ */
+ handleObj = lookup_texture_handle(ctx, handle);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleNonResidentARB(handle)");
+ return;
+ }
+
+ if (!is_texture_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleNonResidentARB(not resident)");
+ return;
+ }
+
+ make_texture_handle_resident(ctx, handleObj, handle, false);
}

GLuint64 GLAPIENTRY
_mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
GLint layer, GLenum format)
{
- return 0;
+ struct gl_texture_object *texObj = NULL;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) &&
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetImageHandleARB(unsupported)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_VALUE is generated by GetImageHandleARB if <texture>
+ * is zero or not the name of an existing texture object, if the image for
+ * <level> does not existing in <texture>, or if <layered> is FALSE and
+ * <layer> is greater than or equal to the number of layers in the image at
+ * <level>."
+ */
+ if (texture > 0)
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(texture)");
+ return 0;
+ }
+
+ if (level < 0 || level >= _mesa_max_texture_levels(ctx, texObj->Target)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(level)");
+ return 0;
+ }
+
+ if (!layered && layer > _mesa_get_texture_layers(texObj, level)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(layer)");
+ return 0;
+ }
+
+ if (!_mesa_is_shader_image_format_supported(ctx, format)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(format)");
+ return 0;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by GetImageHandleARB if the
+ * texture object <texture> is not complete or if <layered> is TRUE and
+ * <texture> is not a three-dimensional, one-dimensional array, two
+ * dimensional array, cube map, or cube map array texture."
+ */
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetImageHandleARB(incomplete texture)");
+ return 0;
+ }
+ }
+
+ if (layered && !_mesa_tex_target_is_layered(texObj->Target)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetImageHandleARB(not layered)");
+ return 0;
+ }
+
+ return get_image_handle(ctx, texObj, level, layered, layer, format);
}

void GLAPIENTRY
_mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access)
{
+ struct gl_image_handle_object *handleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) &&
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleResidentARB(unsupported)");
+ return;
+ }
+
+ if (access != GL_READ_ONLY &&
+ access != GL_WRITE_ONLY &&
+ access != GL_READ_WRITE) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glMakeImageHandleResidentARB(access)");
+ return;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by MakeImageHandleResidentARB
+ * if <handle> is not a valid image handle, or if <handle> is already
+ * resident in the current GL context."
+ */
+ handleObj = lookup_image_handle(ctx, handle);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleResidentARB(handle)");
+ return;
+ }
+
+ if (is_image_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleResidentARB(already resident)");
+ return;
+ }
+
+ make_image_handle_resident(ctx, handleObj, handle, access, true);
}

void GLAPIENTRY
_mesa_MakeImageHandleNonResidentARB(GLuint64 handle)
{
+ struct gl_image_handle_object *handleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) &&
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleNonResidentARB(unsupported)");
+ return;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by
+ * MakeImageHandleNonResidentARB if <handle> is not a valid image handle,
+ * or if <handle> is not resident in the current GL context."
+ */
+ handleObj = lookup_image_handle(ctx, handle);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleNonResidentARB(handle)");
+ return;
+ }
+
+ if (!is_image_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleNonResidentARB(not resident)");
+ return;
+ }
+
+ make_image_handle_resident(ctx, handleObj, handle, GL_READ_ONLY, false);
}

GLboolean GLAPIENTRY
_mesa_IsTextureHandleResidentARB(GLuint64 handle)
{
- return GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsTextureHandleResidentARB(unsupported)");
+ return GL_FALSE;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION will be generated by
+ * IsTextureHandleResidentARB and IsImageHandleResidentARB if <handle> is
+ * not a valid texture or image handle, respectively."
+ */
+ if (!lookup_texture_handle(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsTextureHandleResidentARB(handle)");
+ return GL_FALSE;
+ }
+
+ return is_texture_handle_resident(ctx, handle);
}

GLboolean GLAPIENTRY
_mesa_IsImageHandleResidentARB(GLuint64 handle)
{
- return GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) &&
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsImageHandleResidentARB(unsupported)");
+ return GL_FALSE;
+ }
+
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION will be generated by
+ * IsTextureHandleResidentARB and IsImageHandleResidentARB if <handle> is
+ * not a valid texture or image handle, respectively."
+ */
+ if (!lookup_image_handle(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsImageHandleResidentARB(handle)");
+ return GL_FALSE;
+ }
+
+ return is_image_handle_resident(ctx, handle);
}
diff --git a/src/mesa/main/texturebindless.h b/src/mesa/main/texturebindless.h
index 88b84ce275..bdee74121e 100644
--- a/src/mesa/main/texturebindless.h
+++ b/src/mesa/main/texturebindless.h
@@ -31,6 +31,34 @@ extern "C" {
#endif

/**
+ * \name Internal functions
+ */
+/*@{*/
+
+void
+_mesa_init_resident_handles(struct gl_context *ctx);
+
+void
+_mesa_free_resident_handles(struct gl_context *ctx);
+
+void
+_mesa_init_texture_handles(struct gl_texture_object *texObj);
+void
+_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
+ struct gl_texture_object *texObj);
+void
+_mesa_delete_texture_handles(struct gl_context *ctx,
+ struct gl_texture_object *texObj);
+
+void
+_mesa_init_sampler_handles(struct gl_sampler_object *sampObj);
+void
+_mesa_delete_sampler_handles(struct gl_context *ctx,
+ struct gl_sampler_object *sampObj);
+
+/*@}*/
+
+/**
* \name API functions
*/
/*@{*/
--
2.13.0
Nicolai Hähnle
2017-05-22 10:43:33 UTC
Permalink
Post by Samuel Pitoiset
---
src/mesa/main/context.c | 3 +
src/mesa/main/dd.h | 17 +
src/mesa/main/mtypes.h | 34 ++
src/mesa/main/samplerobj.c | 6 +
src/mesa/main/shared.c | 12 +
src/mesa/main/texobj.c | 12 +
src/mesa/main/texturebindless.c | 827 +++++++++++++++++++++++++++++++++++++++-
src/mesa/main/texturebindless.h | 28 ++
8 files changed, 934 insertions(+), 5 deletions(-)
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 3570f94f5a..5321886a95 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -133,6 +133,7 @@
#include "varray.h"
#include "version.h"
#include "viewport.h"
+#include "texturebindless.h"
#include "program/program.h"
#include "math/m_matrix.h"
#include "main/dispatch.h" /* for _gloffset_COUNT */
@@ -855,6 +856,7 @@ init_attrib_groups(struct gl_context *ctx)
_mesa_init_transform_feedback( ctx );
_mesa_init_varray( ctx );
_mesa_init_viewport( ctx );
+ _mesa_init_resident_handles( ctx );
if (!_mesa_init_texture( ctx ))
return GL_FALSE;
@@ -1339,6 +1341,7 @@ _mesa_free_context_data( struct gl_context *ctx )
_mesa_free_transform_feedback(ctx);
_mesa_free_performance_monitors(ctx);
_mesa_free_performance_queries(ctx);
+ _mesa_free_resident_handles(ctx);
_mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
_mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index a9ca43d69e..d830f5184d 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -1050,6 +1050,23 @@ struct dd_function_table {
GLintptr offset, GLsizeiptr size,
GLboolean commit);
+
+ /**
+ * \name GL_ARB_bindless_texture interface
+ */
+ GLuint64 (*NewTextureHandle)(struct gl_context *ctx,
+ struct gl_texture_object *texObj,
+ struct gl_sampler_object *sampObj);
+ void (*DeleteTextureHandle)(struct gl_context *ctx, GLuint64 handle);
+ void (*MakeTextureHandleResident)(struct gl_context *ctx, GLuint64 handle,
+ bool resident);
+ GLuint64 (*NewImageHandle)(struct gl_context *ctx,
+ struct gl_image_unit *imgObj);
+ void (*DeleteImageHandle)(struct gl_context *ctx, GLuint64 handle);
+ void (*MakeImageHandleResident)(struct gl_context *ctx, GLuint64 handle,
+ GLenum access, bool resident);
};
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index efc6920254..70865b373d 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -987,6 +987,9 @@ struct gl_sampler_object
GLenum CompareFunc; /**< GL_ARB_shadow */
GLenum sRGBDecode; /**< GL_DECODE_EXT or GL_SKIP_DECODE_EXT */
GLboolean CubeMapSeamless; /**< GL_AMD_seamless_cubemap_per_texture */
+ bool HandleAllocated; /**< GL_ARB_bindless_texture */
+
+ struct hash_table *Handles;
};
@@ -1034,6 +1037,8 @@ struct gl_texture_object
GLuint NumLevels; /**< GL_ARB_texture_view */
GLuint NumLayers; /**< GL_ARB_texture_view */
+ GLboolean HandleAllocated; /**< GL_ARB_bindless_texture */
+
/** Actual texture images, indexed by [cube face] and [mipmap level] */
struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS];
@@ -1051,6 +1056,10 @@ struct gl_texture_object
/** GL_ARB_shader_image_load_store */
GLenum ImageFormatCompatibilityType;
+
+ /** GL_ARB_bindless_texture */
+ struct hash_table *SamplerHandles;
+ struct hash_table *ImageHandles;
};
@@ -1390,6 +1399,7 @@ struct gl_buffer_object
GLboolean Written; /**< Ever written to? (for debugging) */
GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
GLboolean Immutable; /**< GL_ARB_buffer_storage */
+ GLboolean HandleAllocated; /**< GL_ARB_bindless_texture */
Should be consistent with gl_sampler_object in terms of type (and
gl_texture_object as well). Which type? Since the state is not
API-visible, bool is justifiable.
Post by Samuel Pitoiset
gl_buffer_usage UsageHistory; /**< How has this buffer been used so far? */
/** Counters used for buffer usage warnings */
@@ -3203,6 +3213,11 @@ struct gl_shared_state
/** GL_ARB_sampler_objects */
struct _mesa_HashTable *SamplerObjects;
+ /* GL_ARB_bindless_texture */
+ struct hash_table *TextureHandles;
+ struct hash_table *ImageHandles;
+ mtx_t HandlesMutex; /**< For texture/image handles safety */
+
/**
* Some context in this share group was affected by a GPU reset
*
@@ -4488,6 +4503,17 @@ struct gl_subroutine_index_binding
GLuint *IndexPtr;
};
+struct gl_texture_handle_object
+{
+ struct gl_texture_object *texObj;
+ struct gl_sampler_object *sampObj;
+};
+
+struct gl_image_handle_object
+{
+ struct gl_image_unit imgObj;
+};
+
/**
* Mesa rendering context.
*
@@ -4842,6 +4868,14 @@ struct gl_context
GLfloat PrimitiveBoundingBox[8];
struct disk_cache *Cache;
+
+ /**
+ * \name GL_ARB_bindless_texture
+ */
+ struct hash_table *ResidentTextureHandles;
+ struct hash_table *ResidentImageHandles;
};
/**
diff --git a/src/mesa/main/samplerobj.c b/src/mesa/main/samplerobj.c
index 63beaf1abb..ee15c68b4f 100644
--- a/src/mesa/main/samplerobj.c
+++ b/src/mesa/main/samplerobj.c
@@ -38,6 +38,7 @@
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/samplerobj.h"
+#include "main/texturebindless.h"
struct gl_sampler_object *
@@ -61,6 +62,7 @@ static void
delete_sampler_object(struct gl_context *ctx,
struct gl_sampler_object *sampObj)
{
+ _mesa_delete_sampler_handles(ctx, sampObj);
mtx_destroy(&sampObj->Mutex);
free(sampObj->Label);
free(sampObj);
@@ -132,6 +134,10 @@ _mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name)
sampObj->CompareFunc = GL_LEQUAL;
sampObj->sRGBDecode = GL_DECODE_EXT;
sampObj->CubeMapSeamless = GL_FALSE;
+ sampObj->HandleAllocated = GL_FALSE;
+
+ /* GL_ARB_bindless_texture */
+ _mesa_init_sampler_handles(sampObj);
}
/**
diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c
index 5344812738..b188287a08 100644
--- a/src/mesa/main/shared.c
+++ b/src/mesa/main/shared.c
@@ -84,6 +84,13 @@ _mesa_alloc_shared_state(struct gl_context *ctx)
/* GL_ARB_sampler_objects */
shared->SamplerObjects = _mesa_NewHashTable();
+ /* GL_ARB_bindless_texture */
+ shared->TextureHandles = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ shared->ImageHandles = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ mtx_init(&shared->HandlesMutex, mtx_recursive);
+
/* Allocate the default buffer object */
shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0);
@@ -373,6 +380,11 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared)
_mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx);
_mesa_DeleteHashTable(shared->TexObjects);
+ /* Bindless texture/image handles */
+ _mesa_hash_table_destroy(shared->TextureHandles, NULL);
+ _mesa_hash_table_destroy(shared->ImageHandles, NULL);
+ mtx_destroy(&shared->HandlesMutex);
+
mtx_destroy(&shared->Mutex);
mtx_destroy(&shared->TexMutex);
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index 868e4eb7a2..13a24f6deb 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -43,6 +43,7 @@
#include "texstate.h"
#include "mtypes.h"
#include "program/prog_instruction.h"
+#include "texturebindless.h"
@@ -311,6 +312,7 @@ _mesa_initialize_texture_object( struct gl_context *ctx,
obj->DepthMode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE;
obj->StencilSampling = false;
obj->Sampler.CubeMapSeamless = GL_FALSE;
+ obj->Sampler.HandleAllocated = GL_FALSE;
obj->Swizzle[0] = GL_RED;
obj->Swizzle[1] = GL_GREEN;
obj->Swizzle[2] = GL_BLUE;
@@ -320,6 +322,9 @@ _mesa_initialize_texture_object( struct gl_context *ctx,
obj->BufferObjectFormat = GL_R8;
obj->_BufferObjectFormat = MESA_FORMAT_R_UNORM8;
obj->ImageFormatCompatibilityType = GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE;
+
+ /* GL_ARB_bindless_texture */
+ _mesa_init_texture_handles(obj);
}
@@ -397,6 +402,9 @@ _mesa_delete_texture_object(struct gl_context *ctx,
}
}
+ /* Delete all texture/image handles. */
+ _mesa_delete_texture_handles(ctx, texObj);
+
_mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL);
/* destroy the mutex -- it may have allocated memory (eg on bsd) */
@@ -1461,6 +1469,10 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
*/
unbind_texobj_from_image_units(ctx, delObj);
+ /* Make all handles that reference this texture object non-resident
+ * in the current context. */
+ _mesa_make_texture_handles_non_resident(ctx, delObj);
+
_mesa_unlock_texture(ctx, delObj);
ctx->NewState |= _NEW_TEXTURE_OBJECT;
diff --git a/src/mesa/main/texturebindless.c b/src/mesa/main/texturebindless.c
index 4d9c22d428..0c6f9c3fc9 100644
--- a/src/mesa/main/texturebindless.c
+++ b/src/mesa/main/texturebindless.c
@@ -29,57 +29,874 @@
#include "mtypes.h"
#include "texobj.h"
#include "texturebindless.h"
+#include "shaderimage.h"
+#include "teximage.h"
+#include "hash.h"
#include "util/set.h"
#include "util/hash_table.h"
+/**
+ * Return the gl_texture_handle_object for a given 64bit handle.
+ */
+static struct gl_texture_handle_object *
+lookup_texture_handle(struct gl_context *ctx, GLuint64 id)
+{
+ struct hash_entry *entry;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(ctx->Shared->TextureHandles, (void *)id);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return entry ? (struct gl_texture_handle_object *)entry->data : NULL;
+}
+
+/**
+ * Return the gl_image_handle_object for a given 64bit handle.
+ */
+static struct gl_image_handle_object *
+lookup_image_handle(struct gl_context *ctx, GLuint64 id)
+{
+ struct hash_entry *entry;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(ctx->Shared->ImageHandles, (void *)id);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return entry ? (struct gl_image_handle_object *)entry->data : NULL;
+}
+
+/**
+ * Delete a texture handle in the shared state.
+ */
+static void
+delete_texture_handle(struct gl_context *ctx, GLuint64 id)
+{
+ struct hash_entry *entry;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(ctx->Shared->TextureHandles, (void *)id);
+ _mesa_hash_table_remove(ctx->Shared->TextureHandles, entry);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+}
+
+/**
+ * Delete an image handle in the shared state.
+ */
+static void
+delete_image_handle(struct gl_context *ctx, GLuint64 id)
+{
+ struct hash_entry *entry;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(ctx->Shared->ImageHandles, (void *)id);
+ _mesa_hash_table_remove(ctx->Shared->ImageHandles, entry);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+}
+
+/**
+ * Return TRUE if the texture handle is resident in the current context.
+ */
+static inline bool
+is_texture_handle_resident(struct gl_context *ctx, GLuint64 handle)
+{
+ return _mesa_hash_table_search(ctx->ResidentTextureHandles,
+ (void *)handle) != NULL;
+}
+
+/**
+ * Return TRUE if the image handle is resident in the current context.
+ */
+static inline bool
+is_image_handle_resident(struct gl_context *ctx, GLuint64 handle)
+{
+ return _mesa_hash_table_search(ctx->ResidentImageHandles,
+ (void *)handle) != NULL;
+}
+
+/**
+ * Set a texture handle resident/non-resident in the current context.
+ */
+static void
+make_texture_handle_resident(struct gl_context *ctx,
+ struct gl_texture_handle_object *handleObj,
+ GLuint64 handle, bool resident)
+{
+ if (resident) {
+ struct gl_sampler_object *sampObj = NULL;
+ struct gl_texture_object *texObj = NULL;
+
+ _mesa_hash_table_insert(ctx->ResidentTextureHandles,
+ (void *)handle, handleObj);
+
+ ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_TRUE);
+
+ /* Reference the texture object (and the separate sampler if needed) to
+ * be sure it won't be deleted until it is not bound anywhere and there
+ * are no handles using the object that are resident in any context. */
+ _mesa_reference_texobj(&texObj, handleObj->texObj);
+ if (handleObj->sampObj)
+ _mesa_reference_sampler_object(ctx, &sampObj, handleObj->sampObj);
+ } else {
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(ctx->ResidentTextureHandles,
+ (void *)handle);
+ _mesa_hash_table_remove(ctx->ResidentTextureHandles, entry);
+
+ ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_FALSE);
+
+ /* Unreference the texture object (and the separate sampler if needed),
+ * if refcount hits zero, the texture and all handles will be deleted. */
+ _mesa_reference_texobj(&handleObj->texObj, NULL);
+ if (handleObj->sampObj)
+ _mesa_reference_sampler_object(ctx, &handleObj->sampObj, NULL);
+ }
+}
+
+/**
+ * Set an image handle resident/non-resident in the current context.
+ */
+static void
+make_image_handle_resident(struct gl_context *ctx,
+ struct gl_image_handle_object *handleObj,
+ GLuint64 handle, GLenum access, bool resident)
+{
+ if (resident) {
+ struct gl_texture_object *texObj = NULL;
+
+ _mesa_hash_table_insert(ctx->ResidentImageHandles,
+ (void *)handle, handleObj);
+
+ ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_TRUE);
+
+ /* Reference the texture object to be sure it won't be deleted until it
+ * is not bound anywhere and there are no handles using the object that
+ * are resident in any context. */
+ _mesa_reference_texobj(&texObj, handleObj->imgObj.TexObj);
+ } else {
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(ctx->ResidentImageHandles,
+ (void *)handle);
+ _mesa_hash_table_remove(ctx->ResidentImageHandles, entry);
+
+ ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_FALSE);
+
+ /* Unreference the texture object, if refcount hits zero, the texture and
+ * all handles will be deleted. */
+ _mesa_reference_texobj(&handleObj->imgObj.TexObj, NULL);
+ }
+}
+
+static GLuint64
+get_texture_handle(struct gl_context *ctx, struct gl_texture_object *texObj,
+ struct gl_sampler_object *sampObj)
+{
+ struct gl_texture_handle_object *handleObj;
+ struct hash_entry *entry;
+ GLuint64 handle;
+
+ handleObj = CALLOC_STRUCT(gl_texture_handle_object);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
+ return 0;
+ }
+
+ handleObj->texObj = texObj;
+ if (&texObj->Sampler != sampObj)
+ handleObj->sampObj = sampObj;
+
+ *
+ * "The handle for each texture or texture/sampler pair is unique; the same
+ * handle will be returned if GetTextureHandleARB is called multiple times
+ * for the same texture or if GetTextureSamplerHandleARB is called multiple
+ * times for the same texture/sampler pair."
+ */
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(texObj->SamplerHandles, handleObj);
+ if (entry) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ return (uint64_t)entry->data;
+ }
+
+ /* Ask the driver for a new handle and store it. */
+ handle = ctx->Driver.NewTextureHandle(ctx, texObj, sampObj);
+ if (!handle) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
+ return 0;
+ }
+
+ _mesa_hash_table_insert(texObj->SamplerHandles, handleObj, (void *)handle);
+
+ if (&texObj->Sampler != sampObj) {
+ _mesa_hash_table_insert(sampObj->Handles, handleObj,
+ (void *)handle);
+ }
+
+ /* When referenced by one or more handles, texture objects are immutable. */
+ texObj->HandleAllocated = true;
+ sampObj->HandleAllocated = true;
+ if (texObj->Target == GL_TEXTURE_BUFFER)
+ texObj->BufferObject->HandleAllocated = true;
+
+ /* Store the handle in the shared state for all contexts. */
+ _mesa_hash_table_insert(ctx->Shared->TextureHandles,
+ (void *)handle, handleObj);
This won't work on 32-bit systems (same for image handles).
Post by Samuel Pitoiset
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return (GLuint64)handle;
+}
+
+static GLuint64
+get_image_handle(struct gl_context *ctx, struct gl_texture_object *texObj,
+ GLint level, GLboolean layered, GLint layer, GLenum format)
+{
+ struct gl_image_handle_object *handleObj;
+ struct gl_image_unit *imgObj;
+ struct hash_entry *entry;
+ GLuint64 handle;
+
+ handleObj = CALLOC_STRUCT(gl_image_handle_object);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
+ return 0;
+ }
+
+ imgObj = &handleObj->imgObj;
+ imgObj->TexObj = texObj; /* weak reference */
+ imgObj->Level = level;
+ imgObj->Access = GL_READ_WRITE;
+ imgObj->Format = format;
+ imgObj->_ActualFormat = _mesa_get_shader_image_format(format);
+
+ if (_mesa_tex_target_is_layered(texObj->Target)) {
+ imgObj->Layered = layered;
+ imgObj->Layer = layer;
+ imgObj->_Layer = (imgObj->Layered ? 0 : imgObj->Layer);
+ } else {
+ imgObj->Layered = GL_FALSE;
+ imgObj->Layer = 0;
+ }
+
+ *
+ * "The handle returned for each combination of <texture>, <level>,
+ * <layered>, <layer>, and <format> is unique; the same handle will be
+ * returned if GetImageHandleARB is called multiple times with the same
+ * parameters."
+ */
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(texObj->ImageHandles, handleObj);
+ if (entry) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ return (uint64_t)entry->data;
+ }
+
+ /* Ask the driver for a new handle and store it. */
+ handle = ctx->Driver.NewImageHandle(ctx, &handleObj->imgObj);
+ if (!handle) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
+ return 0;
+ }
+
+ _mesa_hash_table_insert(texObj->ImageHandles, handleObj, (void *)handle);
+
+ /* When referenced by one or more handles, texture objects are immutable. */
+ texObj->HandleAllocated = true;
+ if (texObj->Target == GL_TEXTURE_BUFFER)
+ texObj->BufferObject->HandleAllocated = true;
+ texObj->Sampler.HandleAllocated = true;
+
+ /* Store the handle in the shared state for all contexts. */
+ _mesa_hash_table_insert(ctx->Shared->ImageHandles,
+ (void *)handle, handleObj);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return (GLuint64)handle;
+}
+
+void
+_mesa_init_resident_handles(struct gl_context *ctx)
+{
+ ctx->ResidentTextureHandles =
+ _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ ctx->ResidentImageHandles =
+ _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+}
+
+void
+_mesa_free_resident_handles(struct gl_context *ctx)
+{
+ _mesa_hash_table_destroy(ctx->ResidentTextureHandles, NULL);
+ _mesa_hash_table_destroy(ctx->ResidentImageHandles, NULL);
+}
+
+static uint32_t
+texture_handle_key_hash(const void *key)
+{
+ return _mesa_hash_data(key, sizeof(struct gl_texture_handle_object));
+}
+
+static bool
+texture_handle_key_equals(const void *a, const void *b)
+{
+ struct gl_texture_handle_object *aa = (struct gl_texture_handle_object *)a;
+ struct gl_texture_handle_object *bb = (struct gl_texture_handle_object *)b;
+
+ return !memcmp(aa, bb, sizeof(struct gl_texture_handle_object));
+}
+
+static uint32_t
+image_handle_key_hash(const void *key)
+{
+ return _mesa_hash_data(key, sizeof(struct gl_image_handle_object));
+}
+
+static bool
+image_handle_key_equals(const void *a, const void *b)
+{
+ struct gl_image_handle_object *aa = (struct gl_image_handle_object *)a;
+ struct gl_image_handle_object *bb = (struct gl_image_handle_object *)b;
+
+ return !memcmp(aa, bb, sizeof(struct gl_image_handle_object));
+}
+
+void
+_mesa_init_texture_handles(struct gl_texture_object *texObj)
+{
+ texObj->SamplerHandles =
+ _mesa_hash_table_create(NULL, texture_handle_key_hash,
+ texture_handle_key_equals);
+ texObj->ImageHandles =
+ _mesa_hash_table_create(NULL, image_handle_key_hash,
+ image_handle_key_equals);
+}
+
+void
+_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
+{
+ struct hash_entry *entry;
+ GLuint64 handle;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+
+ hash_table_foreach(texObj->SamplerHandles, entry) {
+ struct gl_texture_handle_object *handleObj =
+ (struct gl_texture_handle_object *)entry->key;
+
+ handle = (uint64_t)entry->data;
+ if (is_texture_handle_resident(ctx, handle))
+ make_texture_handle_resident(ctx, handleObj, handle, false);
+ }
+
+ hash_table_foreach(texObj->ImageHandles, entry) {
+ struct gl_image_handle_object *handleObj =
+ (struct gl_image_handle_object *)entry->key;
+
+ handle = (uint64_t)entry->data;
+ if (is_image_handle_resident(ctx, handle))
+ make_image_handle_resident(ctx, handleObj, handle, GL_READ_ONLY, false);
+ }
So... this also needs to loop through all other contexts and make the
handle non-resident in them, right? Otherwise you might end up with
dangling pointers (or at least dangling handles).
Post by Samuel Pitoiset
+
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+}
+
+void
+_mesa_delete_texture_handles(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
+{
+ struct hash_entry *entry;
+
+ hash_table_foreach(texObj->SamplerHandles, entry) {
+ struct gl_texture_handle_object *handleObj =
+ (struct gl_texture_handle_object *)entry->key;
+ GLuint64 handle = (GLuint64)entry->data;
+
+ ctx->Driver.DeleteTextureHandle(ctx, handle);
+
+ delete_texture_handle(ctx, handle);
+ free(handleObj);
+ }
+
+ hash_table_foreach(texObj->ImageHandles, entry) {
+ struct gl_image_handle_object *handleObj =
+ (struct gl_image_handle_object *)entry->key;
+ GLuint64 handle = (GLuint64)entry->data;
+
+ ctx->Driver.DeleteImageHandle(ctx, handle);
+
+ delete_image_handle(ctx, handle);
+ free(handleObj);
+ }
+
+ _mesa_hash_table_destroy(texObj->SamplerHandles, NULL);
+ _mesa_hash_table_destroy(texObj->ImageHandles, NULL);
+}
+
+void
+_mesa_init_sampler_handles(struct gl_sampler_object *sampObj)
+{
+ sampObj->Handles = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+}
+
+void
+_mesa_delete_sampler_handles(struct gl_context *ctx,
+ struct gl_sampler_object *sampObj)
+{
+ struct hash_entry *entry;
+
+ hash_table_foreach(sampObj->Handles, entry) {
+ GLuint64 handle = (GLuint64)entry->data;
+
+ ctx->Driver.DeleteTextureHandle(ctx, handle);
+
+ delete_texture_handle(ctx, handle);
+ }
+
+ _mesa_hash_table_destroy(sampObj->Handles, NULL);
+}
+
+static GLboolean
+is_sampler_border_color_valid(struct gl_sampler_object *samp)
+{
+ static const GLfloat valid_float_border_colors[4][4] = {
+ { 0.0, 0.0, 0.0, 0.0 },
+ { 0.0, 0.0, 0.0, 1.0 },
+ { 1.0, 1.0, 1.0, 0.0 },
+ { 1.0, 1.0, 1.0, 1.0 },
+ };
+ static const GLint valid_integer_border_colors[4][4] = {
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 1 },
+ { 1, 1, 1, 0 },
+ { 1, 1, 1, 1 },
+ };
+ size_t size = sizeof(samp->BorderColor.ui);
+
+ *
+ * "The error INVALID_OPERATION is generated if the border color (taken from
+ * the embedded sampler for GetTextureHandleARB or from the <sampler> for
+ * GetTextureSamplerHandleARB) is not one of the following allowed values.
+ * If the texture's base internal format is signed or unsigned integer,
+ * allowed values are (0,0,0,0), (0,0,0,1), (1,1,1,0), and (1,1,1,1). If
+ * the base internal format is not integer, allowed values are
+ * (0.0,0.0,0.0,0.0), (0.0,0.0,0.0,1.0), (1.0,1.0,1.0,0.0), and
+ * (1.0,1.0,1.0,1.0)."
+ */
+ if (!memcmp(samp->BorderColor.f, valid_float_border_colors[0], size) ||
+ !memcmp(samp->BorderColor.f, valid_float_border_colors[1], size) ||
+ !memcmp(samp->BorderColor.f, valid_float_border_colors[2], size) ||
+ !memcmp(samp->BorderColor.f, valid_float_border_colors[3], size))
+ return GL_TRUE;
+
+ if (!memcmp(samp->BorderColor.ui, valid_integer_border_colors[0], size) ||
+ !memcmp(samp->BorderColor.ui, valid_integer_border_colors[1], size) ||
+ !memcmp(samp->BorderColor.ui, valid_integer_border_colors[2], size) ||
+ !memcmp(samp->BorderColor.ui, valid_integer_border_colors[3], size))
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
GLuint64 GLAPIENTRY
_mesa_GetTextureHandleARB(GLuint texture)
{
- return 0;
+ struct gl_texture_object *texObj = NULL;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureHandleARB(unsupported)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_VALUE is generated by GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if <texture> is zero or not the name of an
+ * existing texture object."
+ */
+ if (texture > 0)
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetTextureHandleARB(texture)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if the texture object specified by <texture>
+ * is not complete."
+ */
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureHandleARB(incomplete texture)");
+ return 0;
+ }
+ }
+
+ if (!is_sampler_border_color_valid(&texObj->Sampler)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureHandleARB(invalid border color)");
+ return 0;
+ }
+
+ return get_texture_handle(ctx, texObj, &texObj->Sampler);
}
GLuint64 GLAPIENTRY
_mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler)
{
- return 0;
+ struct gl_texture_object *texObj = NULL;
+ struct gl_sampler_object *sampObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureSamplerHandleARB(unsupported)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_VALUE is generated by GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if <texture> is zero or not the name of an
+ * existing texture object."
+ */
+ if (texture > 0)
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetTextureSamplerHandleARB(texture)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_VALUE is generated by GetTextureSamplerHandleARB if
+ * <sampler> is zero or is not the name of an existing sampler object."
+ */
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetTextureSamplerHandleARB(sampler)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if the texture object specified by <texture>
+ * is not complete."
+ */
+ if (!_mesa_is_texture_complete(texObj, sampObj)) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (!_mesa_is_texture_complete(texObj, sampObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureSamplerHandleARB(incomplete texture)");
+ return 0;
+ }
+ }
+
+ if (!is_sampler_border_color_valid(sampObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureSamplerHandleARB(invalid border color)");
+ return 0;
+ }
+
+ return get_texture_handle(ctx, texObj, sampObj);
}
void GLAPIENTRY
_mesa_MakeTextureHandleResidentARB(GLuint64 handle)
{
+ struct gl_texture_handle_object *handleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleResidentARB(unsupported)");
+ return;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by MakeTextureHandleResidentARB
+ * if <handle> is not a valid texture handle, or if <handle> is already
+ * resident in the current GL context."
+ */
+ handleObj = lookup_texture_handle(ctx, handle);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleResidentARB(handle)");
+ return;
+ }
+
+ if (is_texture_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleResidentARB(already resident)");
+ return;
+ }
+
+ make_texture_handle_resident(ctx, handleObj, handle, true);
}
void GLAPIENTRY
_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle)
{
+ struct gl_texture_handle_object *handleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleNonResidentARB(unsupported)");
+ return;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by
+ * MakeTextureHandleNonResidentARB if <handle> is not a valid texture
+ * handle, or if <handle> is not resident in the current GL context."
+ */
+ handleObj = lookup_texture_handle(ctx, handle);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleNonResidentARB(handle)");
+ return;
+ }
+
+ if (!is_texture_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleNonResidentARB(not resident)");
+ return;
+ }
+
+ make_texture_handle_resident(ctx, handleObj, handle, false);
}
GLuint64 GLAPIENTRY
_mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
GLint layer, GLenum format)
{
- return 0;
+ struct gl_texture_object *texObj = NULL;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) &&
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
|| instead of &&
Post by Samuel Pitoiset
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetImageHandleARB(unsupported)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_VALUE is generated by GetImageHandleARB if <texture>
+ * is zero or not the name of an existing texture object, if the image for
+ * <level> does not existing in <texture>, or if <layered> is FALSE and
+ * <layer> is greater than or equal to the number of layers in the image at
+ * <level>."
+ */
+ if (texture > 0)
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(texture)");
+ return 0;
+ }
+
+ if (level < 0 || level >= _mesa_max_texture_levels(ctx, texObj->Target)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(level)");
+ return 0;
+ }
+
+ if (!layered && layer > _mesa_get_texture_layers(texObj, level)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(layer)");
+ return 0;
+ }
+
+ if (!_mesa_is_shader_image_format_supported(ctx, format)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(format)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by GetImageHandleARB if the
+ * texture object <texture> is not complete or if <layered> is TRUE and
+ * <texture> is not a three-dimensional, one-dimensional array, two
+ * dimensional array, cube map, or cube map array texture."
+ */
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetImageHandleARB(incomplete texture)");
+ return 0;
+ }
+ }
+
+ if (layered && !_mesa_tex_target_is_layered(texObj->Target)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetImageHandleARB(not layered)");
+ return 0;
+ }
+
+ return get_image_handle(ctx, texObj, level, layered, layer, format);
}
void GLAPIENTRY
_mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access)
{
+ struct gl_image_handle_object *handleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) &&
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
|| instead of &&
Post by Samuel Pitoiset
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleResidentARB(unsupported)");
+ return;
+ }
+
+ if (access != GL_READ_ONLY &&
+ access != GL_WRITE_ONLY &&
+ access != GL_READ_WRITE) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glMakeImageHandleResidentARB(access)");
+ return;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by MakeImageHandleResidentARB
+ * if <handle> is not a valid image handle, or if <handle> is already
+ * resident in the current GL context."
+ */
+ handleObj = lookup_image_handle(ctx, handle);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleResidentARB(handle)");
+ return;
+ }
+
+ if (is_image_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleResidentARB(already resident)");
+ return;
+ }
+
+ make_image_handle_resident(ctx, handleObj, handle, access, true);
}
void GLAPIENTRY
_mesa_MakeImageHandleNonResidentARB(GLuint64 handle)
{
+ struct gl_image_handle_object *handleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) &&
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
|| vs. &&
Post by Samuel Pitoiset
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleNonResidentARB(unsupported)");
+ return;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by
+ * MakeImageHandleNonResidentARB if <handle> is not a valid image handle,
+ * or if <handle> is not resident in the current GL context."
+ */
+ handleObj = lookup_image_handle(ctx, handle);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleNonResidentARB(handle)");
+ return;
+ }
+
+ if (!is_image_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleNonResidentARB(not resident)");
+ return;
+ }
+
+ make_image_handle_resident(ctx, handleObj, handle, GL_READ_ONLY, false);
}
GLboolean GLAPIENTRY
_mesa_IsTextureHandleResidentARB(GLuint64 handle)
{
- return GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsTextureHandleResidentARB(unsupported)");
+ return GL_FALSE;
+ }
+
+ *
+ * "The error INVALID_OPERATION will be generated by
+ * IsTextureHandleResidentARB and IsImageHandleResidentARB if <handle> is
+ * not a valid texture or image handle, respectively."
+ */
+ if (!lookup_texture_handle(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsTextureHandleResidentARB(handle)");
+ return GL_FALSE;
+ }
+
+ return is_texture_handle_resident(ctx, handle);
}
GLboolean GLAPIENTRY
_mesa_IsImageHandleResidentARB(GLuint64 handle)
{
- return GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) &&
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
|| instead of &&

Cheers,
Nicolai
Post by Samuel Pitoiset
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsImageHandleResidentARB(unsupported)");
+ return GL_FALSE;
+ }
+
+ *
+ * "The error INVALID_OPERATION will be generated by
+ * IsTextureHandleResidentARB and IsImageHandleResidentARB if <handle> is
+ * not a valid texture or image handle, respectively."
+ */
+ if (!lookup_image_handle(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsImageHandleResidentARB(handle)");
+ return GL_FALSE;
+ }
+
+ return is_image_handle_resident(ctx, handle);
}
diff --git a/src/mesa/main/texturebindless.h b/src/mesa/main/texturebindless.h
index 88b84ce275..bdee74121e 100644
--- a/src/mesa/main/texturebindless.h
+++ b/src/mesa/main/texturebindless.h
@@ -31,6 +31,34 @@ extern "C" {
#endif
/**
+ * \name Internal functions
+ */
+
+void
+_mesa_init_resident_handles(struct gl_context *ctx);
+
+void
+_mesa_free_resident_handles(struct gl_context *ctx);
+
+void
+_mesa_init_texture_handles(struct gl_texture_object *texObj);
+void
+_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
+ struct gl_texture_object *texObj);
+void
+_mesa_delete_texture_handles(struct gl_context *ctx,
+ struct gl_texture_object *texObj);
+
+void
+_mesa_init_sampler_handles(struct gl_sampler_object *sampObj);
+void
+_mesa_delete_sampler_handles(struct gl_context *ctx,
+ struct gl_sampler_object *sampObj);
+
+
+/**
* \name API functions
*/
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
Samuel Pitoiset
2017-05-23 12:03:52 UTC
Permalink
Post by Nicolai Hähnle
Post by Samuel Pitoiset
---
src/mesa/main/context.c | 3 +
src/mesa/main/dd.h | 17 +
src/mesa/main/mtypes.h | 34 ++
src/mesa/main/samplerobj.c | 6 +
src/mesa/main/shared.c | 12 +
src/mesa/main/texobj.c | 12 +
src/mesa/main/texturebindless.c | 827
+++++++++++++++++++++++++++++++++++++++-
src/mesa/main/texturebindless.h | 28 ++
8 files changed, 934 insertions(+), 5 deletions(-)
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 3570f94f5a..5321886a95 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -133,6 +133,7 @@
#include "varray.h"
#include "version.h"
#include "viewport.h"
+#include "texturebindless.h"
#include "program/program.h"
#include "math/m_matrix.h"
#include "main/dispatch.h" /* for _gloffset_COUNT */
@@ -855,6 +856,7 @@ init_attrib_groups(struct gl_context *ctx)
_mesa_init_transform_feedback( ctx );
_mesa_init_varray( ctx );
_mesa_init_viewport( ctx );
+ _mesa_init_resident_handles( ctx );
if (!_mesa_init_texture( ctx ))
return GL_FALSE;
@@ -1339,6 +1341,7 @@ _mesa_free_context_data( struct gl_context *ctx )
_mesa_free_transform_feedback(ctx);
_mesa_free_performance_monitors(ctx);
_mesa_free_performance_queries(ctx);
+ _mesa_free_resident_handles(ctx);
_mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
_mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index a9ca43d69e..d830f5184d 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -1050,6 +1050,23 @@ struct dd_function_table {
GLintptr offset, GLsizeiptr size,
GLboolean commit);
+
+ /**
+ * \name GL_ARB_bindless_texture interface
+ */
+ GLuint64 (*NewTextureHandle)(struct gl_context *ctx,
+ struct gl_texture_object *texObj,
+ struct gl_sampler_object *sampObj);
+ void (*DeleteTextureHandle)(struct gl_context *ctx, GLuint64 handle);
+ void (*MakeTextureHandleResident)(struct gl_context *ctx, GLuint64 handle,
+ bool resident);
+ GLuint64 (*NewImageHandle)(struct gl_context *ctx,
+ struct gl_image_unit *imgObj);
+ void (*DeleteImageHandle)(struct gl_context *ctx, GLuint64 handle);
+ void (*MakeImageHandleResident)(struct gl_context *ctx, GLuint64 handle,
+ GLenum access, bool resident);
};
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index efc6920254..70865b373d 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -987,6 +987,9 @@ struct gl_sampler_object
GLenum CompareFunc; /**< GL_ARB_shadow */
GLenum sRGBDecode; /**< GL_DECODE_EXT or
GL_SKIP_DECODE_EXT */
GLboolean CubeMapSeamless; /**<
GL_AMD_seamless_cubemap_per_texture */
+ bool HandleAllocated; /**< GL_ARB_bindless_texture */
+
+ struct hash_table *Handles;
};
@@ -1034,6 +1037,8 @@ struct gl_texture_object
GLuint NumLevels; /**< GL_ARB_texture_view */
GLuint NumLayers; /**< GL_ARB_texture_view */
+ GLboolean HandleAllocated; /**< GL_ARB_bindless_texture */
+
/** Actual texture images, indexed by [cube face] and [mipmap level] */
struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS];
@@ -1051,6 +1056,10 @@ struct gl_texture_object
/** GL_ARB_shader_image_load_store */
GLenum ImageFormatCompatibilityType;
+
+ /** GL_ARB_bindless_texture */
+ struct hash_table *SamplerHandles;
+ struct hash_table *ImageHandles;
};
@@ -1390,6 +1399,7 @@ struct gl_buffer_object
GLboolean Written; /**< Ever written to? (for debugging) */
GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */
GLboolean Immutable; /**< GL_ARB_buffer_storage */
+ GLboolean HandleAllocated; /**< GL_ARB_bindless_texture */
Should be consistent with gl_sampler_object in terms of type (and
gl_texture_object as well). Which type? Since the state is not
API-visible, bool is justifiable.
Correct.
Post by Nicolai Hähnle
Post by Samuel Pitoiset
gl_buffer_usage UsageHistory; /**< How has this buffer been used so far? */
/** Counters used for buffer usage warnings */
@@ -3203,6 +3213,11 @@ struct gl_shared_state
/** GL_ARB_sampler_objects */
struct _mesa_HashTable *SamplerObjects;
+ /* GL_ARB_bindless_texture */
+ struct hash_table *TextureHandles;
+ struct hash_table *ImageHandles;
+ mtx_t HandlesMutex; /**< For texture/image handles safety */
+
/**
* Some context in this share group was affected by a GPU reset
*
@@ -4488,6 +4503,17 @@ struct gl_subroutine_index_binding
GLuint *IndexPtr;
};
+struct gl_texture_handle_object
+{
+ struct gl_texture_object *texObj;
+ struct gl_sampler_object *sampObj;
+};
+
+struct gl_image_handle_object
+{
+ struct gl_image_unit imgObj;
+};
+
/**
* Mesa rendering context.
*
@@ -4842,6 +4868,14 @@ struct gl_context
GLfloat PrimitiveBoundingBox[8];
struct disk_cache *Cache;
+
+ /**
+ * \name GL_ARB_bindless_texture
+ */
+ struct hash_table *ResidentTextureHandles;
+ struct hash_table *ResidentImageHandles;
};
/**
diff --git a/src/mesa/main/samplerobj.c b/src/mesa/main/samplerobj.c
index 63beaf1abb..ee15c68b4f 100644
--- a/src/mesa/main/samplerobj.c
+++ b/src/mesa/main/samplerobj.c
@@ -38,6 +38,7 @@
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/samplerobj.h"
+#include "main/texturebindless.h"
struct gl_sampler_object *
@@ -61,6 +62,7 @@ static void
delete_sampler_object(struct gl_context *ctx,
struct gl_sampler_object *sampObj)
{
+ _mesa_delete_sampler_handles(ctx, sampObj);
mtx_destroy(&sampObj->Mutex);
free(sampObj->Label);
free(sampObj);
@@ -132,6 +134,10 @@ _mesa_init_sampler_object(struct
gl_sampler_object *sampObj, GLuint name)
sampObj->CompareFunc = GL_LEQUAL;
sampObj->sRGBDecode = GL_DECODE_EXT;
sampObj->CubeMapSeamless = GL_FALSE;
+ sampObj->HandleAllocated = GL_FALSE;
+
+ /* GL_ARB_bindless_texture */
+ _mesa_init_sampler_handles(sampObj);
}
/**
diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c
index 5344812738..b188287a08 100644
--- a/src/mesa/main/shared.c
+++ b/src/mesa/main/shared.c
@@ -84,6 +84,13 @@ _mesa_alloc_shared_state(struct gl_context *ctx)
/* GL_ARB_sampler_objects */
shared->SamplerObjects = _mesa_NewHashTable();
+ /* GL_ARB_bindless_texture */
+ shared->TextureHandles = _mesa_hash_table_create(NULL,
_mesa_hash_pointer,
+
_mesa_key_pointer_equal);
+ shared->ImageHandles = _mesa_hash_table_create(NULL,
_mesa_hash_pointer,
+
_mesa_key_pointer_equal);
+ mtx_init(&shared->HandlesMutex, mtx_recursive);
+
/* Allocate the default buffer object */
shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0);
@@ -373,6 +380,11 @@ free_shared_state(struct gl_context *ctx, struct
gl_shared_state *shared)
_mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx);
_mesa_DeleteHashTable(shared->TexObjects);
+ /* Bindless texture/image handles */
+ _mesa_hash_table_destroy(shared->TextureHandles, NULL);
+ _mesa_hash_table_destroy(shared->ImageHandles, NULL);
+ mtx_destroy(&shared->HandlesMutex);
+
mtx_destroy(&shared->Mutex);
mtx_destroy(&shared->TexMutex);
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index 868e4eb7a2..13a24f6deb 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -43,6 +43,7 @@
#include "texstate.h"
#include "mtypes.h"
#include "program/prog_instruction.h"
+#include "texturebindless.h"
@@ -311,6 +312,7 @@ _mesa_initialize_texture_object( struct gl_context *ctx,
obj->DepthMode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE;
obj->StencilSampling = false;
obj->Sampler.CubeMapSeamless = GL_FALSE;
+ obj->Sampler.HandleAllocated = GL_FALSE;
obj->Swizzle[0] = GL_RED;
obj->Swizzle[1] = GL_GREEN;
obj->Swizzle[2] = GL_BLUE;
@@ -320,6 +322,9 @@ _mesa_initialize_texture_object( struct gl_context *ctx,
obj->BufferObjectFormat = GL_R8;
obj->_BufferObjectFormat = MESA_FORMAT_R_UNORM8;
obj->ImageFormatCompatibilityType =
GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE;
+
+ /* GL_ARB_bindless_texture */
+ _mesa_init_texture_handles(obj);
}
@@ -397,6 +402,9 @@ _mesa_delete_texture_object(struct gl_context *ctx,
}
}
+ /* Delete all texture/image handles. */
+ _mesa_delete_texture_handles(ctx, texObj);
+
_mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL);
/* destroy the mutex -- it may have allocated memory (eg on bsd) */
@@ -1461,6 +1469,10 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
*/
unbind_texobj_from_image_units(ctx, delObj);
+ /* Make all handles that reference this texture object non-resident
+ * in the current context. */
+ _mesa_make_texture_handles_non_resident(ctx, delObj);
+
_mesa_unlock_texture(ctx, delObj);
ctx->NewState |= _NEW_TEXTURE_OBJECT;
diff --git a/src/mesa/main/texturebindless.c
b/src/mesa/main/texturebindless.c
index 4d9c22d428..0c6f9c3fc9 100644
--- a/src/mesa/main/texturebindless.c
+++ b/src/mesa/main/texturebindless.c
@@ -29,57 +29,874 @@
#include "mtypes.h"
#include "texobj.h"
#include "texturebindless.h"
+#include "shaderimage.h"
+#include "teximage.h"
+#include "hash.h"
#include "util/set.h"
#include "util/hash_table.h"
+/**
+ * Return the gl_texture_handle_object for a given 64bit handle.
+ */
+static struct gl_texture_handle_object *
+lookup_texture_handle(struct gl_context *ctx, GLuint64 id)
+{
+ struct hash_entry *entry;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(ctx->Shared->TextureHandles, (void *)id);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return entry ? (struct gl_texture_handle_object *)entry->data : NULL;
+}
+
+/**
+ * Return the gl_image_handle_object for a given 64bit handle.
+ */
+static struct gl_image_handle_object *
+lookup_image_handle(struct gl_context *ctx, GLuint64 id)
+{
+ struct hash_entry *entry;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(ctx->Shared->ImageHandles, (void *)id);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return entry ? (struct gl_image_handle_object *)entry->data : NULL;
+}
+
+/**
+ * Delete a texture handle in the shared state.
+ */
+static void
+delete_texture_handle(struct gl_context *ctx, GLuint64 id)
+{
+ struct hash_entry *entry;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(ctx->Shared->TextureHandles, (void *)id);
+ _mesa_hash_table_remove(ctx->Shared->TextureHandles, entry);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+}
+
+/**
+ * Delete an image handle in the shared state.
+ */
+static void
+delete_image_handle(struct gl_context *ctx, GLuint64 id)
+{
+ struct hash_entry *entry;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(ctx->Shared->ImageHandles, (void *)id);
+ _mesa_hash_table_remove(ctx->Shared->ImageHandles, entry);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+}
+
+/**
+ * Return TRUE if the texture handle is resident in the current context.
+ */
+static inline bool
+is_texture_handle_resident(struct gl_context *ctx, GLuint64 handle)
+{
+ return _mesa_hash_table_search(ctx->ResidentTextureHandles,
+ (void *)handle) != NULL;
+}
+
+/**
+ * Return TRUE if the image handle is resident in the current context.
+ */
+static inline bool
+is_image_handle_resident(struct gl_context *ctx, GLuint64 handle)
+{
+ return _mesa_hash_table_search(ctx->ResidentImageHandles,
+ (void *)handle) != NULL;
+}
+
+/**
+ * Set a texture handle resident/non-resident in the current context.
+ */
+static void
+make_texture_handle_resident(struct gl_context *ctx,
+ struct gl_texture_handle_object *handleObj,
+ GLuint64 handle, bool resident)
+{
+ if (resident) {
+ struct gl_sampler_object *sampObj = NULL;
+ struct gl_texture_object *texObj = NULL;
+
+ _mesa_hash_table_insert(ctx->ResidentTextureHandles,
+ (void *)handle, handleObj);
+
+ ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_TRUE);
+
+ /* Reference the texture object (and the separate sampler if needed) to
+ * be sure it won't be deleted until it is not bound anywhere and there
+ * are no handles using the object that are resident in any context. */
+ _mesa_reference_texobj(&texObj, handleObj->texObj);
+ if (handleObj->sampObj)
+ _mesa_reference_sampler_object(ctx, &sampObj,
handleObj->sampObj);
+ } else {
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(ctx->ResidentTextureHandles,
+ (void *)handle);
+ _mesa_hash_table_remove(ctx->ResidentTextureHandles, entry);
+
+ ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_FALSE);
+
+ /* Unreference the texture object (and the separate sampler if needed),
+ * if refcount hits zero, the texture and all handles will be deleted. */
+ _mesa_reference_texobj(&handleObj->texObj, NULL);
+ if (handleObj->sampObj)
+ _mesa_reference_sampler_object(ctx, &handleObj->sampObj, NULL);
+ }
+}
+
+/**
+ * Set an image handle resident/non-resident in the current context.
+ */
+static void
+make_image_handle_resident(struct gl_context *ctx,
+ struct gl_image_handle_object *handleObj,
+ GLuint64 handle, GLenum access, bool resident)
+{
+ if (resident) {
+ struct gl_texture_object *texObj = NULL;
+
+ _mesa_hash_table_insert(ctx->ResidentImageHandles,
+ (void *)handle, handleObj);
+
+ ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_TRUE);
+
+ /* Reference the texture object to be sure it won't be deleted until it
+ * is not bound anywhere and there are no handles using the object that
+ * are resident in any context. */
+ _mesa_reference_texobj(&texObj, handleObj->imgObj.TexObj);
+ } else {
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(ctx->ResidentImageHandles,
+ (void *)handle);
+ _mesa_hash_table_remove(ctx->ResidentImageHandles, entry);
+
+ ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_FALSE);
+
+ /* Unreference the texture object, if refcount hits zero, the texture and
+ * all handles will be deleted. */
+ _mesa_reference_texobj(&handleObj->imgObj.TexObj, NULL);
+ }
+}
+
+static GLuint64
+get_texture_handle(struct gl_context *ctx, struct gl_texture_object *texObj,
+ struct gl_sampler_object *sampObj)
+{
+ struct gl_texture_handle_object *handleObj;
+ struct hash_entry *entry;
+ GLuint64 handle;
+
+ handleObj = CALLOC_STRUCT(gl_texture_handle_object);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
+ return 0;
+ }
+
+ handleObj->texObj = texObj;
+ if (&texObj->Sampler != sampObj)
+ handleObj->sampObj = sampObj;
+
+ *
+ * "The handle for each texture or texture/sampler pair is unique; the same
+ * handle will be returned if GetTextureHandleARB is called multiple times
+ * for the same texture or if GetTextureSamplerHandleARB is called multiple
+ * times for the same texture/sampler pair."
+ */
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(texObj->SamplerHandles, handleObj);
+ if (entry) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ return (uint64_t)entry->data;
+ }
+
+ /* Ask the driver for a new handle and store it. */
+ handle = ctx->Driver.NewTextureHandle(ctx, texObj, sampObj);
+ if (!handle) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
+ return 0;
+ }
+
+ _mesa_hash_table_insert(texObj->SamplerHandles, handleObj, (void *)handle);
+
+ if (&texObj->Sampler != sampObj) {
+ _mesa_hash_table_insert(sampObj->Handles, handleObj,
+ (void *)handle);
+ }
+
+ /* When referenced by one or more handles, texture objects are immutable. */
+ texObj->HandleAllocated = true;
+ sampObj->HandleAllocated = true;
+ if (texObj->Target == GL_TEXTURE_BUFFER)
+ texObj->BufferObject->HandleAllocated = true;
+
+ /* Store the handle in the shared state for all contexts. */
+ _mesa_hash_table_insert(ctx->Shared->TextureHandles,
+ (void *)handle, handleObj);
This won't work on 32-bit systems (same for image handles).
Because the handle is 64-bit? Mmh...
Post by Nicolai Hähnle
Post by Samuel Pitoiset
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return (GLuint64)handle;
+}
+
+static GLuint64
+get_image_handle(struct gl_context *ctx, struct gl_texture_object *texObj,
+ GLint level, GLboolean layered, GLint layer, GLenum format)
+{
+ struct gl_image_handle_object *handleObj;
+ struct gl_image_unit *imgObj;
+ struct hash_entry *entry;
+ GLuint64 handle;
+
+ handleObj = CALLOC_STRUCT(gl_image_handle_object);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
+ return 0;
+ }
+
+ imgObj = &handleObj->imgObj;
+ imgObj->TexObj = texObj; /* weak reference */
+ imgObj->Level = level;
+ imgObj->Access = GL_READ_WRITE;
+ imgObj->Format = format;
+ imgObj->_ActualFormat = _mesa_get_shader_image_format(format);
+
+ if (_mesa_tex_target_is_layered(texObj->Target)) {
+ imgObj->Layered = layered;
+ imgObj->Layer = layer;
+ imgObj->_Layer = (imgObj->Layered ? 0 : imgObj->Layer);
+ } else {
+ imgObj->Layered = GL_FALSE;
+ imgObj->Layer = 0;
+ }
+
+ *
+ * "The handle returned for each combination of <texture>, <level>,
+ * <layered>, <layer>, and <format> is unique; the same handle will be
+ * returned if GetImageHandleARB is called multiple times with the same
+ * parameters."
+ */
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(texObj->ImageHandles, handleObj);
+ if (entry) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ return (uint64_t)entry->data;
+ }
+
+ /* Ask the driver for a new handle and store it. */
+ handle = ctx->Driver.NewImageHandle(ctx, &handleObj->imgObj);
+ if (!handle) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
+ return 0;
+ }
+
+ _mesa_hash_table_insert(texObj->ImageHandles, handleObj, (void *)handle);
+
+ /* When referenced by one or more handles, texture objects are immutable. */
+ texObj->HandleAllocated = true;
+ if (texObj->Target == GL_TEXTURE_BUFFER)
+ texObj->BufferObject->HandleAllocated = true;
+ texObj->Sampler.HandleAllocated = true;
+
+ /* Store the handle in the shared state for all contexts. */
+ _mesa_hash_table_insert(ctx->Shared->ImageHandles,
+ (void *)handle, handleObj);
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+
+ return (GLuint64)handle;
+}
+
+void
+_mesa_init_resident_handles(struct gl_context *ctx)
+{
+ ctx->ResidentTextureHandles =
+ _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ ctx->ResidentImageHandles =
+ _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+}
+
+void
+_mesa_free_resident_handles(struct gl_context *ctx)
+{
+ _mesa_hash_table_destroy(ctx->ResidentTextureHandles, NULL);
+ _mesa_hash_table_destroy(ctx->ResidentImageHandles, NULL);
+}
+
+static uint32_t
+texture_handle_key_hash(const void *key)
+{
+ return _mesa_hash_data(key, sizeof(struct gl_texture_handle_object));
+}
+
+static bool
+texture_handle_key_equals(const void *a, const void *b)
+{
+ struct gl_texture_handle_object *aa = (struct
gl_texture_handle_object *)a;
+ struct gl_texture_handle_object *bb = (struct
gl_texture_handle_object *)b;
+
+ return !memcmp(aa, bb, sizeof(struct gl_texture_handle_object));
+}
+
+static uint32_t
+image_handle_key_hash(const void *key)
+{
+ return _mesa_hash_data(key, sizeof(struct gl_image_handle_object));
+}
+
+static bool
+image_handle_key_equals(const void *a, const void *b)
+{
+ struct gl_image_handle_object *aa = (struct gl_image_handle_object *)a;
+ struct gl_image_handle_object *bb = (struct gl_image_handle_object *)b;
+
+ return !memcmp(aa, bb, sizeof(struct gl_image_handle_object));
+}
+
+void
+_mesa_init_texture_handles(struct gl_texture_object *texObj)
+{
+ texObj->SamplerHandles =
+ _mesa_hash_table_create(NULL, texture_handle_key_hash,
+ texture_handle_key_equals);
+ texObj->ImageHandles =
+ _mesa_hash_table_create(NULL, image_handle_key_hash,
+ image_handle_key_equals);
+}
+
+void
+_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
+{
+ struct hash_entry *entry;
+ GLuint64 handle;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+
+ hash_table_foreach(texObj->SamplerHandles, entry) {
+ struct gl_texture_handle_object *handleObj =
+ (struct gl_texture_handle_object *)entry->key;
+
+ handle = (uint64_t)entry->data;
+ if (is_texture_handle_resident(ctx, handle))
+ make_texture_handle_resident(ctx, handleObj, handle, false);
+ }
+
+ hash_table_foreach(texObj->ImageHandles, entry) {
+ struct gl_image_handle_object *handleObj =
+ (struct gl_image_handle_object *)entry->key;
+
+ handle = (uint64_t)entry->data;
+ if (is_image_handle_resident(ctx, handle))
+ make_image_handle_resident(ctx, handleObj, handle,
GL_READ_ONLY, false);
+ }
So... this also needs to loop through all other contexts and make the
handle non-resident in them, right? Otherwise you might end up with
dangling pointers (or at least dangling handles).
No. Resident handles are per-context. Though, I'm not very happy myself
with the way I managed the handles. I'm open to any better suggestions.
Post by Nicolai Hähnle
Post by Samuel Pitoiset
+
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+}
+
+void
+_mesa_delete_texture_handles(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
+{
+ struct hash_entry *entry;
+
+ hash_table_foreach(texObj->SamplerHandles, entry) {
+ struct gl_texture_handle_object *handleObj =
+ (struct gl_texture_handle_object *)entry->key;
+ GLuint64 handle = (GLuint64)entry->data;
+
+ ctx->Driver.DeleteTextureHandle(ctx, handle);
+
+ delete_texture_handle(ctx, handle);
+ free(handleObj);
+ }
+
+ hash_table_foreach(texObj->ImageHandles, entry) {
+ struct gl_image_handle_object *handleObj =
+ (struct gl_image_handle_object *)entry->key;
+ GLuint64 handle = (GLuint64)entry->data;
+
+ ctx->Driver.DeleteImageHandle(ctx, handle);
+
+ delete_image_handle(ctx, handle);
+ free(handleObj);
+ }
+
+ _mesa_hash_table_destroy(texObj->SamplerHandles, NULL);
+ _mesa_hash_table_destroy(texObj->ImageHandles, NULL);
+}
+
+void
+_mesa_init_sampler_handles(struct gl_sampler_object *sampObj)
+{
+ sampObj->Handles = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+}
+
+void
+_mesa_delete_sampler_handles(struct gl_context *ctx,
+ struct gl_sampler_object *sampObj)
+{
+ struct hash_entry *entry;
+
+ hash_table_foreach(sampObj->Handles, entry) {
+ GLuint64 handle = (GLuint64)entry->data;
+
+ ctx->Driver.DeleteTextureHandle(ctx, handle);
+
+ delete_texture_handle(ctx, handle);
+ }
+
+ _mesa_hash_table_destroy(sampObj->Handles, NULL);
+}
+
+static GLboolean
+is_sampler_border_color_valid(struct gl_sampler_object *samp)
+{
+ static const GLfloat valid_float_border_colors[4][4] = {
+ { 0.0, 0.0, 0.0, 0.0 },
+ { 0.0, 0.0, 0.0, 1.0 },
+ { 1.0, 1.0, 1.0, 0.0 },
+ { 1.0, 1.0, 1.0, 1.0 },
+ };
+ static const GLint valid_integer_border_colors[4][4] = {
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 1 },
+ { 1, 1, 1, 0 },
+ { 1, 1, 1, 1 },
+ };
+ size_t size = sizeof(samp->BorderColor.ui);
+
+ *
+ * "The error INVALID_OPERATION is generated if the border color (taken from
+ * the embedded sampler for GetTextureHandleARB or from the <sampler> for
+ * GetTextureSamplerHandleARB) is not one of the following allowed values.
+ * If the texture's base internal format is signed or unsigned integer,
+ * allowed values are (0,0,0,0), (0,0,0,1), (1,1,1,0), and (1,1,1,1). If
+ * the base internal format is not integer, allowed values are
+ * (0.0,0.0,0.0,0.0), (0.0,0.0,0.0,1.0), (1.0,1.0,1.0,0.0), and
+ * (1.0,1.0,1.0,1.0)."
+ */
+ if (!memcmp(samp->BorderColor.f, valid_float_border_colors[0], size) ||
+ !memcmp(samp->BorderColor.f, valid_float_border_colors[1], size) ||
+ !memcmp(samp->BorderColor.f, valid_float_border_colors[2], size) ||
+ !memcmp(samp->BorderColor.f, valid_float_border_colors[3], size))
+ return GL_TRUE;
+
+ if (!memcmp(samp->BorderColor.ui, valid_integer_border_colors[0], size) ||
+ !memcmp(samp->BorderColor.ui, valid_integer_border_colors[1], size) ||
+ !memcmp(samp->BorderColor.ui, valid_integer_border_colors[2], size) ||
+ !memcmp(samp->BorderColor.ui, valid_integer_border_colors[3], size))
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
GLuint64 GLAPIENTRY
_mesa_GetTextureHandleARB(GLuint texture)
{
- return 0;
+ struct gl_texture_object *texObj = NULL;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureHandleARB(unsupported)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_VALUE is generated by GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if <texture> is zero or not the name of an
+ * existing texture object."
+ */
+ if (texture > 0)
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
"glGetTextureHandleARB(texture)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by
GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if the texture object specified by <texture>
+ * is not complete."
+ */
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureHandleARB(incomplete texture)");
+ return 0;
+ }
+ }
+
+ if (!is_sampler_border_color_valid(&texObj->Sampler)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureHandleARB(invalid border color)");
+ return 0;
+ }
+
+ return get_texture_handle(ctx, texObj, &texObj->Sampler);
}
GLuint64 GLAPIENTRY
_mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler)
{
- return 0;
+ struct gl_texture_object *texObj = NULL;
+ struct gl_sampler_object *sampObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureSamplerHandleARB(unsupported)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_VALUE is generated by GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if <texture> is zero or not the name of an
+ * existing texture object."
+ */
+ if (texture > 0)
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetTextureSamplerHandleARB(texture)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_VALUE is generated by
GetTextureSamplerHandleARB if
+ * <sampler> is zero or is not the name of an existing sampler object."
+ */
+ sampObj = _mesa_lookup_samplerobj(ctx, sampler);
+ if (!sampObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetTextureSamplerHandleARB(sampler)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by
GetTextureHandleARB or
+ * GetTextureSamplerHandleARB if the texture object specified by <texture>
+ * is not complete."
+ */
+ if (!_mesa_is_texture_complete(texObj, sampObj)) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (!_mesa_is_texture_complete(texObj, sampObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureSamplerHandleARB(incomplete texture)");
+ return 0;
+ }
+ }
+
+ if (!is_sampler_border_color_valid(sampObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTextureSamplerHandleARB(invalid border color)");
+ return 0;
+ }
+
+ return get_texture_handle(ctx, texObj, sampObj);
}
void GLAPIENTRY
_mesa_MakeTextureHandleResidentARB(GLuint64 handle)
{
+ struct gl_texture_handle_object *handleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleResidentARB(unsupported)");
+ return;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by
MakeTextureHandleResidentARB
+ * if <handle> is not a valid texture handle, or if <handle> is already
+ * resident in the current GL context."
+ */
+ handleObj = lookup_texture_handle(ctx, handle);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleResidentARB(handle)");
+ return;
+ }
+
+ if (is_texture_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleResidentARB(already resident)");
+ return;
+ }
+
+ make_texture_handle_resident(ctx, handleObj, handle, true);
}
void GLAPIENTRY
_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle)
{
+ struct gl_texture_handle_object *handleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleNonResidentARB(unsupported)");
+ return;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by
+ * MakeTextureHandleNonResidentARB if <handle> is not a valid texture
+ * handle, or if <handle> is not resident in the current GL context."
+ */
+ handleObj = lookup_texture_handle(ctx, handle);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleNonResidentARB(handle)");
+ return;
+ }
+
+ if (!is_texture_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeTextureHandleNonResidentARB(not resident)");
+ return;
+ }
+
+ make_texture_handle_resident(ctx, handleObj, handle, false);
}
GLuint64 GLAPIENTRY
_mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
GLint layer, GLenum format)
{
- return 0;
+ struct gl_texture_object *texObj = NULL;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) &&
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
|| instead of &&
Right.
Post by Nicolai Hähnle
Post by Samuel Pitoiset
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetImageHandleARB(unsupported)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_VALUE is generated by GetImageHandleARB if <texture>
+ * is zero or not the name of an existing texture object, if the image for
+ * <level> does not existing in <texture>, or if <layered> is FALSE and
+ * <layer> is greater than or equal to the number of layers in the image at
+ * <level>."
+ */
+ if (texture > 0)
+ texObj = _mesa_lookup_texture(ctx, texture);
+
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
"glGetImageHandleARB(texture)");
+ return 0;
+ }
+
+ if (level < 0 || level >= _mesa_max_texture_levels(ctx,
texObj->Target)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(level)");
+ return 0;
+ }
+
+ if (!layered && layer > _mesa_get_texture_layers(texObj, level)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(layer)");
+ return 0;
+ }
+
+ if (!_mesa_is_shader_image_format_supported(ctx, format)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(format)");
+ return 0;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by GetImageHandleARB if the
+ * texture object <texture> is not complete or if <layered> is TRUE and
+ * <texture> is not a three-dimensional, one-dimensional array, two
+ * dimensional array, cube map, or cube map array texture."
+ */
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetImageHandleARB(incomplete texture)");
+ return 0;
+ }
+ }
+
+ if (layered && !_mesa_tex_target_is_layered(texObj->Target)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetImageHandleARB(not layered)");
+ return 0;
+ }
+
+ return get_image_handle(ctx, texObj, level, layered, layer, format);
}
void GLAPIENTRY
_mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access)
{
+ struct gl_image_handle_object *handleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) &&
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
|| instead of &&
Post by Samuel Pitoiset
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleResidentARB(unsupported)");
+ return;
+ }
+
+ if (access != GL_READ_ONLY &&
+ access != GL_WRITE_ONLY &&
+ access != GL_READ_WRITE) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glMakeImageHandleResidentARB(access)");
+ return;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by
MakeImageHandleResidentARB
+ * if <handle> is not a valid image handle, or if <handle> is already
+ * resident in the current GL context."
+ */
+ handleObj = lookup_image_handle(ctx, handle);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleResidentARB(handle)");
+ return;
+ }
+
+ if (is_image_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleResidentARB(already resident)");
+ return;
+ }
+
+ make_image_handle_resident(ctx, handleObj, handle, access, true);
}
void GLAPIENTRY
_mesa_MakeImageHandleNonResidentARB(GLuint64 handle)
{
+ struct gl_image_handle_object *handleObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) &&
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
|| vs. &&
Post by Samuel Pitoiset
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleNonResidentARB(unsupported)");
+ return;
+ }
+
+ *
+ * "The error INVALID_OPERATION is generated by
+ * MakeImageHandleNonResidentARB if <handle> is not a valid image handle,
+ * or if <handle> is not resident in the current GL context."
+ */
+ handleObj = lookup_image_handle(ctx, handle);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleNonResidentARB(handle)");
+ return;
+ }
+
+ if (!is_image_handle_resident(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMakeImageHandleNonResidentARB(not resident)");
+ return;
+ }
+
+ make_image_handle_resident(ctx, handleObj, handle, GL_READ_ONLY, false);
}
GLboolean GLAPIENTRY
_mesa_IsTextureHandleResidentARB(GLuint64 handle)
{
- return GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsTextureHandleResidentARB(unsupported)");
+ return GL_FALSE;
+ }
+
+ *
+ * "The error INVALID_OPERATION will be generated by
+ * IsTextureHandleResidentARB and IsImageHandleResidentARB if <handle> is
+ * not a valid texture or image handle, respectively."
+ */
+ if (!lookup_texture_handle(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsTextureHandleResidentARB(handle)");
+ return GL_FALSE;
+ }
+
+ return is_texture_handle_resident(ctx, handle);
}
GLboolean GLAPIENTRY
_mesa_IsImageHandleResidentARB(GLuint64 handle)
{
- return GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_has_ARB_bindless_texture(ctx) &&
+ !_mesa_has_ARB_shader_image_load_store(ctx)) {
|| instead of &&
Cheers,
Nicolai
Post by Samuel Pitoiset
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsImageHandleResidentARB(unsupported)");
+ return GL_FALSE;
+ }
+
+ *
+ * "The error INVALID_OPERATION will be generated by
+ * IsTextureHandleResidentARB and IsImageHandleResidentARB if <handle> is
+ * not a valid texture or image handle, respectively."
+ */
+ if (!lookup_image_handle(ctx, handle)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsImageHandleResidentARB(handle)");
+ return GL_FALSE;
+ }
+
+ return is_image_handle_resident(ctx, handle);
}
diff --git a/src/mesa/main/texturebindless.h
b/src/mesa/main/texturebindless.h
index 88b84ce275..bdee74121e 100644
--- a/src/mesa/main/texturebindless.h
+++ b/src/mesa/main/texturebindless.h
@@ -31,6 +31,34 @@ extern "C" {
#endif
/**
+ * \name Internal functions
+ */
+
+void
+_mesa_init_resident_handles(struct gl_context *ctx);
+
+void
+_mesa_free_resident_handles(struct gl_context *ctx);
+
+void
+_mesa_init_texture_handles(struct gl_texture_object *texObj);
+void
+_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
+ struct gl_texture_object *texObj);
+void
+_mesa_delete_texture_handles(struct gl_context *ctx,
+ struct gl_texture_object *texObj);
+
+void
+_mesa_init_sampler_handles(struct gl_sampler_object *sampObj);
+void
+_mesa_delete_sampler_handles(struct gl_context *ctx,
+ struct gl_sampler_object *sampObj);
+
+
+/**
* \name API functions
*/
Samuel Pitoiset
2017-05-26 12:09:23 UTC
Permalink
[snip]
Post by Samuel Pitoiset
Post by Nicolai Hähnle
Post by Samuel Pitoiset
+static GLuint64
+get_texture_handle(struct gl_context *ctx, struct gl_texture_object *texObj,
+ struct gl_sampler_object *sampObj)
+{
+ struct gl_texture_handle_object *handleObj;
+ struct hash_entry *entry;
+ GLuint64 handle;
+
+ handleObj = CALLOC_STRUCT(gl_texture_handle_object);
+ if (!handleObj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
+ return 0;
+ }
+
+ handleObj->texObj = texObj;
+ if (&texObj->Sampler != sampObj)
+ handleObj->sampObj = sampObj;
+
+ *
+ * "The handle for each texture or texture/sampler pair is unique; the same
+ * handle will be returned if GetTextureHandleARB is called multiple times
+ * for the same texture or if GetTextureSamplerHandleARB is called multiple
+ * times for the same texture/sampler pair."
+ */
+ mtx_lock(&ctx->Shared->HandlesMutex);
+ entry = _mesa_hash_table_search(texObj->SamplerHandles, handleObj);
+ if (entry) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ return (uint64_t)entry->data;
+ }
+
+ /* Ask the driver for a new handle and store it. */
+ handle = ctx->Driver.NewTextureHandle(ctx, texObj, sampObj);
+ if (!handle) {
+ mtx_unlock(&ctx->Shared->HandlesMutex);
+ free(handleObj);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
+ return 0;
+ }
+
+ _mesa_hash_table_insert(texObj->SamplerHandles, handleObj, (void *)handle);
+
+ if (&texObj->Sampler != sampObj) {
+ _mesa_hash_table_insert(sampObj->Handles, handleObj,
+ (void *)handle);
+ }
+
+ /* When referenced by one or more handles, texture objects are immutable. */
+ texObj->HandleAllocated = true;
+ sampObj->HandleAllocated = true;
+ if (texObj->Target == GL_TEXTURE_BUFFER)
+ texObj->BufferObject->HandleAllocated = true;
+
+ /* Store the handle in the shared state for all contexts. */
+ _mesa_hash_table_insert(ctx->Shared->TextureHandles,
+ (void *)handle, handleObj);
This won't work on 32-bit systems (same for image handles).
Because the handle is 64-bit? Mmh...
Right.
[snip]
Post by Samuel Pitoiset
Post by Nicolai Hähnle
Post by Samuel Pitoiset
+void
+_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
+{
+ struct hash_entry *entry;
+ GLuint64 handle;
+
+ mtx_lock(&ctx->Shared->HandlesMutex);
+
+ hash_table_foreach(texObj->SamplerHandles, entry) {
+ struct gl_texture_handle_object *handleObj =
+ (struct gl_texture_handle_object *)entry->key;
+
+ handle = (uint64_t)entry->data;
+ if (is_texture_handle_resident(ctx, handle))
+ make_texture_handle_resident(ctx, handleObj, handle, false);
+ }
+
+ hash_table_foreach(texObj->ImageHandles, entry) {
+ struct gl_image_handle_object *handleObj =
+ (struct gl_image_handle_object *)entry->key;
+
+ handle = (uint64_t)entry->data;
+ if (is_image_handle_resident(ctx, handle))
+ make_image_handle_resident(ctx, handleObj, handle, GL_READ_ONLY, false);
+ }
So... this also needs to loop through all other contexts and make the
handle non-resident in them, right? Otherwise you might end up with
dangling pointers (or at least dangling handles).
No. Resident handles are per-context. Though, I'm not very happy
myself with the way I managed the handles. I'm open to any better
suggestions.
Right, resident handles are per-context, but the handles of a texture
might be resident in multiple contexts simultaneously. What happens if
they are, and then the texture object is deleted?
The ARB_bindless_texture spec says:

(7) What happens if you try to delete a texture or sampler object with a
handle that is resident in another context?

RESOLVED: Deleting the texture will remove the texture from the name
space and make all handles using the texture non-resident in the current
context. However, texture or image handles for a deleted texture are
not deleted until the underlying texture or sampler object itself is
deleted. That deletion won't happen until the object is not bound
anywhere and there are no handles using the object that are resident in
any context.

Currently, my implementation does exactly this. I think the app should
handle this.
It seems to me that right now, you end up with dangling resident handles
in the "other" contexts. At the very least, this can cause incorrect
errors when the handle is re-used by the driver for another texture, so
*something* needs to loop over all contexts, it seems...
Cheers,
Nicolai
Samuel Pitoiset
2017-05-19 16:52:08 UTC
Permalink
This adds support in the VBO and array code to handle unsigned
64-bit vertex attributes as specified by ARB_bindless_texture.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mapi/glapi/gen/apiexec.py | 3 +++
src/mesa/main/api_loopback.c | 4 ++++
src/mesa/main/varray.c | 18 ++++++++++++++++++
src/mesa/vbo/vbo_attrib_tmp.h | 19 +++++++++++++++++++
src/mesa/vbo/vbo_context.h | 2 ++
src/mesa/vbo/vbo_exec_api.c | 12 +++++++++---
6 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/src/mapi/glapi/gen/apiexec.py b/src/mapi/glapi/gen/apiexec.py
index e5e1b7d78c..61eda4b0f9 100644
--- a/src/mapi/glapi/gen/apiexec.py
+++ b/src/mapi/glapi/gen/apiexec.py
@@ -291,4 +291,7 @@ functions = {
"ProgramUniform2ui64vARB": exec_info(core=31),
"ProgramUniform3ui64vARB": exec_info(core=31),
"ProgramUniform4ui64vARB": exec_info(core=31),
+
+ # GL_ARB_bindless_texture
+ "GetVertexAttribLui64vARB": exec_info(core=31),
}
diff --git a/src/mesa/main/api_loopback.c b/src/mesa/main/api_loopback.c
index 36e5194b93..b552d17d6a 100644
--- a/src/mesa/main/api_loopback.c
+++ b/src/mesa/main/api_loopback.c
@@ -89,6 +89,8 @@
#define ATTRIB3_D(index,x,y,z) CALL_VertexAttribL3d(GET_DISPATCH(), (index,x,y,z))
#define ATTRIB4_D(index,x,y,z,w) CALL_VertexAttribL4d(GET_DISPATCH(), (index,x,y,z,w))

+#define ATTRIB1_UI64(index, x) CALL_VertexAttribL1ui64ARB(GET_DISPATCH(), (index, x))
+
void GLAPIENTRY
_mesa_Color3b( GLbyte red, GLbyte green, GLbyte blue )
{
@@ -1531,11 +1533,13 @@ _mesa_VertexAttribL1dv(GLuint index, const GLdouble *v)
void GLAPIENTRY
_mesa_VertexAttribL1ui64ARB(GLuint index, GLuint64EXT x)
{
+ ATTRIB1_UI64(index, x);
}

void GLAPIENTRY
_mesa_VertexAttribL1ui64vARB(GLuint index, const GLuint64EXT *v)
{
+ ATTRIB1_UI64(index, v[0]);
}

void GLAPIENTRY
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
index fcb53d3986..2100cd1b9e 100644
--- a/src/mesa/main/varray.c
+++ b/src/mesa/main/varray.c
@@ -1356,6 +1356,24 @@ _mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
void GLAPIENTRY
_mesa_GetVertexAttribLui64vARB(GLuint index, GLenum pname, GLuint64EXT *params)
{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
+ const GLuint64 *v =
+ (const GLuint64 *)get_current_attrib(ctx, index,
+ "glGetVertexAttribLui64vARB");
+ if (v != NULL) {
+ params[0] = v[0];
+ params[1] = v[1];
+ params[2] = v[2];
+ params[3] = v[3];
+ }
+ }
+ else {
+ params[0] = (GLuint64) get_vertex_array_attrib(ctx, ctx->Array.VAO,
+ index, pname,
+ "glGetVertexAttribLui64vARB");
+ }
}


diff --git a/src/mesa/vbo/vbo_attrib_tmp.h b/src/mesa/vbo/vbo_attrib_tmp.h
index 08b441aafb..8328445b2b 100644
--- a/src/mesa/vbo/vbo_attrib_tmp.h
+++ b/src/mesa/vbo/vbo_attrib_tmp.h
@@ -41,6 +41,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
FLOAT_AS_UNION(V2), FLOAT_AS_UNION(V3))
#define ATTRD( A, N, V0, V1, V2, V3 ) \
ATTR_UNION(A, N, GL_DOUBLE, double, V0, V1, V2, V3)
+#define ATTRUI64( A, N, V0, V1, V2, V3 ) \
+ ATTR_UNION(A, N, GL_UNSIGNED_INT64_ARB, uint64_t, V0, V1, V2, V3)


/* float */
@@ -246,6 +248,9 @@ static inline float conv_i2_to_norm_float(const struct gl_context *ctx, int i2)
#define ATTR3D( A, X, Y, Z ) ATTRD( A, 3, X, Y, Z, 1 )
#define ATTR4D( A, X, Y, Z, W ) ATTRD( A, 4, X, Y, Z, W )

+#define ATTR1UIV64( A, V ) ATTRUI64( A, 1, (V)[0], 0, 0, 0 )
+#define ATTR1UI64( A, X ) ATTRUI64( A, 1, X, 0, 0, 0 )
+

static void GLAPIENTRY
TAG(Vertex2f)(GLfloat x, GLfloat y)
@@ -1305,11 +1310,25 @@ TAG(VertexAttribL4dv)(GLuint index, const GLdouble * v)
static void GLAPIENTRY
TAG(VertexAttribL1ui64ARB)(GLuint index, GLuint64EXT x)
{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR1UI64(0, x);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR1UI64(VBO_ATTRIB_GENERIC0 + index, x);
+ else
+ ERROR(GL_INVALID_VALUE);
}

static void GLAPIENTRY
TAG(VertexAttribL1ui64vARB)(GLuint index, const GLuint64EXT *v)
{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index == 0 && _mesa_attr_zero_aliases_vertex(ctx))
+ ATTR1UIV64(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR1UIV64(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR(GL_INVALID_VALUE);
}

#undef ATTR1FV
diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h
index 5cf399ffcd..a54258455f 100644
--- a/src/mesa/vbo/vbo_context.h
+++ b/src/mesa/vbo/vbo_context.h
@@ -156,6 +156,7 @@ vbo_attrtype_to_integer_flag(GLenum format)
return GL_FALSE;
case GL_INT:
case GL_UNSIGNED_INT:
+ case GL_UNSIGNED_INT64_ARB:
return GL_TRUE;
default:
assert(0);
@@ -170,6 +171,7 @@ vbo_attrtype_to_double_flag(GLenum format)
case GL_FLOAT:
case GL_INT:
case GL_UNSIGNED_INT:
+ case GL_UNSIGNED_INT64_ARB:
return GL_FALSE;
case GL_DOUBLE:
return GL_TRUE;
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index 4db4eef3b6..019f986f0b 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -176,11 +176,16 @@ vbo_exec_copy_to_current(struct vbo_exec_context *exec)
*/
GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
fi_type tmp[8]; /* space for doubles */
- int dmul = exec->vtx.attrtype[i] == GL_DOUBLE ? 2 : 1;
+ int dmul = 1;
+
+ if (exec->vtx.attrtype[i] == GL_DOUBLE ||
+ exec->vtx.attrtype[i] == GL_UNSIGNED_INT64_ARB)
+ dmul = 2;

assert(exec->vtx.attrsz[i]);

- if (exec->vtx.attrtype[i] == GL_DOUBLE) {
+ if (exec->vtx.attrtype[i] == GL_DOUBLE ||
+ exec->vtx.attrtype[i] == GL_UNSIGNED_INT64_ARB) {
memset(tmp, 0, sizeof(tmp));
memcpy(tmp, exec->vtx.attrptr[i], exec->vtx.attrsz[i] * sizeof(GLfloat));
} else {
@@ -241,7 +246,8 @@ vbo_exec_copy_from_current(struct vbo_exec_context *exec)
GLint i;

for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) {
- if (exec->vtx.attrtype[i] == GL_DOUBLE) {
+ if (exec->vtx.attrtype[i] == GL_DOUBLE ||
+ exec->vtx.attrtype[i] == GL_UNSIGNED_INT64_ARB) {
memcpy(exec->vtx.attrptr[i], vbo->currval[i].Ptr,
exec->vtx.attrsz[i] * sizeof(GLfloat));
} else {
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:10 UTC
Permalink
The ARB_bindless_texture spec says:

"The error INVALID_OPERATION is generated by SamplerParameter* if
<sampler> identifies a sampler object referenced by one or more
texture handles."

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/main/samplerobj.c | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)

diff --git a/src/mesa/main/samplerobj.c b/src/mesa/main/samplerobj.c
index ee15c68b4f..cf4bcfce7c 100644
--- a/src/mesa/main/samplerobj.c
+++ b/src/mesa/main/samplerobj.c
@@ -801,6 +801,18 @@ _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
if (!sampObj)
return;

+ if (sampObj->HandleAllocated) {
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by SamplerParameter* if
+ * <sampler> identifies a sampler object referenced by one or more
+ * texture handles."
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glSamplerParameteri(immutable sampler)");
+ return;
+ }
+
switch (pname) {
case GL_TEXTURE_WRAP_S:
res = set_sampler_wrap_s(ctx, sampObj, param);
@@ -884,6 +896,12 @@ _mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
if (!sampObj)
return;

+ if (sampObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glSamplerParameterf(immutable sampler)");
+ return;
+ }
+
switch (pname) {
case GL_TEXTURE_WRAP_S:
res = set_sampler_wrap_s(ctx, sampObj, (GLint) param);
@@ -966,6 +984,12 @@ _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params)
if (!sampObj)
return;

+ if (sampObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glSamplerParameteriv(immutable sampler)");
+ return;
+ }
+
switch (pname) {
case GL_TEXTURE_WRAP_S:
res = set_sampler_wrap_s(ctx, sampObj, params[0]);
@@ -1056,6 +1080,12 @@ _mesa_SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *params)
if (!sampObj)
return;

+ if (sampObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glSamplerParameterfv(immutable sampler)");
+ return;
+ }
+
switch (pname) {
case GL_TEXTURE_WRAP_S:
res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]);
@@ -1139,6 +1169,12 @@ _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params)
if (!sampObj)
return;

+ if (sampObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glSamplerParameterIiv(immutable sampler)");
+ return;
+ }
+
switch (pname) {
case GL_TEXTURE_WRAP_S:
res = set_sampler_wrap_s(ctx, sampObj, params[0]);
@@ -1223,6 +1259,12 @@ _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params)
if (!sampObj)
return;

+ if (sampObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glSamplerParameterIuiv(immutable sampler)");
+ return;
+ }
+
switch (pname) {
case GL_TEXTURE_WRAP_S:
res = set_sampler_wrap_s(ctx, sampObj, params[0]);
--
2.13.0
Samuel Pitoiset
2017-05-24 14:20:00 UTC
Permalink
Post by Samuel Pitoiset
"The error INVALID_OPERATION is generated by SamplerParameter* if
<sampler> identifies a sampler object referenced by one or more
texture handles."
---
src/mesa/main/samplerobj.c | 42
++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/src/mesa/main/samplerobj.c b/src/mesa/main/samplerobj.c
index ee15c68b4f..cf4bcfce7c 100644
--- a/src/mesa/main/samplerobj.c
+++ b/src/mesa/main/samplerobj.c
@@ -801,6 +801,18 @@ _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
if (!sampObj)
return;
+ if (sampObj->HandleAllocated) {
+ *
+ * "The error INVALID_OPERATION is generated by
SamplerParameter* if
+ * <sampler> identifies a sampler object referenced by one or more
+ * texture handles."
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glSamplerParameteri(immutable sampler)");
+ return;
+ }
Maybe these could go into sampler_parameter_error_check?
Yes, I added a new boolean parameter to sampler_parameter_error_check()
to differentiate set/get functions and moved the HandleAllocated check
there.
Cheers,
Nicolai
Post by Samuel Pitoiset
+
switch (pname) {
res = set_sampler_wrap_s(ctx, sampObj, param);
@@ -884,6 +896,12 @@ _mesa_SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
if (!sampObj)
return;
+ if (sampObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glSamplerParameterf(immutable sampler)");
+ return;
+ }
+
switch (pname) {
res = set_sampler_wrap_s(ctx, sampObj, (GLint) param);
@@ -966,6 +984,12 @@ _mesa_SamplerParameteriv(GLuint sampler, GLenum
pname, const GLint *params)
if (!sampObj)
return;
+ if (sampObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glSamplerParameteriv(immutable sampler)");
+ return;
+ }
+
switch (pname) {
res = set_sampler_wrap_s(ctx, sampObj, params[0]);
@@ -1056,6 +1080,12 @@ _mesa_SamplerParameterfv(GLuint sampler, GLenum
pname, const GLfloat *params)
if (!sampObj)
return;
+ if (sampObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glSamplerParameterfv(immutable sampler)");
+ return;
+ }
+
switch (pname) {
res = set_sampler_wrap_s(ctx, sampObj, (GLint) params[0]);
@@ -1139,6 +1169,12 @@ _mesa_SamplerParameterIiv(GLuint sampler,
GLenum pname, const GLint *params)
if (!sampObj)
return;
+ if (sampObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glSamplerParameterIiv(immutable sampler)");
+ return;
+ }
+
switch (pname) {
res = set_sampler_wrap_s(ctx, sampObj, params[0]);
@@ -1223,6 +1259,12 @@ _mesa_SamplerParameterIuiv(GLuint sampler,
GLenum pname, const GLuint *params)
if (!sampObj)
return;
+ if (sampObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glSamplerParameterIuiv(immutable sampler)");
+ return;
+ }
+
switch (pname) {
res = set_sampler_wrap_s(ctx, sampObj, params[0]);
Samuel Pitoiset
2017-05-19 16:52:11 UTC
Permalink
The ARB_bindless_texture spec says:

"The ARB_bindless_texture spec says: "The error INVALID_OPERATION
is generated by TexImage*, CopyTexImage*, CompressedTexImage*,
TexBuffer*, TexParameter*, as well as other functions defined in
terms of these, if the texture object to be modified is referenced
by one or more texture or image handles."

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/main/texparam.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)

diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c
index 0156bbd275..c73cf8bf83 100644
--- a/src/mesa/main/texparam.c
+++ b/src/mesa/main/texparam.c
@@ -1026,6 +1026,9 @@ _mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param)
if (!texObj)
return;

+ if (texObj->HandleAllocated)
+ return;
+
_mesa_texture_parameterf(ctx, texObj, pname, param, false);
}

@@ -1039,6 +1042,9 @@ _mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
if (!texObj)
return;

+ if (texObj->HandleAllocated)
+ return;
+
_mesa_texture_parameterfv(ctx, texObj, pname, params, false);
}

@@ -1052,6 +1058,9 @@ _mesa_TexParameteri(GLenum target, GLenum pname, GLint param)
if (!texObj)
return;

+ if (texObj->HandleAllocated)
+ return;
+
_mesa_texture_parameteri(ctx, texObj, pname, param, false);
}

@@ -1065,6 +1074,9 @@ _mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
if (!texObj)
return;

+ if (texObj->HandleAllocated)
+ return;
+
_mesa_texture_parameteriv(ctx, texObj, pname, params, false);
}

@@ -1083,6 +1095,9 @@ _mesa_TexParameterIiv(GLenum target, GLenum pname, const GLint *params)
if (!texObj)
return;

+ if (texObj->HandleAllocated)
+ return;
+
_mesa_texture_parameterIiv(ctx, texObj, pname, params, false);
}

@@ -1101,6 +1116,9 @@ _mesa_TexParameterIuiv(GLenum target, GLenum pname, const GLuint *params)
if (!texObj)
return;

+ if (texObj->HandleAllocated)
+ return;
+
_mesa_texture_parameterIuiv(ctx, texObj, pname, params, false);
}

@@ -1118,6 +1136,19 @@ _mesa_TextureParameterfv(GLuint texture, GLenum pname, const GLfloat *params)
return;
}

+ if (texObj->HandleAllocated) {
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by TexImage*, CopyTexImage*,
+ * CompressedTexImage*, TexBuffer*, TexParameter*, as well as other
+ * functions defined in terms of these, if the texture object to be
+ * modified is referenced by one or more texture or image handles."
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameterfv(immutable texture)");
+ return;
+ }
+
_mesa_texture_parameterfv(ctx, texObj, pname, params, true);
}

@@ -1134,6 +1165,12 @@ _mesa_TextureParameterf(GLuint texture, GLenum pname, GLfloat param)
return;
}

+ if (texObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameterf(immutable texture)");
+ return;
+ }
+
_mesa_texture_parameterf(ctx, texObj, pname, param, true);
}

@@ -1150,6 +1187,12 @@ _mesa_TextureParameteri(GLuint texture, GLenum pname, GLint param)
return;
}

+ if (texObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameteri(immutable texture)");
+ return;
+ }
+
_mesa_texture_parameteri(ctx, texObj, pname, param, true);
}

@@ -1167,6 +1210,12 @@ _mesa_TextureParameteriv(GLuint texture, GLenum pname,
return;
}

+ if (texObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameteriv(immutable texture)");
+ return;
+ }
+
_mesa_texture_parameteriv(ctx, texObj, pname, params, true);
}

@@ -1185,6 +1234,12 @@ _mesa_TextureParameterIiv(GLuint texture, GLenum pname, const GLint *params)
return;
}

+ if (texObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameterIiv(immutable texture)");
+ return;
+ }
+
_mesa_texture_parameterIiv(ctx, texObj, pname, params, true);
}

@@ -1202,6 +1257,12 @@ _mesa_TextureParameterIuiv(GLuint texture, GLenum pname, const GLuint *params)
return;
}

+ if (texObj->HandleAllocated) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTextureParameterIuv(immutable texture)");
+ return;
+ }
+
_mesa_texture_parameterIuiv(ctx, texObj, pname, params, true);
}
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:12 UTC
Permalink
The ARB_bindless_texture spec says:

"The error INVALID_OPERATION is generated by TexImage*, CopyTexImage*,
CompressedTexImage*, TexBuffer*, TexParameter*, as well as other
functions defined in terms of these, if the texture object to be
modified is referenced by one or more texture or image handles."

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/main/teximage.c | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index fed1dad262..ac06b66985 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -1578,7 +1578,7 @@ legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target,

/**
* Helper function to determine if a texture object is mutable (in terms
- * of GL_ARB_texture_storage).
+ * of GL_ARB_texture_storage/GL_ARB_bindless_texture).
*/
static GLboolean
mutable_tex_object(struct gl_context *ctx, GLenum target)
@@ -1587,6 +1587,17 @@ mutable_tex_object(struct gl_context *ctx, GLenum target)
if (!texObj)
return GL_FALSE;

+ if (texObj->HandleAllocated) {
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by TexImage*, CopyTexImage*,
+ * CompressedTexImage*, TexBuffer*, TexParameter*, as well as other
+ * functions defined in terms of these, if the texture object to be
+ * modified is referenced by one or more texture or image handles."
+ */
+ return GL_FALSE;
+ }
+
return !texObj->Immutable;
}

@@ -5009,6 +5020,18 @@ texture_buffer_range(struct gl_context *ctx,
return;
}

+ if (texObj->HandleAllocated) {
+ /* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated by TexImage*, CopyTexImage*,
+ * CompressedTexImage*, TexBuffer*, TexParameter*, as well as other
+ * functions defined in terms of these, if the texture object to be
+ * modified is referenced by one or more texture or image handles."
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable texture)", caller);
+ return;
+ }
+
format = _mesa_validate_texbuffer_format(ctx, internalFormat);
if (format == MESA_FORMAT_NONE) {
_mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat %s)",
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:14 UTC
Permalink
Bindless samplers are considered PROGRAM_UNIFORM but
add_uniform_to_shader::visit_field() is based on glsl_type.

Because only ir_variable knows if the uniform variable is
bindless via ir_variable::bindless, store it instead of
adding a new parameter to visit_field().

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/program/ir_to_mesa.cpp | 2 ++
1 file changed, 2 insertions(+)

diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 3299ab722a..a1a788e9e8 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -2420,6 +2420,7 @@ public:
void process(ir_variable *var)
{
this->idx = -1;
+ this->var = var;
this->program_resource_visitor::process(var);
var->data.param_index = this->idx;
}
@@ -2433,6 +2434,7 @@ private:
struct gl_shader_program *shader_program;
struct gl_program_parameter_list *params;
int idx;
+ ir_variable *var;
gl_shader_stage shader_type;
};
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:13 UTC
Permalink
The ARB_bindless_texture spec says:

"The error INVALID_OPERATION is generated by BufferData if it is
called to modify a buffer object bound to a buffer texture while
that texture object is referenced by one or more texture handles."

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/main/bufferobj.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
index 461d69779a..db95a2b511 100644
--- a/src/mesa/main/bufferobj.c
+++ b/src/mesa/main/bufferobj.c
@@ -1552,7 +1552,7 @@ validate_buffer_storage(struct gl_context *ctx,
return false;
}

- if (bufObj->Immutable) {
+ if (bufObj->Immutable || bufObj->HandleAllocated) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
return false;
}
@@ -1716,7 +1716,7 @@ _mesa_buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
return;
}

- if (bufObj->Immutable) {
+ if (bufObj->Immutable || bufObj->HandleAllocated) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
return;
}
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:18 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/compiler/glsl/link_uniforms.cpp | 74 ++++++++++++++++++++++++++++++++-----
src/compiler/glsl/shader_cache.cpp | 20 ++++++++++
src/mesa/program/program.c | 4 ++
3 files changed, 89 insertions(+), 9 deletions(-)

diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp
index c962f98d59..d2cb22c206 100644
--- a/src/compiler/glsl/link_uniforms.cpp
+++ b/src/compiler/glsl/link_uniforms.cpp
@@ -419,13 +419,14 @@ public:
struct gl_uniform_storage *uniforms,
union gl_constant_value *values)
: prog(prog), map(map), uniforms(uniforms), values(values),
- bindless_targets(NULL)
+ bindless_targets(NULL), bindless_access(NULL)
{
}

virtual ~parcel_out_uniform_storage()
{
free(this->bindless_targets);
+ free(this->bindless_access);
}

void start_shader(gl_shader_stage shader_type)
@@ -445,6 +446,11 @@ public:
this->next_bindless_sampler = 0;
free(this->bindless_targets);
this->bindless_targets = NULL;
+
+ this->num_bindless_images = 0;
+ this->next_bindless_image = 0;
+ free(this->bindless_access);
+ this->bindless_access = NULL;
}

void set_and_process(ir_variable *var)
@@ -454,6 +460,7 @@ public:
this->record_next_sampler = new string_to_uint_map;
this->record_next_bindless_sampler = new string_to_uint_map;
this->record_next_image = new string_to_uint_map;
+ this->record_next_bindless_image = new string_to_uint_map;

buffer_block_index = -1;
if (var->is_in_buffer_block()) {
@@ -516,6 +523,7 @@ public:
delete this->record_next_sampler;
delete this->record_next_bindless_sampler;
delete this->record_next_image;
+ delete this->record_next_bindless_image;
}

int buffer_block_index;
@@ -634,20 +642,40 @@ private:
if (base_type->is_image()) {
uniform->opaque[shader_type].active = true;

- if (!set_opaque_indices(base_type, uniform, name, this->next_image,
- this->record_next_image))
- return;
-
/* Set image access qualifiers */
const GLenum access =
(current_var->data.memory_read_only ? GL_READ_ONLY :
current_var->data.memory_write_only ? GL_WRITE_ONLY :
GL_READ_WRITE);

- for (unsigned i = uniform->opaque[shader_type].index;
- i < MIN2(this->next_image, MAX_IMAGE_UNIFORMS);
- i++) {
- prog->_LinkedShaders[shader_type]->Program->sh.ImageAccess[i] = access;
+ if (current_var->data.bindless) {
+ if (!set_opaque_indices(base_type, uniform, name,
+ this->next_bindless_image,
+ this->record_next_bindless_image))
+ return;
+
+ this->num_bindless_images = this->next_bindless_image;
+
+ this->bindless_access = (GLenum *)
+ realloc(this->bindless_access,
+ this->num_bindless_images * sizeof(GLenum));
+
+ for (unsigned i = uniform->opaque[shader_type].index;
+ i < this->num_bindless_images;
+ i++) {
+ this->bindless_access[i] = access;
+ }
+ } else {
+ if (!set_opaque_indices(base_type, uniform, name,
+ this->next_image,
+ this->record_next_image))
+ return;
+
+ for (unsigned i = uniform->opaque[shader_type].index;
+ i < MIN2(this->next_image, MAX_IMAGE_UNIFORMS);
+ i++) {
+ prog->_LinkedShaders[shader_type]->Program->sh.ImageAccess[i] = access;
+ }
}
}
}
@@ -863,6 +891,7 @@ private:
unsigned next_sampler;
unsigned next_bindless_sampler;
unsigned next_image;
+ unsigned next_bindless_image;
unsigned next_subroutine;

/**
@@ -899,6 +928,11 @@ private:
*/
struct string_to_uint_map *record_next_bindless_sampler;

+ /* Map for temporarily storing next bindless image index when handling
+ * bindless images in struct arrays.
+ */
+ struct string_to_uint_map *record_next_bindless_image;
+
public:
union gl_constant_value *values;

@@ -923,6 +957,17 @@ public:
* Texture targets for bindless samplers used by the current stage.
*/
gl_texture_index *bindless_targets;
+
+ /**
+ * Number of bindless images used by the current shader stage.
+ */
+ unsigned num_bindless_images;
+
+ /**
+ * Access types for bindless images used by the current stage.
+ */
+ GLenum *bindless_access;
+
};

static bool
@@ -1320,6 +1365,17 @@ link_assign_uniform_storage(struct gl_context *ctx,
}
}

+ if (parcel.num_bindless_images > 0) {
+ shader->Program->sh.NumBindlessImages = parcel.num_bindless_images;
+ shader->Program->sh.BindlessImages =
+ rzalloc_array(shader->Program, gl_bindless_image,
+ parcel.num_bindless_images);
+ for (unsigned j = 0; j < parcel.num_bindless_images; j++) {
+ shader->Program->sh.BindlessImages[j].access =
+ parcel.bindless_access[j];
+ }
+ }
+
STATIC_ASSERT(sizeof(shader->Program->sh.SamplerTargets) ==
sizeof(parcel.targets));
memcpy(shader->Program->sh.SamplerTargets,
diff --git a/src/compiler/glsl/shader_cache.cpp b/src/compiler/glsl/shader_cache.cpp
index 35f30e1289..6811cb2f50 100644
--- a/src/compiler/glsl/shader_cache.cpp
+++ b/src/compiler/glsl/shader_cache.cpp
@@ -1153,6 +1153,13 @@ write_shader_metadata(struct blob *metadata, gl_linked_shader *shader)
sizeof(struct gl_bindless_sampler));
}

+ blob_write_uint32(metadata, glprog->sh.NumBindlessImages);
+ blob_write_uint32(metadata, glprog->sh.HasBoundBindlessImage);
+ for (i = 0; i < glprog->sh.NumBindlessImages; i++) {
+ blob_write_bytes(metadata, &glprog->sh.BindlessImages[i],
+ sizeof(struct gl_bindless_image));
+ }
+
write_shader_parameters(metadata, glprog->Parameters);
}

@@ -1191,6 +1198,19 @@ read_shader_metadata(struct blob_reader *metadata,
}
}

+ glprog->sh.NumBindlessImages = blob_read_uint32(metadata);
+ glprog->sh.HasBoundBindlessImage = blob_read_uint32(metadata);
+ if (glprog->sh.NumBindlessImages > 0) {
+ glprog->sh.BindlessImages =
+ rzalloc_array(glprog, gl_bindless_image,
+ glprog->sh.NumBindlessImages);
+
+ for (i = 0; i < glprog->sh.NumBindlessImages; i++) {
+ blob_copy_bytes(metadata, (uint8_t *) &glprog->sh.BindlessImages[i],
+ sizeof(struct gl_bindless_image));
+ }
+ }
+
glprog->Parameters = _mesa_new_parameter_list();
read_shader_parameters(metadata, glprog->Parameters);
}
diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c
index b5533c7257..0defa012ae 100644
--- a/src/mesa/program/program.c
+++ b/src/mesa/program/program.c
@@ -275,6 +275,10 @@ _mesa_delete_program(struct gl_context *ctx, struct gl_program *prog)
ralloc_free(prog->sh.BindlessSamplers);
}

+ if (prog->sh.BindlessImages) {
+ ralloc_free(prog->sh.BindlessImages);
+ }
+
ralloc_free(prog);
}
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:20 UTC
Permalink
This handles a situation like:

layout (bindless_sampler, binding = 7) uniform sampler2D;

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/compiler/glsl/link_uniform_initializers.cpp | 35 ++++++++++++++++++++-----
1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/src/compiler/glsl/link_uniform_initializers.cpp b/src/compiler/glsl/link_uniform_initializers.cpp
index bc3dcab7c3..e7f9c9d8ac 100644
--- a/src/compiler/glsl/link_uniform_initializers.cpp
+++ b/src/compiler/glsl/link_uniform_initializers.cpp
@@ -140,16 +140,39 @@ set_opaque_binding(void *mem_ctx, gl_shader_program *prog,
if (storage->type->is_sampler()) {
for (unsigned i = 0; i < elements; i++) {
const unsigned index = storage->opaque[sh].index + i;
- if (index >= ARRAY_SIZE(shader->Program->SamplerUnits))
- break;
- shader->Program->SamplerUnits[index] = storage->storage[i].i;
+
+ if (var->data.bindless) {
+ if (index >= shader->Program->sh.NumBindlessSamplers)
+ break;
+ shader->Program->sh.BindlessSamplers[index].unit =
+ storage->storage[i].i;
+ shader->Program->sh.BindlessSamplers[index].bound = true;
+ shader->Program->sh.HasBoundBindlessSampler = true;
+ } else {
+ if (index >= ARRAY_SIZE(shader->Program->SamplerUnits))
+ break;
+ shader->Program->SamplerUnits[index] =
+ storage->storage[i].i;
+ }
}
} else if (storage->type->is_image()) {
for (unsigned i = 0; i < elements; i++) {
const unsigned index = storage->opaque[sh].index + i;
- if (index >= ARRAY_SIZE(shader->Program->sh.ImageUnits))
- break;
- shader->Program->sh.ImageUnits[index] = storage->storage[i].i;
+
+
+ if (var->data.bindless) {
+ if (index >= shader->Program->sh.NumBindlessImages)
+ break;
+ shader->Program->sh.BindlessImages[index].unit =
+ storage->storage[i].i;
+ shader->Program->sh.BindlessImages[index].bound = true;
+ shader->Program->sh.HasBoundBindlessImage = true;
+ } else {
+ if (index >= ARRAY_SIZE(shader->Program->sh.ImageUnits))
+ break;
+ shader->Program->sh.ImageUnits[index] =
+ storage->storage[i].i;
+ }
}
}
}
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:17 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/compiler/glsl/link_uniforms.cpp | 83 ++++++++++++++++++++++++++++++++-----
src/compiler/glsl/shader_cache.cpp | 23 ++++++++++
src/mesa/program/program.c | 4 ++
3 files changed, 99 insertions(+), 11 deletions(-)

diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp
index 7c3ca75416..c962f98d59 100644
--- a/src/compiler/glsl/link_uniforms.cpp
+++ b/src/compiler/glsl/link_uniforms.cpp
@@ -418,10 +418,16 @@ public:
struct string_to_uint_map *map,
struct gl_uniform_storage *uniforms,
union gl_constant_value *values)
- : prog(prog), map(map), uniforms(uniforms), values(values)
+ : prog(prog), map(map), uniforms(uniforms), values(values),
+ bindless_targets(NULL)
{
}

+ virtual ~parcel_out_uniform_storage()
+ {
+ free(this->bindless_targets);
+ }
+
void start_shader(gl_shader_stage shader_type)
{
assert(shader_type < MESA_SHADER_STAGES);
@@ -434,6 +440,11 @@ public:
this->next_subroutine = 0;
this->record_array_count = 1;
memset(this->targets, 0, sizeof(this->targets));
+
+ this->num_bindless_samplers = 0;
+ this->next_bindless_sampler = 0;
+ free(this->bindless_targets);
+ this->bindless_targets = NULL;
}

void set_and_process(ir_variable *var)
@@ -441,6 +452,7 @@ public:
current_var = var;
field_counter = 0;
this->record_next_sampler = new string_to_uint_map;
+ this->record_next_bindless_sampler = new string_to_uint_map;
this->record_next_image = new string_to_uint_map;

buffer_block_index = -1;
@@ -502,6 +514,7 @@ public:
process(var);
}
delete this->record_next_sampler;
+ delete this->record_next_bindless_sampler;
delete this->record_next_image;
}

@@ -578,18 +591,39 @@ private:
if (base_type->is_sampler()) {
uniform->opaque[shader_type].active = true;

- if (!set_opaque_indices(base_type, uniform, name, this->next_sampler,
- this->record_next_sampler))
- return;
-
const gl_texture_index target = base_type->sampler_index();
const unsigned shadow = base_type->sampler_shadow;
- for (unsigned i = uniform->opaque[shader_type].index;
- i < MIN2(this->next_sampler, MAX_SAMPLERS);
- i++) {
- this->targets[i] = target;
- this->shader_samplers_used |= 1U << i;
- this->shader_shadow_samplers |= shadow << i;
+
+ if (current_var->data.bindless) {
+ if (!set_opaque_indices(base_type, uniform, name,
+ this->next_bindless_sampler,
+ this->record_next_bindless_sampler))
+ return;
+
+ this->num_bindless_samplers = this->next_bindless_sampler;
+
+ this->bindless_targets = (gl_texture_index *)
+ realloc(this->bindless_targets,
+ this->num_bindless_samplers * sizeof(gl_texture_index));
+
+ for (unsigned i = uniform->opaque[shader_type].index;
+ i < this->num_bindless_samplers;
+ i++) {
+ this->bindless_targets[i] = target;
+ }
+ } else {
+ if (!set_opaque_indices(base_type, uniform, name,
+ this->next_sampler,
+ this->record_next_sampler))
+ return;
+
+ for (unsigned i = uniform->opaque[shader_type].index;
+ i < MIN2(this->next_sampler, MAX_SAMPLERS);
+ i++) {
+ this->targets[i] = target;
+ this->shader_samplers_used |= 1U << i;
+ this->shader_shadow_samplers |= shadow << i;
+ }
}
}
}
@@ -827,6 +861,7 @@ private:

struct gl_uniform_storage *uniforms;
unsigned next_sampler;
+ unsigned next_bindless_sampler;
unsigned next_image;
unsigned next_subroutine;

@@ -859,6 +894,11 @@ private:
*/
struct string_to_uint_map *record_next_image;

+ /* Map for temporarily storing next bindless sampler index when handling
+ * bindless samplers in struct arrays.
+ */
+ struct string_to_uint_map *record_next_bindless_sampler;
+
public:
union gl_constant_value *values;

@@ -873,6 +913,16 @@ public:
* Mask of samplers used by the current shader stage for shadows.
*/
unsigned shader_shadow_samplers;
+
+ /**
+ * Number of bindless samplers used by the current shader stage.
+ */
+ unsigned num_bindless_samplers;
+
+ /**
+ * Texture targets for bindless samplers used by the current stage.
+ */
+ gl_texture_index *bindless_targets;
};

static bool
@@ -1259,6 +1309,17 @@ link_assign_uniform_storage(struct gl_context *ctx,
shader->Program->SamplersUsed = parcel.shader_samplers_used;
shader->shadow_samplers = parcel.shader_shadow_samplers;

+ if (parcel.num_bindless_samplers > 0) {
+ shader->Program->sh.NumBindlessSamplers = parcel.num_bindless_samplers;
+ shader->Program->sh.BindlessSamplers =
+ rzalloc_array(shader->Program, gl_bindless_sampler,
+ parcel.num_bindless_samplers);
+ for (unsigned j = 0; j < parcel.num_bindless_samplers; j++) {
+ shader->Program->sh.BindlessSamplers[j].target =
+ parcel.bindless_targets[j];
+ }
+ }
+
STATIC_ASSERT(sizeof(shader->Program->sh.SamplerTargets) ==
sizeof(parcel.targets));
memcpy(shader->Program->sh.SamplerTargets,
diff --git a/src/compiler/glsl/shader_cache.cpp b/src/compiler/glsl/shader_cache.cpp
index 2bfddebcd7..35f30e1289 100644
--- a/src/compiler/glsl/shader_cache.cpp
+++ b/src/compiler/glsl/shader_cache.cpp
@@ -1129,6 +1129,7 @@ write_shader_metadata(struct blob *metadata, gl_linked_shader *shader)
{
assert(shader->Program);
struct gl_program *glprog = shader->Program;
+ unsigned i;

blob_write_bytes(metadata, glprog->TexturesUsed,
sizeof(glprog->TexturesUsed));
@@ -1145,6 +1146,13 @@ write_shader_metadata(struct blob *metadata, gl_linked_shader *shader)
blob_write_bytes(metadata, glprog->sh.ImageUnits,
sizeof(glprog->sh.ImageUnits));

+ blob_write_uint32(metadata, glprog->sh.NumBindlessSamplers);
+ blob_write_uint32(metadata, glprog->sh.HasBoundBindlessSampler);
+ for (i = 0; i < glprog->sh.NumBindlessSamplers; i++) {
+ blob_write_bytes(metadata, &glprog->sh.BindlessSamplers[i],
+ sizeof(struct gl_bindless_sampler));
+ }
+
write_shader_parameters(metadata, glprog->Parameters);
}

@@ -1153,6 +1161,8 @@ read_shader_metadata(struct blob_reader *metadata,
struct gl_program *glprog,
gl_linked_shader *linked)
{
+ unsigned i;
+
blob_copy_bytes(metadata, (uint8_t *) glprog->TexturesUsed,
sizeof(glprog->TexturesUsed));
glprog->SamplersUsed = blob_read_uint64(metadata);
@@ -1168,6 +1178,19 @@ read_shader_metadata(struct blob_reader *metadata,
blob_copy_bytes(metadata, (uint8_t *) glprog->sh.ImageUnits,
sizeof(glprog->sh.ImageUnits));

+ glprog->sh.NumBindlessSamplers = blob_read_uint32(metadata);
+ glprog->sh.HasBoundBindlessSampler = blob_read_uint32(metadata);
+ if (glprog->sh.NumBindlessSamplers > 0) {
+ glprog->sh.BindlessSamplers =
+ rzalloc_array(glprog, gl_bindless_sampler,
+ glprog->sh.NumBindlessSamplers);
+
+ for (i = 0; i < glprog->sh.NumBindlessSamplers; i++) {
+ blob_copy_bytes(metadata, (uint8_t *) &glprog->sh.BindlessSamplers[i],
+ sizeof(struct gl_bindless_sampler));
+ }
+ }
+
glprog->Parameters = _mesa_new_parameter_list();
read_shader_parameters(metadata, glprog->Parameters);
}
diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c
index 277e6ce2d8..b5533c7257 100644
--- a/src/mesa/program/program.c
+++ b/src/mesa/program/program.c
@@ -271,6 +271,10 @@ _mesa_delete_program(struct gl_context *ctx, struct gl_program *prog)
ralloc_free(prog->nir);
}

+ if (prog->sh.BindlessSamplers) {
+ ralloc_free(prog->sh.BindlessSamplers);
+ }
+
ralloc_free(prog);
}
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:21 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/compiler/glsl/ir.h | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h
index 91e665cc1b..c816a327c1 100644
--- a/src/compiler/glsl/ir.h
+++ b/src/compiler/glsl/ir.h
@@ -475,6 +475,17 @@ public:
}

/**
+ * Return whether this variable is a bindless sampler/image.
+ */
+ inline bool is_bindless() const
+ {
+ if (!this->type->contains_sampler() && !this->type->contains_image())
+ return false;
+
+ return this->data.bindless || this->data.mode != ir_var_uniform;
+ }
+
+ /**
* Set this->interface_type on a newly created variable.
*/
void init_interface_type(const struct glsl_type *type)
--
2.13.0
Nicolai Hähnle
2017-05-24 11:32:49 UTC
Permalink
Post by Samuel Pitoiset
---
src/compiler/glsl/ir.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h
index 91e665cc1b..c816a327c1 100644
--- a/src/compiler/glsl/ir.h
+++ b/src/compiler/glsl/ir.h
}
/**
+ * Return whether this variable is a bindless sampler/image.
+ */
+ inline bool is_bindless() const
+ {
+ if (!this->type->contains_sampler() && !this->type->contains_image())
+ return false;
+
+ return this->data.bindless || this->data.mode != ir_var_uniform;
+ }
This should really be called contains_bindless(), and the comment be
adjusted accordingly.

Cheers,
Nicolai
Post by Samuel Pitoiset
+
+ /**
* Set this->interface_type on a newly created variable.
*/
void init_interface_type(const struct glsl_type *type)
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
Samuel Pitoiset
2017-05-19 16:52:16 UTC
Permalink
Yes, ARB_bindless_texture allows to do this. In other words, in
a situation like:

layout (bindless_sampler) uniform sampler2D tex;

The 'tex' sampler uniform can be either set with glUniform1()
(old-style bound samplers) or with glUniformHandleui() (resident
handles).

When glUniform1() is used, we have to somehow make the texture
resident "under the hood". This is done by requesting a texture
handle to the driver, making the handle resident in the current
context and overwriting the value directly in the constant buffer.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/main/mtypes.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)

diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 70865b373d..1d168e8c68 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1988,6 +1988,42 @@ struct gl_perf_query_state


/**
+ * A bindless sampler object.
+ */
+struct gl_bindless_sampler
+{
+ /** Texture unit (set by glUniform1()). */
+ GLubyte unit;
+
+ /** Texture Target (TEXTURE_1D/2D/3D/etc_INDEX). */
+ gl_texture_index target;
+
+ /** Whether this bindless sampler is bound to a unit. */
+ GLboolean bound;
+
+ /** Pointer to the base of the data. */
+ GLvoid *data;
+};
+
+/**
+ * A bindless image object.
+ */
+struct gl_bindless_image
+{
+ /** Image unit (set by glUniform1()). */
+ GLubyte unit;
+
+ /** Access qualifier (GL_READ_WRITE, GL_READ_ONLY, GL_WRITE_ONLY) */
+ GLenum access;
+
+ /** Whether this bindless image is bound to a unit. */
+ GLboolean bound;
+
+ /** Pointer to the base of the data. */
+ GLvoid *data;
+};
+
+/**
* Names of the various vertex/fragment program register files, etc.
*
* NOTE: first four tokens must fit into 2 bits (see t_vb_arbprogram.c)
@@ -2121,6 +2157,22 @@ struct gl_program
*/
gl_texture_index SamplerTargets[MAX_SAMPLERS];

+ /**
+ * Number of samplers declared with the bindless_sampler layout
+ * qualifier as specified by ARB_bindless_texture.
+ */
+ GLuint NumBindlessSamplers;
+ GLboolean HasBoundBindlessSampler;
+ struct gl_bindless_sampler *BindlessSamplers;
+
+ /**
+ * Number of images declared with the bindless_image layout qualifier
+ * as specified by ARB_bindless_texture.
+ */
+ GLuint NumBindlessImages;
+ GLboolean HasBoundBindlessImage;
+ struct gl_bindless_image *BindlessImages;
+
union {
struct {
/**
--
2.13.0
Nicolai Hähnle
2017-05-24 10:28:08 UTC
Permalink
Post by Samuel Pitoiset
Yes, ARB_bindless_texture allows to do this. In other words, in
layout (bindless_sampler) uniform sampler2D tex;
The 'tex' sampler uniform can be either set with glUniform1()
(old-style bound samplers) or with glUniformHandleui() (resident
handles).
When glUniform1() is used, we have to somehow make the texture
resident "under the hood". This is done by requesting a texture
handle to the driver, making the handle resident in the current
context and overwriting the value directly in the constant buffer.
---
src/mesa/main/mtypes.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 70865b373d..1d168e8c68 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1988,6 +1988,42 @@ struct gl_perf_query_state
/**
+ * A bindless sampler object.
+ */
+struct gl_bindless_sampler
+{
+ /** Texture unit (set by glUniform1()). */
+ GLubyte unit;
+
+ /** Texture Target (TEXTURE_1D/2D/3D/etc_INDEX). */
+ gl_texture_index target;
+
+ /** Whether this bindless sampler is bound to a unit. */
+ GLboolean bound;
+
+ /** Pointer to the base of the data. */
+ GLvoid *data;
+};
+
+/**
+ * A bindless image object.
+ */
+struct gl_bindless_image
+{
+ /** Image unit (set by glUniform1()). */
+ GLubyte unit;
+
+ /** Access qualifier (GL_READ_WRITE, GL_READ_ONLY, GL_WRITE_ONLY) */
+ GLenum access;
+
+ /** Whether this bindless image is bound to a unit. */
+ GLboolean bound;
+
+ /** Pointer to the base of the data. */
+ GLvoid *data;
+};
+
+/**
* Names of the various vertex/fragment program register files, etc.
*
* NOTE: first four tokens must fit into 2 bits (see t_vb_arbprogram.c)
@@ -2121,6 +2157,22 @@ struct gl_program
*/
gl_texture_index SamplerTargets[MAX_SAMPLERS];
+ /**
+ * Number of samplers declared with the bindless_sampler layout
+ * qualifier as specified by ARB_bindless_texture.
+ */
+ GLuint NumBindlessSamplers;
+ GLboolean HasBoundBindlessSampler;
+ struct gl_bindless_sampler *BindlessSamplers;
+
+ /**
+ * Number of images declared with the bindless_image layout qualifier
+ * as specified by ARB_bindless_texture.
+ */
+ GLuint NumBindlessImages;
+ GLboolean HasBoundBindlessImage;
+ struct gl_bindless_image *BindlessImages;
+
This could go into the sh part of the union below, couldn't it?

Cheers,
Nicolai
Post by Samuel Pitoiset
union {
struct {
/**
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
Samuel Pitoiset
2017-05-19 16:52:24 UTC
Permalink
This is analogous to the existing SamplerUnits and SamplerTargets,
but it loops over bindless samplers bound to texture units.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/main/texstate.c | 18 +++++++++++++++++-
src/mesa/main/uniforms.c | 17 ++++++++++++++++-
2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index 4fd853f386..4bac9c040c 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -690,6 +690,7 @@ update_program_texture_state(struct gl_context *ctx, struct gl_program **prog,

for (i = 0; i < MESA_SHADER_STAGES; i++) {
GLbitfield mask;
+ GLuint s;

if (!prog[i])
continue;
@@ -697,12 +698,27 @@ update_program_texture_state(struct gl_context *ctx, struct gl_program **prog,
mask = prog[i]->SamplersUsed;

while (mask) {
- const int s = u_bit_scan(&mask);
+ s = u_bit_scan(&mask);

update_single_program_texture_state(ctx, prog[i],
prog[i]->SamplerUnits[s],
enabled_texture_units);
}
+
+ if (unlikely(prog[i]->sh.HasBoundBindlessSampler)) {
+ /* Loop over bindless samplers bound to texture units.
+ */
+ for (s = 0; s < prog[i]->sh.NumBindlessSamplers; s++) {
+ struct gl_bindless_sampler *sampler =
+ &prog[i]->sh.BindlessSamplers[s];
+
+ if (!sampler->bound)
+ continue;
+
+ update_single_program_texture_state(ctx, prog[i], sampler->unit,
+ enabled_texture_units);
+ }
+ }
}

if (prog[MESA_SHADER_FRAGMENT]) {
diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index 6706f794d7..91c3bf66f8 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c
@@ -105,18 +105,33 @@ _mesa_update_shader_textures_used(struct gl_shader_program *shProg,
gl_shader_stage prog_stage =
_mesa_program_enum_to_shader_stage(prog->Target);
struct gl_linked_shader *shader = shProg->_LinkedShaders[prog_stage];
+ GLuint s;

assert(shader);

memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));

while (mask) {
- const int s = u_bit_scan(&mask);
+ s = u_bit_scan(&mask);

update_single_shader_texture_used(shProg, prog,
prog->SamplerUnits[s],
prog->sh.SamplerTargets[s]);
}
+
+ if (unlikely(prog->sh.HasBoundBindlessSampler)) {
+ /* Loop over bindless samplers bound to texture units.
+ */
+ for (s = 0; s < prog->sh.NumBindlessSamplers; s++) {
+ struct gl_bindless_sampler *sampler = &prog->sh.BindlessSamplers[s];
+
+ if (!sampler->bound)
+ continue;
+
+ update_single_shader_texture_used(shProg, prog, sampler->unit,
+ sampler->target);
+ }
+ }
}

/**
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:28 UTC
Permalink
This post might be inappropriate. Click to display it.
Samuel Pitoiset
2017-05-19 16:52:19 UTC
Permalink
In order to set the explicit binding value for bindless
samplers/images.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/compiler/glsl/link_uniform_initializers.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/compiler/glsl/link_uniform_initializers.cpp b/src/compiler/glsl/link_uniform_initializers.cpp
index a7af75586e..bc3dcab7c3 100644
--- a/src/compiler/glsl/link_uniform_initializers.cpp
+++ b/src/compiler/glsl/link_uniform_initializers.cpp
@@ -97,7 +97,8 @@ copy_constant_to_storage(union gl_constant_value *storage,
*/
void
set_opaque_binding(void *mem_ctx, gl_shader_program *prog,
- const glsl_type *type, const char *name, int *binding)
+ const ir_variable *var, const glsl_type *type,
+ const char *name, int *binding)
{

if (type->is_array() && type->fields.array->is_array()) {
@@ -106,7 +107,7 @@ set_opaque_binding(void *mem_ctx, gl_shader_program *prog,
for (unsigned int i = 0; i < type->length; i++) {
const char *element_name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i);

- set_opaque_binding(mem_ctx, prog, element_type,
+ set_opaque_binding(mem_ctx, prog, var, element_type,
element_name, binding);
}
} else {
@@ -281,7 +282,7 @@ link_set_uniform_initializers(struct gl_shader_program *prog,
if (type->without_array()->is_sampler() ||
type->without_array()->is_image()) {
int binding = var->data.binding;
- linker::set_opaque_binding(mem_ctx, prog, var->type,
+ linker::set_opaque_binding(mem_ctx, prog, var, var->type,
var->name, &binding);
} else if (var->is_in_buffer_block()) {
const glsl_type *const iface_type = var->get_interface_type();
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:26 UTC
Permalink
When a bindless sampler/image is bound to a texture/image unit,
we have to overwrite the constant value by the resident handle
directly in the constant buffer before the next draw.

One solution is to keep track of a pointer to the data.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/program/ir_to_mesa.cpp | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 5e6304036d..0c3ffd2e22 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -2541,6 +2541,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx,
bool propagate_to_storage)
{
struct gl_program_parameter_list *params = prog->Parameters;
+ gl_shader_stage shader_type = prog->info.stage;

/* After adding each uniform to the parameter list, connect the storage for
* the parameter with the tracking structure used by the API for the
@@ -2623,6 +2624,30 @@ _mesa_associate_uniform_storage(struct gl_context *ctx,
format,
&params->ParameterValues[i]);

+ /* When a bindless sampler/image is bound to a texture/image unit, we
+ * have to overwrite the constant value by the resident handle
+ * directly in the constant buffer before the next draw. One solution
+ * is to keep track a pointer to the base of the data.
+ */
+ if (storage->is_bindless && (prog->sh.NumBindlessSamplers ||
+ prog->sh.NumBindlessImages)) {
+ unsigned array_elements = MAX2(1, storage->array_elements);
+
+ for (unsigned j = 0; j < array_elements; ++j) {
+ unsigned unit = storage->opaque[shader_type].index + j;
+
+ if (storage->type->without_array()->is_sampler()) {
+ assert(unit >= 0 && unit < prog->sh.NumBindlessSamplers);
+ prog->sh.BindlessSamplers[unit].data =
+ &params->ParameterValues[i] + j;
+ } else if (storage->type->without_array()->is_image()) {
+ assert(unit >= 0 && unit < prog->sh.NumBindlessImages);
+ prog->sh.BindlessImages[unit].data =
+ &params->ParameterValues[i] + j;
+ }
+ }
+ }
+
/* After attaching the driver's storage to the uniform, propagate any
* data from the linker's backing store. This will cause values from
* initializers in the source code to be copied over.
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:35 UTC
Permalink
Old-style images are identified using TGSI_FILE_IMAGE, but
bindless images can be TGSI_FILE_CONSTANT or TGSI_FILE_TEMPORARY.

To avoid backend compilers to be confused, this adds a new flag
that will only be set for bindless images.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/auxiliary/tgsi/tgsi_build.c | 4 ++++
src/gallium/auxiliary/tgsi/tgsi_ureg.c | 10 +++++++---
src/gallium/auxiliary/tgsi/tgsi_ureg.h | 6 ++++--
src/gallium/include/pipe/p_shader_tokens.h | 3 ++-
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 4 ++--
src/mesa/state_tracker/st_pbo.c | 2 +-
6 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c
index be1931e482..1aa2fd12d4 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_build.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_build.c
@@ -759,6 +759,7 @@ tgsi_default_instruction_memory( void )
instruction_memory.Qualifier = 0;
instruction_memory.Texture = 0;
instruction_memory.Format = 0;
+ instruction_memory.Bindless = 0;
instruction_memory.Padding = 0;

return instruction_memory;
@@ -769,6 +770,7 @@ tgsi_build_instruction_memory(
unsigned qualifier,
unsigned texture,
unsigned format,
+ unsigned bindless,
struct tgsi_token *prev_token,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
@@ -778,6 +780,7 @@ tgsi_build_instruction_memory(
instruction_memory.Qualifier = qualifier;
instruction_memory.Texture = texture;
instruction_memory.Format = format;
+ instruction_memory.Bindless = bindless;
instruction_memory.Padding = 0;
instruction->Memory = 1;

@@ -1137,6 +1140,7 @@ tgsi_build_full_instruction(
full_inst->Memory.Qualifier,
full_inst->Memory.Texture,
full_inst->Memory.Format,
+ full_inst->Memory.Bindless,
prev_token,
instruction,
header );
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
index 8efa95f009..faed1e2708 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
@@ -1324,7 +1324,8 @@ ureg_emit_memory(struct ureg_program *ureg,
unsigned extended_token,
unsigned qualifier,
unsigned texture,
- unsigned format)
+ unsigned format,
+ unsigned bindless)
{
union tgsi_any_token *out, *insn;

@@ -1337,6 +1338,7 @@ ureg_emit_memory(struct ureg_program *ureg,
out[0].insn_memory.Qualifier = qualifier;
out[0].insn_memory.Texture = texture;
out[0].insn_memory.Format = format;
+ out[0].insn_memory.Bindless = bindless;
}

void
@@ -1437,7 +1439,8 @@ ureg_memory_insn(struct ureg_program *ureg,
unsigned nr_src,
unsigned qualifier,
unsigned texture,
- unsigned format)
+ unsigned format,
+ unsigned bindless)
{
struct ureg_emit_insn_result insn;
unsigned i;
@@ -1448,7 +1451,8 @@ ureg_memory_insn(struct ureg_program *ureg,
nr_dst,
nr_src);

- ureg_emit_memory(ureg, insn.extended_token, qualifier, texture, format);
+ ureg_emit_memory(ureg, insn.extended_token, qualifier, texture, format,
+ bindless);

for (i = 0; i < nr_dst; i++)
ureg_emit_dst(ureg, dst[i]);
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
index 9e30a41ff7..fe8620149a 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
@@ -572,7 +572,8 @@ ureg_memory_insn(struct ureg_program *ureg,
unsigned nr_src,
unsigned qualifier,
unsigned texture,
- unsigned format);
+ unsigned format,
+ unsigned bindless);

/***********************************************************************
* Internal instruction helpers, don't call these directly:
@@ -610,7 +611,8 @@ ureg_emit_memory(struct ureg_program *ureg,
unsigned insn_token,
unsigned qualifier,
unsigned texture,
- unsigned format);
+ unsigned format,
+ unsigned bindless);

void
ureg_emit_dst( struct ureg_program *ureg,
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
index 2665eb4235..a4c68b1dbb 100644
--- a/src/gallium/include/pipe/p_shader_tokens.h
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -797,7 +797,8 @@ struct tgsi_instruction_memory
unsigned Qualifier : 3; /* TGSI_MEMORY_ */
unsigned Texture : 8; /* only for images: TGSI_TEXTURE_ */
unsigned Format : 10; /* only for images: PIPE_FORMAT_ */
- unsigned Padding : 11;
+ unsigned Bindless : 1; /* only for images: whether it's bindless */
+ unsigned Padding : 10;
};

#define TGSI_MEMBAR_SHADER_BUFFER (1 << 0)
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 4e6678c8ac..ef6597e083 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -5904,7 +5904,7 @@ compile_tgsi_instruction(struct st_translate *t,
assert(src[0].File != TGSI_FILE_NULL);
ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
inst->buffer_access,
- tex_target, inst->image_format);
+ tex_target, inst->image_format, 0);
break;

case TGSI_OPCODE_STORE:
@@ -5922,7 +5922,7 @@ compile_tgsi_instruction(struct st_translate *t,
assert(dst[0].File != TGSI_FILE_NULL);
ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
inst->buffer_access,
- tex_target, inst->image_format);
+ tex_target, inst->image_format, 0);
break;

case TGSI_OPCODE_SCS:
diff --git a/src/mesa/state_tracker/st_pbo.c b/src/mesa/state_tracker/st_pbo.c
index 303c8535b2..3dff1609e8 100644
--- a/src/mesa/state_tracker/st_pbo.c
+++ b/src/mesa/state_tracker/st_pbo.c
@@ -528,7 +528,7 @@ create_fs(struct st_context *st, bool download, enum pipe_texture_target target,
op[0] = ureg_src(temp0);
op[1] = ureg_src(temp1);
ureg_memory_insn(ureg, TGSI_OPCODE_STORE, &out, 1, op, 2, 0,
- TGSI_TEXTURE_BUFFER, PIPE_FORMAT_NONE);
+ TGSI_TEXTURE_BUFFER, PIPE_FORMAT_NONE, 0);

ureg_release_temporary(ureg, temp1);
} else {
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:36 UTC
Permalink
For example, TGSI_OPCODE_STORE for bindless images might use
a constant buffer or a shader input.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/auxiliary/tgsi/tgsi_ureg.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
index faed1e2708..6c51af3453 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
@@ -1140,8 +1140,6 @@ ureg_emit_dst( struct ureg_program *ureg,
unsigned n = 0;

assert(dst.File != TGSI_FILE_NULL);
- assert(dst.File != TGSI_FILE_CONSTANT);
- assert(dst.File != TGSI_FILE_INPUT);
assert(dst.File != TGSI_FILE_SAMPLER);
assert(dst.File != TGSI_FILE_SAMPLER_VIEW);
assert(dst.File != TGSI_FILE_IMMEDIATE);
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:40 UTC
Permalink
When a texture (or an image) instruction uses a bindless sampler
(respectively a bindless image), make sure the DCE pass won't
remove code when the resource is a temporary variable.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index f30544eb4c..ee1afdcd08 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -5247,6 +5247,21 @@ glsl_to_tgsi_visitor::eliminate_dead_code(void)
}
}
}
+
+ if (inst->resource.file == PROGRAM_TEMPORARY) {
+ int src_chans;
+
+ src_chans = 1 << GET_SWZ(inst->resource.swizzle, 0);
+ src_chans |= 1 << GET_SWZ(inst->resource.swizzle, 1);
+ src_chans |= 1 << GET_SWZ(inst->resource.swizzle, 2);
+ src_chans |= 1 << GET_SWZ(inst->resource.swizzle, 3);
+
+ for (int c = 0; c < 4; c++) {
+ if (src_chans & (1 << c))
+ writes[4 * inst->resource.index + c] = NULL;
+ }
+ }
+
break;
}
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:22 UTC
Permalink
This will also be used for looping over bindless samplers bound
to texture units.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/main/uniforms.c | 67 +++++++++++++++++++++++++++---------------------
1 file changed, 38 insertions(+), 29 deletions(-)

diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index 67c238e4f3..6706f794d7 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c
@@ -63,6 +63,40 @@
* TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
* We'll use that info for state validation before rendering.
*/
+static inline void
+update_single_shader_texture_used(struct gl_shader_program *shProg,
+ struct gl_program *prog,
+ GLuint unit, GLuint target)
+{
+ gl_shader_stage prog_stage =
+ _mesa_program_enum_to_shader_stage(prog->Target);
+
+ assert(unit < ARRAY_SIZE(prog->TexturesUsed));
+ assert(target < NUM_TEXTURE_TARGETS);
+
+ /* From section 7.10 (Samplers) of the OpenGL 4.5 spec:
+ *
+ * "It is not allowed to have variables of different sampler types pointing
+ * to the same texture image unit within a program object."
+ */
+ unsigned stages_mask = shProg->data->linked_stages;
+ while (stages_mask) {
+ const int stage = u_bit_scan(&stages_mask);
+
+ /* Skip validation if we are yet to update textures used in this
+ * stage.
+ */
+ if (prog_stage < stage)
+ break;
+
+ struct gl_program *glprog = shProg->_LinkedShaders[stage]->Program;
+ if (glprog->TexturesUsed[unit] & ~(1 << target))
+ shProg->SamplersValidated = GL_FALSE;
+ }
+
+ prog->TexturesUsed[unit] |= (1 << target);
+}
+
void
_mesa_update_shader_textures_used(struct gl_shader_program *shProg,
struct gl_program *prog)
@@ -78,35 +112,10 @@ _mesa_update_shader_textures_used(struct gl_shader_program *shProg,

while (mask) {
const int s = u_bit_scan(&mask);
- GLuint unit = prog->SamplerUnits[s];
- GLuint tgt = prog->sh.SamplerTargets[s];
- assert(unit < ARRAY_SIZE(prog->TexturesUsed));
- assert(tgt < NUM_TEXTURE_TARGETS);
-
- /* The types of the samplers associated with a particular texture
- * unit must be an exact match. Page 74 (page 89 of the PDF) of the
- * OpenGL 3.3 core spec says:
- *
- * "It is not allowed to have variables of different sampler
- * types pointing to the same texture image unit within a program
- * object."
- */
- unsigned stages_mask = shProg->data->linked_stages;
- while (stages_mask) {
- const int stage = u_bit_scan(&stages_mask);
-
- /* Skip validation if we are yet to update textures used in this
- * stage.
- */
- if (prog_stage < stage)
- break;
-
- struct gl_program *glprog = shProg->_LinkedShaders[stage]->Program;
- if (glprog->TexturesUsed[unit] & ~(1 << tgt))
- shProg->SamplersValidated = GL_FALSE;
- }
-
- prog->TexturesUsed[unit] |= (1 << tgt);
+
+ update_single_shader_texture_used(shProg, prog,
+ prog->SamplerUnits[s],
+ prog->sh.SamplerTargets[s]);
}
}
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:37 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 27 +++++++++++++++++++++------
1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index ef6597e083..5734d0e456 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -306,6 +306,7 @@ public:
unsigned tex_offset_num_offset:3;
unsigned dead_mask:4; /**< Used in dead code elimination */
unsigned buffer_access:3; /**< buffer access type */
+ unsigned bindless:1; /**< bindless sampler/image */

const struct tgsi_opcode_info *info;
};
@@ -4154,6 +4155,7 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
const glsl_type *sampler_type = ir->sampler->type;
unsigned sampler_array_size = 1, sampler_base = 0;
bool is_cube_array = false, is_cube_shadow = false;
+ ir_variable *var = ir->sampler->variable_referenced();
unsigned i;

/* if we are a cube array sampler or a cube shadow */
@@ -4386,7 +4388,7 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
st_src_reg sampler(PROGRAM_SAMPLER, 0, GLSL_TYPE_UINT);

get_deref_offsets(ir->sampler, &sampler_array_size, &sampler_base,
- (uint16_t *)&sampler.index, &reladdr, true);
+ (uint16_t *)&sampler.index, &reladdr, !var->is_bindless());

if (reladdr.file != PROGRAM_UNDEFINED) {
sampler.reladdr = ralloc(mem_ctx, st_src_reg);
@@ -4423,9 +4425,17 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
if (ir->shadow_comparator)
inst->tex_shadow = GL_TRUE;

- inst->resource = sampler;
- inst->sampler_array_size = sampler_array_size;
- inst->sampler_base = sampler_base;
+ if (var->is_bindless()) {
+ ir->sampler->accept(this);
+ inst->resource = this->result;
+ inst->resource.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+ SWIZZLE_X, SWIZZLE_Y);
+ inst->bindless = 1;
+ } else {
+ inst->resource = sampler;
+ inst->sampler_array_size = sampler_array_size;
+ inst->sampler_base = sampler_base;
+ }

if (ir->offset) {
if (!inst->tex_offsets)
@@ -5856,7 +5866,12 @@ compile_tgsi_instruction(struct st_translate *t,
case TGSI_OPCODE_TXL2:
case TGSI_OPCODE_TG4:
case TGSI_OPCODE_LODQ:
- src[num_src] = t->samplers[inst->resource.index];
+ if (inst->resource.file == PROGRAM_SAMPLER) {
+ src[num_src] = t->samplers[inst->resource.index];
+ } else {
+ /* Bindless samplers. */
+ src[num_src] = translate_src(t, &inst->resource);
+ }
assert(src[num_src].File != TGSI_FILE_NULL);
if (inst->resource.reladdr)
src[num_src] =
@@ -5873,7 +5888,7 @@ compile_tgsi_instruction(struct st_translate *t,
tex_target,
st_translate_texture_type(inst->tex_type),
texoffsets, inst->tex_offset_num_offset,
- src, num_src, 0);
+ src, num_src, inst->bindless);
return;

case TGSI_OPCODE_RESQ:
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:38 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 78 ++++++++++++++++++++++++------
1 file changed, 63 insertions(+), 15 deletions(-)

diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 5734d0e456..264b43c10b 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -288,7 +288,7 @@ public:

st_dst_reg dst[2];
st_src_reg src[4];
- st_src_reg resource; /**< sampler or buffer register */
+ st_src_reg resource; /**< sampler, image or buffer register */
st_src_reg *tex_offsets;

/** Pointer to the ir source this tree came from for debugging */
@@ -3765,15 +3765,46 @@ glsl_to_tgsi_visitor::visit_image_intrinsic(ir_call *ir)
exec_node *param = ir->actual_parameters.get_head();

ir_dereference *img = (ir_dereference *)param;
- const ir_variable *imgvar = img->variable_referenced();
- const glsl_type *type = imgvar->type->without_array();
+ const struct glsl_struct_field *struct_field = NULL;
unsigned sampler_array_size = 1, sampler_base = 0;
+ unsigned memory_coherent, memory_volatile, memory_restrict, image_format;
+ const ir_variable *imgvar;
+ const glsl_type *type;
+
+ if (img->ir_type == ir_type_dereference_record) {
+ ir_dereference_record *r = img->as_dereference_record();
+ const glsl_type *struct_type = r->record->type;
+
+ for (unsigned i = 0; i < struct_type->length; i++) {
+ if (!strcmp(struct_type->fields.structure[i].name, r->field)) {
+ struct_field = &struct_type->fields.structure[i];
+ break;
+ }
+ }
+ assert(struct_field);
+ }
+
+ imgvar = img->variable_referenced();
+
+ if (struct_field) {
+ type = struct_field->type;
+ memory_coherent = struct_field->memory_coherent;
+ memory_volatile = struct_field->memory_volatile;
+ memory_restrict = struct_field->memory_restrict;
+ image_format = struct_field->image_format;
+ } else {
+ type = imgvar->type->without_array();
+ memory_coherent = imgvar->data.memory_coherent;
+ memory_volatile = imgvar->data.memory_volatile;
+ memory_restrict = imgvar->data.memory_restrict;
+ image_format = imgvar->data.image_format;
+ }

st_src_reg reladdr;
st_src_reg image(PROGRAM_IMAGE, 0, GLSL_TYPE_UINT);

get_deref_offsets(img, &sampler_array_size, &sampler_base,
- (uint16_t*)&image.index, &reladdr, true);
+ (uint16_t*)&image.index, &reladdr, !imgvar->is_bindless());

if (reladdr.file != PROGRAM_UNDEFINED) {
image.reladdr = ralloc(mem_ctx, st_src_reg);
@@ -3886,19 +3917,27 @@ glsl_to_tgsi_visitor::visit_image_intrinsic(ir_call *ir)
inst->dst[0].writemask = WRITEMASK_XYZW;
}

- inst->resource = image;
- inst->sampler_array_size = sampler_array_size;
- inst->sampler_base = sampler_base;
+ if (imgvar->is_bindless()) {
+ img->accept(this);
+ inst->resource = this->result;
+ inst->resource.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+ SWIZZLE_X, SWIZZLE_Y);
+ inst->bindless = 1;
+ } else {
+ inst->resource = image;
+ inst->sampler_array_size = sampler_array_size;
+ inst->sampler_base = sampler_base;
+ }

inst->tex_target = type->sampler_index();
inst->image_format = st_mesa_format_to_pipe_format(st_context(ctx),
- _mesa_get_shader_image_format(imgvar->data.image_format));
+ _mesa_get_shader_image_format(image_format));

- if (imgvar->data.memory_coherent)
+ if (memory_coherent)
inst->buffer_access |= TGSI_MEMORY_COHERENT;
- if (imgvar->data.memory_restrict)
+ if (memory_restrict)
inst->buffer_access |= TGSI_MEMORY_RESTRICT;
- if (imgvar->data.memory_volatile)
+ if (memory_volatile)
inst->buffer_access |= TGSI_MEMORY_VOLATILE;
}

@@ -5911,7 +5950,12 @@ compile_tgsi_instruction(struct st_translate *t,
} else if (inst->resource.file == PROGRAM_BUFFER) {
src[0] = t->buffers[inst->resource.index];
} else {
- src[0] = t->images[inst->resource.index];
+ if (inst->resource.file == PROGRAM_IMAGE) {
+ src[0] = t->images[inst->resource.index];
+ } else {
+ /* Bindless images. */
+ src[0] = translate_src(t, &inst->resource);
+ }
tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow);
}
if (inst->resource.reladdr)
@@ -5919,7 +5963,7 @@ compile_tgsi_instruction(struct st_translate *t,
assert(src[0].File != TGSI_FILE_NULL);
ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
inst->buffer_access,
- tex_target, inst->image_format, 0);
+ tex_target, inst->image_format, inst->bindless);
break;

case TGSI_OPCODE_STORE:
@@ -5928,7 +5972,11 @@ compile_tgsi_instruction(struct st_translate *t,
} else if (inst->resource.file == PROGRAM_BUFFER) {
dst[0] = ureg_dst(t->buffers[inst->resource.index]);
} else {
- dst[0] = ureg_dst(t->images[inst->resource.index]);
+ if (inst->resource.file == PROGRAM_IMAGE) {
+ dst[0] = ureg_dst(t->images[inst->resource.index]);
+ } else {
+ dst[0] = ureg_dst(translate_src(t, &inst->resource));
+ }
tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow);
}
dst[0] = ureg_writemask(dst[0], inst->dst[0].writemask);
@@ -5937,7 +5985,7 @@ compile_tgsi_instruction(struct st_translate *t,
assert(dst[0].File != TGSI_FILE_NULL);
ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
inst->buffer_access,
- tex_target, inst->image_format, 0);
+ tex_target, inst->image_format, inst->bindless);
break;

case TGSI_OPCODE_SCS:
--
2.13.0
Nicolai Hähnle
2017-05-24 11:34:09 UTC
Permalink
Post by Samuel Pitoiset
---
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 78 ++++++++++++++++++++++++------
1 file changed, 63 insertions(+), 15 deletions(-)
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 5734d0e456..264b43c10b 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
st_dst_reg dst[2];
st_src_reg src[4];
- st_src_reg resource; /**< sampler or buffer register */
+ st_src_reg resource; /**< sampler, image or buffer register */
st_src_reg *tex_offsets;
/** Pointer to the ir source this tree came from for debugging */
@@ -3765,15 +3765,46 @@ glsl_to_tgsi_visitor::visit_image_intrinsic(ir_call *ir)
exec_node *param = ir->actual_parameters.get_head();
ir_dereference *img = (ir_dereference *)param;
- const ir_variable *imgvar = img->variable_referenced();
- const glsl_type *type = imgvar->type->without_array();
+ const struct glsl_struct_field *struct_field = NULL;
unsigned sampler_array_size = 1, sampler_base = 0;
+ unsigned memory_coherent, memory_volatile, memory_restrict, image_format;
+ const ir_variable *imgvar;
+ const glsl_type *type;
+
+ if (img->ir_type == ir_type_dereference_record) {
+ ir_dereference_record *r = img->as_dereference_record();
+ const glsl_type *struct_type = r->record->type;
+
+ for (unsigned i = 0; i < struct_type->length; i++) {
+ if (!strcmp(struct_type->fields.structure[i].name, r->field)) {
+ struct_field = &struct_type->fields.structure[i];
+ break;
+ }
+ }
+ assert(struct_field);
+ }
+
+ imgvar = img->variable_referenced();
+
+ if (struct_field) {
+ type = struct_field->type;
+ memory_coherent = struct_field->memory_coherent;
+ memory_volatile = struct_field->memory_volatile;
+ memory_restrict = struct_field->memory_restrict;
+ image_format = struct_field->image_format;
+ } else {
+ type = imgvar->type->without_array();
+ memory_coherent = imgvar->data.memory_coherent;
+ memory_volatile = imgvar->data.memory_volatile;
+ memory_restrict = imgvar->data.memory_restrict;
+ image_format = imgvar->data.image_format;
+ }
What about

struct {
coherent image2D imgs[6];
} s;

imageStore(s.imgs[i], ...);

and obviously nested arrays. I think you need to follow the dereferences
until you hit the first ir_dereference_record or ir_dereference_variable.

Cheers,
Nicolai
Post by Samuel Pitoiset
st_src_reg reladdr;
st_src_reg image(PROGRAM_IMAGE, 0, GLSL_TYPE_UINT);
get_deref_offsets(img, &sampler_array_size, &sampler_base,
- (uint16_t*)&image.index, &reladdr, true);
+ (uint16_t*)&image.index, &reladdr, !imgvar->is_bindless());
if (reladdr.file != PROGRAM_UNDEFINED) {
image.reladdr = ralloc(mem_ctx, st_src_reg);
@@ -3886,19 +3917,27 @@ glsl_to_tgsi_visitor::visit_image_intrinsic(ir_call *ir)
inst->dst[0].writemask = WRITEMASK_XYZW;
}
- inst->resource = image;
- inst->sampler_array_size = sampler_array_size;
- inst->sampler_base = sampler_base;
+ if (imgvar->is_bindless()) {
+ img->accept(this);
+ inst->resource = this->result;
+ inst->resource.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+ SWIZZLE_X, SWIZZLE_Y);
+ inst->bindless = 1;
+ } else {
+ inst->resource = image;
+ inst->sampler_array_size = sampler_array_size;
+ inst->sampler_base = sampler_base;
+ }
inst->tex_target = type->sampler_index();
inst->image_format = st_mesa_format_to_pipe_format(st_context(ctx),
- _mesa_get_shader_image_format(imgvar->data.image_format));
+ _mesa_get_shader_image_format(image_format));
- if (imgvar->data.memory_coherent)
+ if (memory_coherent)
inst->buffer_access |= TGSI_MEMORY_COHERENT;
- if (imgvar->data.memory_restrict)
+ if (memory_restrict)
inst->buffer_access |= TGSI_MEMORY_RESTRICT;
- if (imgvar->data.memory_volatile)
+ if (memory_volatile)
inst->buffer_access |= TGSI_MEMORY_VOLATILE;
}
@@ -5911,7 +5950,12 @@ compile_tgsi_instruction(struct st_translate *t,
} else if (inst->resource.file == PROGRAM_BUFFER) {
src[0] = t->buffers[inst->resource.index];
} else {
- src[0] = t->images[inst->resource.index];
+ if (inst->resource.file == PROGRAM_IMAGE) {
+ src[0] = t->images[inst->resource.index];
+ } else {
+ /* Bindless images. */
+ src[0] = translate_src(t, &inst->resource);
+ }
tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow);
}
if (inst->resource.reladdr)
@@ -5919,7 +5963,7 @@ compile_tgsi_instruction(struct st_translate *t,
assert(src[0].File != TGSI_FILE_NULL);
ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
inst->buffer_access,
- tex_target, inst->image_format, 0);
+ tex_target, inst->image_format, inst->bindless);
break;
@@ -5928,7 +5972,11 @@ compile_tgsi_instruction(struct st_translate *t,
} else if (inst->resource.file == PROGRAM_BUFFER) {
dst[0] = ureg_dst(t->buffers[inst->resource.index]);
} else {
- dst[0] = ureg_dst(t->images[inst->resource.index]);
+ if (inst->resource.file == PROGRAM_IMAGE) {
+ dst[0] = ureg_dst(t->images[inst->resource.index]);
+ } else {
+ dst[0] = ureg_dst(translate_src(t, &inst->resource));
+ }
tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow);
}
dst[0] = ureg_writemask(dst[0], inst->dst[0].writemask);
@@ -5937,7 +5985,7 @@ compile_tgsi_instruction(struct st_translate *t,
assert(dst[0].File != TGSI_FILE_NULL);
ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
inst->buffer_access,
- tex_target, inst->image_format, 0);
+ tex_target, inst->image_format, inst->bindless);
break;
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
Samuel Pitoiset
2017-05-25 12:08:26 UTC
Permalink
Post by Nicolai Hähnle
Post by Samuel Pitoiset
---
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 78
++++++++++++++++++++++++------
1 file changed, 63 insertions(+), 15 deletions(-)
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 5734d0e456..264b43c10b 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
st_dst_reg dst[2];
st_src_reg src[4];
- st_src_reg resource; /**< sampler or buffer register */
+ st_src_reg resource; /**< sampler, image or buffer register */
st_src_reg *tex_offsets;
/** Pointer to the ir source this tree came from for debugging */
@@ -3765,15 +3765,46 @@
glsl_to_tgsi_visitor::visit_image_intrinsic(ir_call *ir)
exec_node *param = ir->actual_parameters.get_head();
ir_dereference *img = (ir_dereference *)param;
- const ir_variable *imgvar = img->variable_referenced();
- const glsl_type *type = imgvar->type->without_array();
+ const struct glsl_struct_field *struct_field = NULL;
unsigned sampler_array_size = 1, sampler_base = 0;
+ unsigned memory_coherent, memory_volatile, memory_restrict, image_format;
+ const ir_variable *imgvar;
+ const glsl_type *type;
+
+ if (img->ir_type == ir_type_dereference_record) {
+ ir_dereference_record *r = img->as_dereference_record();
+ const glsl_type *struct_type = r->record->type;
+
+ for (unsigned i = 0; i < struct_type->length; i++) {
+ if (!strcmp(struct_type->fields.structure[i].name, r->field)) {
+ struct_field = &struct_type->fields.structure[i];
+ break;
+ }
+ }
+ assert(struct_field);
+ }
+
+ imgvar = img->variable_referenced();
+
+ if (struct_field) {
+ type = struct_field->type;
+ memory_coherent = struct_field->memory_coherent;
+ memory_volatile = struct_field->memory_volatile;
+ memory_restrict = struct_field->memory_restrict;
+ image_format = struct_field->image_format;
+ } else {
+ type = imgvar->type->without_array();
+ memory_coherent = imgvar->data.memory_coherent;
+ memory_volatile = imgvar->data.memory_volatile;
+ memory_restrict = imgvar->data.memory_restrict;
+ image_format = imgvar->data.image_format;
+ }
What about
struct {
coherent image2D imgs[6];
} s;
imageStore(s.imgs[i], ...);
and obviously nested arrays. I think you need to follow the dereferences
until you hit the first ir_dereference_record or ir_dereference_variable.
This is right. I'm going to fix it up.
Post by Nicolai Hähnle
Cheers,
Nicolai
Post by Samuel Pitoiset
st_src_reg reladdr;
st_src_reg image(PROGRAM_IMAGE, 0, GLSL_TYPE_UINT);
get_deref_offsets(img, &sampler_array_size, &sampler_base,
- (uint16_t*)&image.index, &reladdr, true);
+ (uint16_t*)&image.index, &reladdr,
!imgvar->is_bindless());
if (reladdr.file != PROGRAM_UNDEFINED) {
image.reladdr = ralloc(mem_ctx, st_src_reg);
@@ -3886,19 +3917,27 @@
glsl_to_tgsi_visitor::visit_image_intrinsic(ir_call *ir)
inst->dst[0].writemask = WRITEMASK_XYZW;
}
- inst->resource = image;
- inst->sampler_array_size = sampler_array_size;
- inst->sampler_base = sampler_base;
+ if (imgvar->is_bindless()) {
+ img->accept(this);
+ inst->resource = this->result;
+ inst->resource.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+ SWIZZLE_X, SWIZZLE_Y);
+ inst->bindless = 1;
+ } else {
+ inst->resource = image;
+ inst->sampler_array_size = sampler_array_size;
+ inst->sampler_base = sampler_base;
+ }
inst->tex_target = type->sampler_index();
inst->image_format = st_mesa_format_to_pipe_format(st_context(ctx),
- _mesa_get_shader_image_format(imgvar->data.image_format));
+ _mesa_get_shader_image_format(image_format));
- if (imgvar->data.memory_coherent)
+ if (memory_coherent)
inst->buffer_access |= TGSI_MEMORY_COHERENT;
- if (imgvar->data.memory_restrict)
+ if (memory_restrict)
inst->buffer_access |= TGSI_MEMORY_RESTRICT;
- if (imgvar->data.memory_volatile)
+ if (memory_volatile)
inst->buffer_access |= TGSI_MEMORY_VOLATILE;
}
@@ -5911,7 +5950,12 @@ compile_tgsi_instruction(struct st_translate *t,
} else if (inst->resource.file == PROGRAM_BUFFER) {
src[0] = t->buffers[inst->resource.index];
} else {
- src[0] = t->images[inst->resource.index];
+ if (inst->resource.file == PROGRAM_IMAGE) {
+ src[0] = t->images[inst->resource.index];
+ } else {
+ /* Bindless images. */
+ src[0] = translate_src(t, &inst->resource);
+ }
tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow);
}
if (inst->resource.reladdr)
@@ -5919,7 +5963,7 @@ compile_tgsi_instruction(struct st_translate *t,
assert(src[0].File != TGSI_FILE_NULL);
ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
inst->buffer_access,
- tex_target, inst->image_format, 0);
+ tex_target, inst->image_format, inst->bindless);
break;
@@ -5928,7 +5972,11 @@ compile_tgsi_instruction(struct st_translate *t,
} else if (inst->resource.file == PROGRAM_BUFFER) {
dst[0] = ureg_dst(t->buffers[inst->resource.index]);
} else {
- dst[0] = ureg_dst(t->images[inst->resource.index]);
+ if (inst->resource.file == PROGRAM_IMAGE) {
+ dst[0] = ureg_dst(t->images[inst->resource.index]);
+ } else {
+ dst[0] = ureg_dst(translate_src(t, &inst->resource));
+ }
tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow);
}
dst[0] = ureg_writemask(dst[0], inst->dst[0].writemask);
@@ -5937,7 +5985,7 @@ compile_tgsi_instruction(struct st_translate *t,
assert(dst[0].File != TGSI_FILE_NULL);
ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
inst->buffer_access,
- tex_target, inst->image_format, 0);
+ tex_target, inst->image_format, inst->bindless);
break;
Samuel Pitoiset
2017-05-19 16:52:27 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/main/uniform_query.cpp | 122 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 116 insertions(+), 6 deletions(-)

diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp
index cc145f29e9..be04e48d53 100644
--- a/src/mesa/main/uniform_query.cpp
+++ b/src/mesa/main/uniform_query.cpp
@@ -993,9 +993,25 @@ _mesa_uniform(GLint location, GLsizei count, const GLvoid *values,
bool changed = false;
for (int j = 0; j < count; j++) {
unsigned unit = uni->opaque[i].index + offset + j;
- if (sh->Program->SamplerUnits[unit] != ((unsigned *) values)[j]) {
- sh->Program->SamplerUnits[unit] = ((unsigned *) values)[j];
- changed = true;
+ unsigned value = ((unsigned *)values)[j];
+
+ if (uni->is_bindless) {
+ struct gl_bindless_sampler *sampler =
+ &sh->Program->sh.BindlessSamplers[unit];
+
+ /* Mark this bindless sampler as bound to a texture unit.
+ */
+ if (sampler->unit != value) {
+ sampler->unit = value;
+ changed = true;
+ }
+ sampler->bound = true;
+ sh->Program->sh.HasBoundBindlessSampler = true;
+ } else {
+ if (sh->Program->SamplerUnits[unit] != value) {
+ sh->Program->SamplerUnits[unit] = value;
+ changed = true;
+ }
}
}

@@ -1024,9 +1040,23 @@ _mesa_uniform(GLint location, GLsizei count, const GLvoid *values,
if (!uni->opaque[i].active)
continue;

- for (int j = 0; j < count; j++)
- sh->Program->sh.ImageUnits[uni->opaque[i].index + offset + j] =
- ((GLint *) values)[j];
+ for (int j = 0; j < count; j++) {
+ unsigned unit = uni->opaque[i].index + offset + j;
+ unsigned value = ((unsigned *)values)[j];
+
+ if (uni->is_bindless) {
+ struct gl_bindless_image *image =
+ &sh->Program->sh.BindlessImages[unit];
+
+ /* Mark this bindless image as bound to an image unit.
+ */
+ image->unit = value;
+ image->bound = true;
+ sh->Program->sh.HasBoundBindlessImage = true;
+ } else {
+ sh->Program->sh.ImageUnits[unit] = value;
+ }
+ }
}

ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
@@ -1173,6 +1203,40 @@ _mesa_uniform_matrix(GLint location, GLsizei count,
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
}

+static void
+update_bound_bindless_sampler_flag(struct gl_program *prog)
+{
+ unsigned i;
+
+ if (likely(!prog->sh.HasBoundBindlessSampler))
+ return;
+
+ for (i = 0; i < prog->sh.NumBindlessSamplers; i++) {
+ struct gl_bindless_sampler *sampler = &prog->sh.BindlessSamplers[i];
+
+ if (sampler->bound)
+ return;
+ }
+ prog->sh.HasBoundBindlessSampler = false;
+}
+
+static void
+update_bound_bindless_image_flag(struct gl_program *prog)
+{
+ unsigned i;
+
+ if (likely(!prog->sh.HasBoundBindlessImage))
+ return;
+
+ for (i = 0; i < prog->sh.NumBindlessImages; i++) {
+ struct gl_bindless_image *image = &prog->sh.BindlessImages[i];
+
+ if (image->bound)
+ return;
+ }
+ prog->sh.HasBoundBindlessImage = false;
+}
+
/**
* Called via glUniformHandleui64*ARB() functions.
*/
@@ -1236,6 +1300,52 @@ _mesa_uniform_handle(GLint location, GLsizei count, const GLvoid *values,
sizeof(uni->storage[0]) * components * count * size_mul);

_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
+
+ if (uni->type->is_sampler()) {
+ /* Mark this bindless sampler as not bound to a texture unit because
+ * it refers to a texture handle.
+ */
+ for (int i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *const sh = shProg->_LinkedShaders[i];
+
+ /* If the shader stage doesn't use the sampler uniform, skip this. */
+ if (!uni->opaque[i].active)
+ continue;
+
+ for (int j = 0; j < count; j++) {
+ unsigned unit = uni->opaque[i].index + offset + j;
+ struct gl_bindless_sampler *sampler =
+ &sh->Program->sh.BindlessSamplers[unit];
+
+ sampler->bound = false;
+ }
+
+ update_bound_bindless_sampler_flag(sh->Program);
+ }
+ }
+
+ if (uni->type->is_image()) {
+ /* Mark this bindless image as not bound to an image unit because it
+ * refers to a texture handle.
+ */
+ for (int i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *sh = shProg->_LinkedShaders[i];
+
+ /* If the shader stage doesn't use the sampler uniform, skip this. */
+ if (!uni->opaque[i].active)
+ continue;
+
+ for (int j = 0; j < count; j++) {
+ unsigned unit = uni->opaque[i].index + offset + j;
+ struct gl_bindless_image *image =
+ &sh->Program->sh.BindlessImages[unit];
+
+ image->bound = false;
+ }
+
+ update_bound_bindless_image_flag(sh->Program);
+ }
+ }
}

extern "C" bool
--
2.13.0
Nicolai Hähnle
2017-05-26 09:09:22 UTC
Permalink
Something else just occurred to me. Do you have a test case where an
array of bindless sampler uniforms is set at once with glUniform1iv?
https://hastebin.com/jiduzevage
Works fine.
I really think this is pure chance (and I think I see why it works in
the code), but in part it's because you didn't test rendering with a
uniform array of samplers.

On the second thought, the whole uni->is_bindless_handle design can't
possibly work. Consider an array

layout(bindless_texture) uniform sampler2D tex[2];

which is bound with

glUniform1i(loc, tex_unit);
glUniformHandleui64ARB(loc + 1, handle);

We don't need uni->is_bindless_handle; what we do need is that each of
_mesa_uniform, _mesa_uniform_handle, and _mesa_get_uniform use size_mul
== 2 unconditionally when the uniform is bindless.

Cheers,
Nicolai
That should have a 32- vs. 64-bit mismatch when the user-supplied
array is directly memcpy()'d to uni->storage. I think you need to fix
that mismatch. On the plus side, that probably makes patch #23
unnecessary.
I don't see where a mismatch could happen actually.
Cheers,
Nicolai
Post by Samuel Pitoiset
---
src/mesa/main/uniform_query.cpp | 122
++++++++++++++++++++++++++++++++++++++--
1 file changed, 116 insertions(+), 6 deletions(-)
diff --git a/src/mesa/main/uniform_query.cpp
b/src/mesa/main/uniform_query.cpp
index cc145f29e9..be04e48d53 100644
--- a/src/mesa/main/uniform_query.cpp
+++ b/src/mesa/main/uniform_query.cpp
@@ -993,9 +993,25 @@ _mesa_uniform(GLint location, GLsizei count, const GLvoid *values,
bool changed = false;
for (int j = 0; j < count; j++) {
unsigned unit = uni->opaque[i].index + offset + j;
- if (sh->Program->SamplerUnits[unit] != ((unsigned *) values)[j]) {
- sh->Program->SamplerUnits[unit] = ((unsigned *) values)[j];
- changed = true;
+ unsigned value = ((unsigned *)values)[j];
+
+ if (uni->is_bindless) {
+ struct gl_bindless_sampler *sampler =
+ &sh->Program->sh.BindlessSamplers[unit];
+
+ /* Mark this bindless sampler as bound to a texture unit.
+ */
+ if (sampler->unit != value) {
+ sampler->unit = value;
+ changed = true;
+ }
+ sampler->bound = true;
+ sh->Program->sh.HasBoundBindlessSampler = true;
+ } else {
+ if (sh->Program->SamplerUnits[unit] != value) {
+ sh->Program->SamplerUnits[unit] = value;
+ changed = true;
+ }
}
}
@@ -1024,9 +1040,23 @@ _mesa_uniform(GLint location, GLsizei count,
const GLvoid *values,
if (!uni->opaque[i].active)
continue;
- for (int j = 0; j < count; j++)
- sh->Program->sh.ImageUnits[uni->opaque[i].index + offset + j] =
- ((GLint *) values)[j];
+ for (int j = 0; j < count; j++) {
+ unsigned unit = uni->opaque[i].index + offset + j;
+ unsigned value = ((unsigned *)values)[j];
+
+ if (uni->is_bindless) {
+ struct gl_bindless_image *image =
+ &sh->Program->sh.BindlessImages[unit];
+
+ /* Mark this bindless image as bound to an image unit.
+ */
+ image->unit = value;
+ image->bound = true;
+ sh->Program->sh.HasBoundBindlessImage = true;
+ } else {
+ sh->Program->sh.ImageUnits[unit] = value;
+ }
+ }
}
ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
@@ -1173,6 +1203,40 @@ _mesa_uniform_matrix(GLint location, GLsizei count,
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
}
+static void
+update_bound_bindless_sampler_flag(struct gl_program *prog)
+{
+ unsigned i;
+
+ if (likely(!prog->sh.HasBoundBindlessSampler))
+ return;
+
+ for (i = 0; i < prog->sh.NumBindlessSamplers; i++) {
+ struct gl_bindless_sampler *sampler =
&prog->sh.BindlessSamplers[i];
+
+ if (sampler->bound)
+ return;
+ }
+ prog->sh.HasBoundBindlessSampler = false;
+}
+
+static void
+update_bound_bindless_image_flag(struct gl_program *prog)
+{
+ unsigned i;
+
+ if (likely(!prog->sh.HasBoundBindlessImage))
+ return;
+
+ for (i = 0; i < prog->sh.NumBindlessImages; i++) {
+ struct gl_bindless_image *image = &prog->sh.BindlessImages[i];
+
+ if (image->bound)
+ return;
+ }
+ prog->sh.HasBoundBindlessImage = false;
+}
+
/**
* Called via glUniformHandleui64*ARB() functions.
*/
@@ -1236,6 +1300,52 @@ _mesa_uniform_handle(GLint location, GLsizei
count, const GLvoid *values,
sizeof(uni->storage[0]) * components * count * size_mul);
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
+
+ if (uni->type->is_sampler()) {
+ /* Mark this bindless sampler as not bound to a texture unit because
+ * it refers to a texture handle.
+ */
+ for (int i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *const sh = shProg->_LinkedShaders[i];
+
+ /* If the shader stage doesn't use the sampler uniform, skip this. */
+ if (!uni->opaque[i].active)
+ continue;
+
+ for (int j = 0; j < count; j++) {
+ unsigned unit = uni->opaque[i].index + offset + j;
+ struct gl_bindless_sampler *sampler =
+ &sh->Program->sh.BindlessSamplers[unit];
+
+ sampler->bound = false;
+ }
+
+ update_bound_bindless_sampler_flag(sh->Program);
+ }
+ }
+
+ if (uni->type->is_image()) {
+ /* Mark this bindless image as not bound to an image unit because it
+ * refers to a texture handle.
+ */
+ for (int i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *sh = shProg->_LinkedShaders[i];
+
+ /* If the shader stage doesn't use the sampler uniform, skip this. */
+ if (!uni->opaque[i].active)
+ continue;
+
+ for (int j = 0; j < count; j++) {
+ unsigned unit = uni->opaque[i].index + offset + j;
+ struct gl_bindless_image *image =
+ &sh->Program->sh.BindlessImages[unit];
+
+ image->bound = false;
+ }
+
+ update_bound_bindless_image_flag(sh->Program);
+ }
+ }
}
extern "C" bool
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
Samuel Pitoiset
2017-05-26 12:10:10 UTC
Permalink
Post by Nicolai Hähnle
Something else just occurred to me. Do you have a test case where an
array of bindless sampler uniforms is set at once with glUniform1iv?
https://hastebin.com/jiduzevage
Works fine.
I really think this is pure chance (and I think I see why it works in
the code), but in part it's because you didn't test rendering with a
uniform array of samplers.
On the second thought, the whole uni->is_bindless_handle design can't
possibly work. Consider an array
layout(bindless_texture) uniform sampler2D tex[2];
which is bound with
glUniform1i(loc, tex_unit);
glUniformHandleui64ARB(loc + 1, handle);
We don't need uni->is_bindless_handle; what we do need is that each of
_mesa_uniform, _mesa_uniform_handle, and _mesa_get_uniform use size_mul
== 2 unconditionally when the uniform is bindless.
Ah right, this can't fly. I will fix it.
Thanks.
Post by Nicolai Hähnle
Cheers,
Nicolai
That should have a 32- vs. 64-bit mismatch when the user-supplied
array is directly memcpy()'d to uni->storage. I think you need to fix
that mismatch. On the plus side, that probably makes patch #23
unnecessary.
I don't see where a mismatch could happen actually.
Cheers,
Nicolai
Post by Samuel Pitoiset
---
src/mesa/main/uniform_query.cpp | 122
++++++++++++++++++++++++++++++++++++++--
1 file changed, 116 insertions(+), 6 deletions(-)
diff --git a/src/mesa/main/uniform_query.cpp
b/src/mesa/main/uniform_query.cpp
index cc145f29e9..be04e48d53 100644
--- a/src/mesa/main/uniform_query.cpp
+++ b/src/mesa/main/uniform_query.cpp
@@ -993,9 +993,25 @@ _mesa_uniform(GLint location, GLsizei count,
const GLvoid *values,
bool changed = false;
for (int j = 0; j < count; j++) {
unsigned unit = uni->opaque[i].index + offset + j;
- if (sh->Program->SamplerUnits[unit] != ((unsigned *) values)[j]) {
- sh->Program->SamplerUnits[unit] = ((unsigned *) values)[j];
- changed = true;
+ unsigned value = ((unsigned *)values)[j];
+
+ if (uni->is_bindless) {
+ struct gl_bindless_sampler *sampler =
+ &sh->Program->sh.BindlessSamplers[unit];
+
+ /* Mark this bindless sampler as bound to a texture unit.
+ */
+ if (sampler->unit != value) {
+ sampler->unit = value;
+ changed = true;
+ }
+ sampler->bound = true;
+ sh->Program->sh.HasBoundBindlessSampler = true;
+ } else {
+ if (sh->Program->SamplerUnits[unit] != value) {
+ sh->Program->SamplerUnits[unit] = value;
+ changed = true;
+ }
}
}
@@ -1024,9 +1040,23 @@ _mesa_uniform(GLint location, GLsizei count,
const GLvoid *values,
if (!uni->opaque[i].active)
continue;
- for (int j = 0; j < count; j++)
- sh->Program->sh.ImageUnits[uni->opaque[i].index + offset + j] =
- ((GLint *) values)[j];
+ for (int j = 0; j < count; j++) {
+ unsigned unit = uni->opaque[i].index + offset + j;
+ unsigned value = ((unsigned *)values)[j];
+
+ if (uni->is_bindless) {
+ struct gl_bindless_image *image =
+ &sh->Program->sh.BindlessImages[unit];
+
+ /* Mark this bindless image as bound to an image unit.
+ */
+ image->unit = value;
+ image->bound = true;
+ sh->Program->sh.HasBoundBindlessImage = true;
+ } else {
+ sh->Program->sh.ImageUnits[unit] = value;
+ }
+ }
}
ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
@@ -1173,6 +1203,40 @@ _mesa_uniform_matrix(GLint location, GLsizei count,
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
}
+static void
+update_bound_bindless_sampler_flag(struct gl_program *prog)
+{
+ unsigned i;
+
+ if (likely(!prog->sh.HasBoundBindlessSampler))
+ return;
+
+ for (i = 0; i < prog->sh.NumBindlessSamplers; i++) {
+ struct gl_bindless_sampler *sampler =
&prog->sh.BindlessSamplers[i];
+
+ if (sampler->bound)
+ return;
+ }
+ prog->sh.HasBoundBindlessSampler = false;
+}
+
+static void
+update_bound_bindless_image_flag(struct gl_program *prog)
+{
+ unsigned i;
+
+ if (likely(!prog->sh.HasBoundBindlessImage))
+ return;
+
+ for (i = 0; i < prog->sh.NumBindlessImages; i++) {
+ struct gl_bindless_image *image = &prog->sh.BindlessImages[i];
+
+ if (image->bound)
+ return;
+ }
+ prog->sh.HasBoundBindlessImage = false;
+}
+
/**
* Called via glUniformHandleui64*ARB() functions.
*/
@@ -1236,6 +1300,52 @@ _mesa_uniform_handle(GLint location, GLsizei
count, const GLvoid *values,
sizeof(uni->storage[0]) * components * count * size_mul);
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
+
+ if (uni->type->is_sampler()) {
+ /* Mark this bindless sampler as not bound to a texture unit because
+ * it refers to a texture handle.
+ */
+ for (int i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *const sh =
shProg->_LinkedShaders[i];
+
+ /* If the shader stage doesn't use the sampler uniform, skip this. */
+ if (!uni->opaque[i].active)
+ continue;
+
+ for (int j = 0; j < count; j++) {
+ unsigned unit = uni->opaque[i].index + offset + j;
+ struct gl_bindless_sampler *sampler =
+ &sh->Program->sh.BindlessSamplers[unit];
+
+ sampler->bound = false;
+ }
+
+ update_bound_bindless_sampler_flag(sh->Program);
+ }
+ }
+
+ if (uni->type->is_image()) {
+ /* Mark this bindless image as not bound to an image unit because it
+ * refers to a texture handle.
+ */
+ for (int i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *sh = shProg->_LinkedShaders[i];
+
+ /* If the shader stage doesn't use the sampler uniform, skip this. */
+ if (!uni->opaque[i].active)
+ continue;
+
+ for (int j = 0; j < count; j++) {
+ unsigned unit = uni->opaque[i].index + offset + j;
+ struct gl_bindless_image *image =
+ &sh->Program->sh.BindlessImages[unit];
+
+ image->bound = false;
+ }
+
+ update_bound_bindless_image_flag(sh->Program);
+ }
+ }
}
extern "C" bool
Samuel Pitoiset
2017-05-25 09:42:42 UTC
Permalink
Something else just occurred to me. Do you have a test case where an
array of bindless sampler uniforms is set at once with glUniform1iv?
I don't have, but I will write one right now.
That should have a 32- vs. 64-bit mismatch when the user-supplied array
is directly memcpy()'d to uni->storage. I think you need to fix that
mismatch. On the plus side, that probably makes patch #23 unnecessary.
Cheers,
Nicolai
Post by Samuel Pitoiset
---
src/mesa/main/uniform_query.cpp | 122
++++++++++++++++++++++++++++++++++++++--
1 file changed, 116 insertions(+), 6 deletions(-)
diff --git a/src/mesa/main/uniform_query.cpp
b/src/mesa/main/uniform_query.cpp
index cc145f29e9..be04e48d53 100644
--- a/src/mesa/main/uniform_query.cpp
+++ b/src/mesa/main/uniform_query.cpp
@@ -993,9 +993,25 @@ _mesa_uniform(GLint location, GLsizei count, const GLvoid *values,
bool changed = false;
for (int j = 0; j < count; j++) {
unsigned unit = uni->opaque[i].index + offset + j;
- if (sh->Program->SamplerUnits[unit] != ((unsigned *) values)[j]) {
- sh->Program->SamplerUnits[unit] = ((unsigned *) values)[j];
- changed = true;
+ unsigned value = ((unsigned *)values)[j];
+
+ if (uni->is_bindless) {
+ struct gl_bindless_sampler *sampler =
+ &sh->Program->sh.BindlessSamplers[unit];
+
+ /* Mark this bindless sampler as bound to a texture unit.
+ */
+ if (sampler->unit != value) {
+ sampler->unit = value;
+ changed = true;
+ }
+ sampler->bound = true;
+ sh->Program->sh.HasBoundBindlessSampler = true;
+ } else {
+ if (sh->Program->SamplerUnits[unit] != value) {
+ sh->Program->SamplerUnits[unit] = value;
+ changed = true;
+ }
}
}
@@ -1024,9 +1040,23 @@ _mesa_uniform(GLint location, GLsizei count, const GLvoid *values,
if (!uni->opaque[i].active)
continue;
- for (int j = 0; j < count; j++)
- sh->Program->sh.ImageUnits[uni->opaque[i].index + offset + j] =
- ((GLint *) values)[j];
+ for (int j = 0; j < count; j++) {
+ unsigned unit = uni->opaque[i].index + offset + j;
+ unsigned value = ((unsigned *)values)[j];
+
+ if (uni->is_bindless) {
+ struct gl_bindless_image *image =
+ &sh->Program->sh.BindlessImages[unit];
+
+ /* Mark this bindless image as bound to an image unit.
+ */
+ image->unit = value;
+ image->bound = true;
+ sh->Program->sh.HasBoundBindlessImage = true;
+ } else {
+ sh->Program->sh.ImageUnits[unit] = value;
+ }
+ }
}
ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
@@ -1173,6 +1203,40 @@ _mesa_uniform_matrix(GLint location, GLsizei count,
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
}
+static void
+update_bound_bindless_sampler_flag(struct gl_program *prog)
+{
+ unsigned i;
+
+ if (likely(!prog->sh.HasBoundBindlessSampler))
+ return;
+
+ for (i = 0; i < prog->sh.NumBindlessSamplers; i++) {
+ struct gl_bindless_sampler *sampler =
&prog->sh.BindlessSamplers[i];
+
+ if (sampler->bound)
+ return;
+ }
+ prog->sh.HasBoundBindlessSampler = false;
+}
+
+static void
+update_bound_bindless_image_flag(struct gl_program *prog)
+{
+ unsigned i;
+
+ if (likely(!prog->sh.HasBoundBindlessImage))
+ return;
+
+ for (i = 0; i < prog->sh.NumBindlessImages; i++) {
+ struct gl_bindless_image *image = &prog->sh.BindlessImages[i];
+
+ if (image->bound)
+ return;
+ }
+ prog->sh.HasBoundBindlessImage = false;
+}
+
/**
* Called via glUniformHandleui64*ARB() functions.
*/
@@ -1236,6 +1300,52 @@ _mesa_uniform_handle(GLint location, GLsizei
count, const GLvoid *values,
sizeof(uni->storage[0]) * components * count * size_mul);
_mesa_propagate_uniforms_to_driver_storage(uni, offset, count);
+
+ if (uni->type->is_sampler()) {
+ /* Mark this bindless sampler as not bound to a texture unit because
+ * it refers to a texture handle.
+ */
+ for (int i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *const sh = shProg->_LinkedShaders[i];
+
+ /* If the shader stage doesn't use the sampler uniform, skip this. */
+ if (!uni->opaque[i].active)
+ continue;
+
+ for (int j = 0; j < count; j++) {
+ unsigned unit = uni->opaque[i].index + offset + j;
+ struct gl_bindless_sampler *sampler =
+ &sh->Program->sh.BindlessSamplers[unit];
+
+ sampler->bound = false;
+ }
+
+ update_bound_bindless_sampler_flag(sh->Program);
+ }
+ }
+
+ if (uni->type->is_image()) {
+ /* Mark this bindless image as not bound to an image unit because it
+ * refers to a texture handle.
+ */
+ for (int i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *sh = shProg->_LinkedShaders[i];
+
+ /* If the shader stage doesn't use the sampler uniform, skip this. */
+ if (!uni->opaque[i].active)
+ continue;
+
+ for (int j = 0; j < count; j++) {
+ unsigned unit = uni->opaque[i].index + offset + j;
+ struct gl_bindless_image *image =
+ &sh->Program->sh.BindlessImages[unit];
+
+ image->bound = false;
+ }
+
+ update_bound_bindless_image_flag(sh->Program);
+ }
+ }
}
extern "C" bool
Samuel Pitoiset
2017-05-19 16:52:31 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/ddebug/dd_context.c | 61 +++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)

diff --git a/src/gallium/drivers/ddebug/dd_context.c b/src/gallium/drivers/ddebug/dd_context.c
index 8260d4f869..8a07411c46 100644
--- a/src/gallium/drivers/ddebug/dd_context.c
+++ b/src/gallium/drivers/ddebug/dd_context.c
@@ -764,6 +764,61 @@ dd_context_dump_debug_state(struct pipe_context *_pipe, FILE *stream,
return pipe->dump_debug_state(pipe, stream, flags);
}

+static uint64_t
+dd_context_create_texture_handle(struct pipe_context *_pipe,
+ struct pipe_resource *res,
+ struct pipe_sampler_view *view,
+ const struct pipe_sampler_state *state)
+{
+ struct pipe_context *pipe = dd_context(_pipe)->pipe;
+
+ return pipe->create_texture_handle(pipe, res, view, state);
+}
+
+static void
+dd_context_delete_texture_handle(struct pipe_context *_pipe, uint64_t handle)
+{
+ struct pipe_context *pipe = dd_context(_pipe)->pipe;
+
+ pipe->delete_texture_handle(pipe, handle);
+}
+
+static void
+dd_context_make_texture_handle_resident(struct pipe_context *_pipe,
+ uint64_t handle, bool resident)
+{
+ struct pipe_context *pipe = dd_context(_pipe)->pipe;
+
+ pipe->make_texture_handle_resident(pipe, handle, resident);
+}
+
+static uint64_t
+dd_context_create_image_handle(struct pipe_context *_pipe,
+ const struct pipe_image_view *image)
+{
+ struct pipe_context *pipe = dd_context(_pipe)->pipe;
+
+ return pipe->create_image_handle(pipe, image);
+}
+
+static void
+dd_context_delete_image_handle(struct pipe_context *_pipe, uint64_t handle)
+{
+ struct pipe_context *pipe = dd_context(_pipe)->pipe;
+
+ pipe->delete_image_handle(pipe, handle);
+}
+
+static void
+dd_context_make_image_handle_resident(struct pipe_context *_pipe,
+ uint64_t handle, unsigned access,
+ bool resident)
+{
+ struct pipe_context *pipe = dd_context(_pipe)->pipe;
+
+ pipe->make_image_handle_resident(pipe, handle, access, resident);
+}
+
struct pipe_context *
dd_context_create(struct dd_screen *dscreen, struct pipe_context *pipe)
{
@@ -866,6 +921,12 @@ dd_context_create(struct dd_screen *dscreen, struct pipe_context *pipe)
CTX_INIT(set_device_reset_callback);
CTX_INIT(dump_debug_state);
CTX_INIT(emit_string_marker);
+ CTX_INIT(create_texture_handle);
+ CTX_INIT(delete_texture_handle);
+ CTX_INIT(make_texture_handle_resident);
+ CTX_INIT(create_image_handle);
+ CTX_INIT(delete_image_handle);
+ CTX_INIT(make_image_handle_resident);

dd_init_draw_functions(dctx);
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:25 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/program/ir_to_mesa.cpp | 7 ++++---
src/mesa/program/ir_to_mesa.h | 4 ++--
src/mesa/state_tracker/st_glsl_to_nir.cpp | 3 +--
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 3 +--
src/mesa/state_tracker/st_shader_cache.c | 3 +--
5 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 8ed249f8ca..5e6304036d 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -2537,9 +2537,11 @@ _mesa_generate_parameters_list_for_uniforms(struct gl_shader_program
void
_mesa_associate_uniform_storage(struct gl_context *ctx,
struct gl_shader_program *shader_program,
- struct gl_program_parameter_list *params,
+ struct gl_program *prog,
bool propagate_to_storage)
{
+ struct gl_program_parameter_list *params = prog->Parameters;
+
/* After adding each uniform to the parameter list, connect the storage for
* the parameter with the tracking structure used by the API for the
* uniform.
@@ -2987,8 +2989,7 @@ get_mesa_program(struct gl_context *ctx,
* prog->ParameterValues to get reallocated (e.g., anything that adds a
* program constant) has to happen before creating this linkage.
*/
- _mesa_associate_uniform_storage(ctx, shader_program, prog->Parameters,
- true);
+ _mesa_associate_uniform_storage(ctx, shader_program, prog, true);
if (!shader_program->data->LinkStatus) {
goto fail_exit;
}
diff --git a/src/mesa/program/ir_to_mesa.h b/src/mesa/program/ir_to_mesa.h
index 09446197b2..e3d364455c 100644
--- a/src/mesa/program/ir_to_mesa.h
+++ b/src/mesa/program/ir_to_mesa.h
@@ -45,8 +45,8 @@ _mesa_generate_parameters_list_for_uniforms(struct gl_shader_program
*params);
void
_mesa_associate_uniform_storage(struct gl_context *ctx,
- struct gl_shader_program *shader_program,
- struct gl_program_parameter_list *params,
+ struct gl_shader_program *shader_program,
+ struct gl_program *prog,
bool propagate_to_storage);

#ifdef __cplusplus
diff --git a/src/mesa/state_tracker/st_glsl_to_nir.cpp b/src/mesa/state_tracker/st_glsl_to_nir.cpp
index fd5eeea0f9..524eefa236 100644
--- a/src/mesa/state_tracker/st_glsl_to_nir.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_nir.cpp
@@ -436,8 +436,7 @@ st_nir_get_mesa_program(struct gl_context *ctx,
* prog->ParameterValues to get reallocated (e.g., anything that adds a
* program constant) has to happen before creating this linkage.
*/
- _mesa_associate_uniform_storage(ctx, shader_program, prog->Parameters,
- true);
+ _mesa_associate_uniform_storage(ctx, shader_program, prog, true);

struct st_vertex_program *stvp;
struct st_fragment_program *stfp;
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 76cd4dc3a5..7571e7d495 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -6805,8 +6805,7 @@ get_mesa_program_tgsi(struct gl_context *ctx,
* prog->ParameterValues to get reallocated (e.g., anything that adds a
* program constant) has to happen before creating this linkage.
*/
- _mesa_associate_uniform_storage(ctx, shader_program, prog->Parameters,
- true);
+ _mesa_associate_uniform_storage(ctx, shader_program, prog, true);
if (!shader_program->data->LinkStatus) {
free_glsl_to_tgsi_visitor(v);
_mesa_reference_program(ctx, &shader->Program, NULL);
diff --git a/src/mesa/state_tracker/st_shader_cache.c b/src/mesa/state_tracker/st_shader_cache.c
index 23416c0c3f..068b4e20bb 100644
--- a/src/mesa/state_tracker/st_shader_cache.c
+++ b/src/mesa/state_tracker/st_shader_cache.c
@@ -360,8 +360,7 @@ st_load_tgsi_from_disk_cache(struct gl_context *ctx,
}

st_set_prog_affected_state_flags(glprog);
- _mesa_associate_uniform_storage(ctx, prog, glprog->Parameters,
- false);
+ _mesa_associate_uniform_storage(ctx, prog, glprog, false);

free(buffer);
} else {
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:15 UTC
Permalink
Old-style samplers (ie. bound samplers) are stored as
PROGRAM_SAMPLER, while bindless ones are PROGRAM_UNIFORM.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/program/ir_to_mesa.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index a1a788e9e8..8ed249f8ca 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -2462,7 +2462,7 @@ add_uniform_to_shader::visit_field(const glsl_type *type, const char *name,
}

gl_register_file file;
- if (type->without_array()->is_sampler()) {
+ if (type->without_array()->is_sampler() && !var->data.bindless) {
file = PROGRAM_SAMPLER;
} else {
file = PROGRAM_UNIFORM;
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:33 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/auxiliary/util/u_threaded_context.c | 147 +++++++++++++++++++++
.../auxiliary/util/u_threaded_context_calls.h | 4 +
2 files changed, 151 insertions(+)

diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c
index 8ea7f8aa26..36c2e4ed46 100644
--- a/src/gallium/auxiliary/util/u_threaded_context.c
+++ b/src/gallium/auxiliary/util/u_threaded_context.c
@@ -1086,6 +1086,147 @@ tc_stream_output_target_destroy(struct pipe_context *_pipe,


/********************************************************************
+ * bindless
+ */
+
+static uint64_t
+tc_create_texture_handle(struct pipe_context *_pipe,
+ struct pipe_resource *res,
+ struct pipe_sampler_view *view,
+ const struct pipe_sampler_state *state)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct pipe_context *pipe = tc->pipe;
+
+ tc_sync(tc);
+ return pipe->create_texture_handle(pipe, res, view, state);
+}
+
+struct tc_delete_texture_handle
+{
+ uint64_t handle;
+};
+
+static void
+tc_call_delete_texture_handle(struct pipe_context *pipe,
+ union tc_payload *payload)
+{
+ struct tc_delete_texture_handle *p =
+ (struct tc_delete_texture_handle *)payload;
+
+ pipe->delete_texture_handle(pipe, p->handle);
+}
+
+static void
+tc_delete_texture_handle(struct pipe_context *_pipe, uint64_t handle)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct tc_delete_texture_handle *p =
+ tc_add_struct_typed_call(tc, TC_CALL_delete_texture_handle,
+ tc_delete_texture_handle);
+
+ p->handle = handle;
+}
+
+struct tc_make_texture_handle_resident
+{
+ uint64_t handle;
+ bool resident;
+};
+
+static void
+tc_call_make_texture_handle_resident(struct pipe_context *pipe,
+ union tc_payload *payload)
+{
+ struct tc_make_texture_handle_resident *p =
+ (struct tc_make_texture_handle_resident *)payload;
+
+ pipe->make_texture_handle_resident(pipe, p->handle, p->resident);
+}
+
+static void
+tc_make_texture_handle_resident(struct pipe_context *_pipe, uint64_t handle,
+ bool resident)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct tc_make_texture_handle_resident *p =
+ tc_add_struct_typed_call(tc, TC_CALL_make_texture_handle_resident,
+ tc_make_texture_handle_resident);
+
+ p->handle = handle;
+ p->resident = resident;
+}
+
+static uint64_t
+tc_create_image_handle(struct pipe_context *_pipe,
+ const struct pipe_image_view *image)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct pipe_context *pipe = tc->pipe;
+
+ tc_sync(tc);
+ return pipe->create_image_handle(pipe, image);
+}
+
+struct tc_delete_image_handle
+{
+ uint64_t handle;
+};
+
+static void
+tc_call_delete_image_handle(struct pipe_context *pipe,
+ union tc_payload *payload)
+{
+ struct tc_delete_image_handle *p =
+ (struct tc_delete_image_handle *)payload;
+
+ pipe->delete_image_handle(pipe, p->handle);
+}
+
+static void
+tc_delete_image_handle(struct pipe_context *_pipe, uint64_t handle)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct tc_delete_image_handle *p =
+ tc_add_struct_typed_call(tc, TC_CALL_delete_image_handle,
+ tc_delete_image_handle);
+
+ p->handle = handle;
+}
+
+struct tc_make_image_handle_resident
+{
+ uint64_t handle;
+ unsigned access;
+ bool resident;
+};
+
+static void
+tc_call_make_image_handle_resident(struct pipe_context *pipe,
+ union tc_payload *payload)
+{
+ struct tc_make_image_handle_resident *p =
+ (struct tc_make_image_handle_resident *)payload;
+
+ pipe->make_image_handle_resident(pipe, p->handle, p->access, p->resident);
+}
+
+static void
+tc_make_image_handle_resident(struct pipe_context *_pipe, uint64_t handle,
+ unsigned access, bool resident)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct tc_make_image_handle_resident *p =
+ tc_add_struct_typed_call(tc, TC_CALL_make_image_handle_resident,
+ tc_make_image_handle_resident);
+
+ p->handle = handle;
+ p->access = access;
+ p->resident = resident;
+}
+
+
+/********************************************************************
* transfer
*/

@@ -2311,6 +2452,12 @@ threaded_context_create(struct pipe_context *pipe,
CTX_INIT(create_fence_fd);
CTX_INIT(fence_server_sync);
CTX_INIT(get_timestamp);
+ CTX_INIT(create_texture_handle);
+ CTX_INIT(delete_texture_handle);
+ CTX_INIT(make_texture_handle_resident);
+ CTX_INIT(create_image_handle);
+ CTX_INIT(delete_image_handle);
+ CTX_INIT(make_image_handle_resident);
#undef CTX_INIT

if (out)
diff --git a/src/gallium/auxiliary/util/u_threaded_context_calls.h b/src/gallium/auxiliary/util/u_threaded_context_calls.h
index 7dfccb0f0d..546819a258 100644
--- a/src/gallium/auxiliary/util/u_threaded_context_calls.h
+++ b/src/gallium/auxiliary/util/u_threaded_context_calls.h
@@ -41,6 +41,10 @@ CALL(set_min_samples)
CALL(set_polygon_stipple)
CALL(texture_barrier)
CALL(memory_barrier)
+CALL(delete_texture_handle)
+CALL(make_texture_handle_resident)
+CALL(delete_image_handle)
+CALL(make_image_handle_resident)

CALL(bind_blend_state)
CALL(bind_rasterizer_state)
--
2.13.0
Marek Olšák
2017-05-22 17:01:27 UTC
Permalink
On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
---
src/gallium/auxiliary/util/u_threaded_context.c | 147 +++++++++++++++++++++
.../auxiliary/util/u_threaded_context_calls.h | 4 +
2 files changed, 151 insertions(+)
diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c
index 8ea7f8aa26..36c2e4ed46 100644
--- a/src/gallium/auxiliary/util/u_threaded_context.c
+++ b/src/gallium/auxiliary/util/u_threaded_context.c
@@ -1086,6 +1086,147 @@ tc_stream_output_target_destroy(struct pipe_context *_pipe,
/********************************************************************
+ * bindless
+ */
+
+static uint64_t
+tc_create_texture_handle(struct pipe_context *_pipe,
+ struct pipe_resource *res,
+ struct pipe_sampler_view *view,
+ const struct pipe_sampler_state *state)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct pipe_context *pipe = tc->pipe;
+
+ tc_sync(tc);
+ return pipe->create_texture_handle(pipe, res, view, state);
+}
+
+struct tc_delete_texture_handle
+{
+ uint64_t handle;
+};
You can just add uint64_t handle into union tc_payload directly,
remove tc_payload::__use_8_bytes, and use tc_add_small_call instead.
Post by Samuel Pitoiset
+
+static void
+tc_call_delete_texture_handle(struct pipe_context *pipe,
+ union tc_payload *payload)
+{
+ struct tc_delete_texture_handle *p =
+ (struct tc_delete_texture_handle *)payload;
+
+ pipe->delete_texture_handle(pipe, p->handle);
+}
+
+static void
+tc_delete_texture_handle(struct pipe_context *_pipe, uint64_t handle)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct tc_delete_texture_handle *p =
+ tc_add_struct_typed_call(tc, TC_CALL_delete_texture_handle,
+ tc_delete_texture_handle);
+
+ p->handle = handle;
+}
+
+struct tc_make_texture_handle_resident
+{
+ uint64_t handle;
+ bool resident;
+};
+
+static void
+tc_call_make_texture_handle_resident(struct pipe_context *pipe,
+ union tc_payload *payload)
+{
+ struct tc_make_texture_handle_resident *p =
+ (struct tc_make_texture_handle_resident *)payload;
+
+ pipe->make_texture_handle_resident(pipe, p->handle, p->resident);
+}
+
+static void
+tc_make_texture_handle_resident(struct pipe_context *_pipe, uint64_t handle,
+ bool resident)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct tc_make_texture_handle_resident *p =
+ tc_add_struct_typed_call(tc, TC_CALL_make_texture_handle_resident,
+ tc_make_texture_handle_resident);
+
+ p->handle = handle;
+ p->resident = resident;
+}
+
+static uint64_t
+tc_create_image_handle(struct pipe_context *_pipe,
+ const struct pipe_image_view *image)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct pipe_context *pipe = tc->pipe;
+
+ tc_sync(tc);
+ return pipe->create_image_handle(pipe, image);
+}
+
+struct tc_delete_image_handle
+{
+ uint64_t handle;
+};
Same here.

Marek
Post by Samuel Pitoiset
+
+static void
+tc_call_delete_image_handle(struct pipe_context *pipe,
+ union tc_payload *payload)
+{
+ struct tc_delete_image_handle *p =
+ (struct tc_delete_image_handle *)payload;
+
+ pipe->delete_image_handle(pipe, p->handle);
+}
+
+static void
+tc_delete_image_handle(struct pipe_context *_pipe, uint64_t handle)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct tc_delete_image_handle *p =
+ tc_add_struct_typed_call(tc, TC_CALL_delete_image_handle,
+ tc_delete_image_handle);
+
+ p->handle = handle;
+}
Samuel Pitoiset
2017-05-23 12:17:15 UTC
Permalink
Post by Marek Olšák
On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
---
src/gallium/auxiliary/util/u_threaded_context.c | 147 +++++++++++++++++++++
.../auxiliary/util/u_threaded_context_calls.h | 4 +
2 files changed, 151 insertions(+)
diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c
index 8ea7f8aa26..36c2e4ed46 100644
--- a/src/gallium/auxiliary/util/u_threaded_context.c
+++ b/src/gallium/auxiliary/util/u_threaded_context.c
@@ -1086,6 +1086,147 @@ tc_stream_output_target_destroy(struct pipe_context *_pipe,
/********************************************************************
+ * bindless
+ */
+
+static uint64_t
+tc_create_texture_handle(struct pipe_context *_pipe,
+ struct pipe_resource *res,
+ struct pipe_sampler_view *view,
+ const struct pipe_sampler_state *state)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct pipe_context *pipe = tc->pipe;
+
+ tc_sync(tc);
+ return pipe->create_texture_handle(pipe, res, view, state);
+}
+
+struct tc_delete_texture_handle
+{
+ uint64_t handle;
+};
You can just add uint64_t handle into union tc_payload directly,
remove tc_payload::__use_8_bytes, and use tc_add_small_call instead.
Fixed locally, for both texture and image handles.
Post by Marek Olšák
Post by Samuel Pitoiset
+
+static void
+tc_call_delete_texture_handle(struct pipe_context *pipe,
+ union tc_payload *payload)
+{
+ struct tc_delete_texture_handle *p =
+ (struct tc_delete_texture_handle *)payload;
+
+ pipe->delete_texture_handle(pipe, p->handle);
+}
+
+static void
+tc_delete_texture_handle(struct pipe_context *_pipe, uint64_t handle)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct tc_delete_texture_handle *p =
+ tc_add_struct_typed_call(tc, TC_CALL_delete_texture_handle,
+ tc_delete_texture_handle);
+
+ p->handle = handle;
+}
+
+struct tc_make_texture_handle_resident
+{
+ uint64_t handle;
+ bool resident;
+};
+
+static void
+tc_call_make_texture_handle_resident(struct pipe_context *pipe,
+ union tc_payload *payload)
+{
+ struct tc_make_texture_handle_resident *p =
+ (struct tc_make_texture_handle_resident *)payload;
+
+ pipe->make_texture_handle_resident(pipe, p->handle, p->resident);
+}
+
+static void
+tc_make_texture_handle_resident(struct pipe_context *_pipe, uint64_t handle,
+ bool resident)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct tc_make_texture_handle_resident *p =
+ tc_add_struct_typed_call(tc, TC_CALL_make_texture_handle_resident,
+ tc_make_texture_handle_resident);
+
+ p->handle = handle;
+ p->resident = resident;
+}
+
+static uint64_t
+tc_create_image_handle(struct pipe_context *_pipe,
+ const struct pipe_image_view *image)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct pipe_context *pipe = tc->pipe;
+
+ tc_sync(tc);
+ return pipe->create_image_handle(pipe, image);
+}
+
+struct tc_delete_image_handle
+{
+ uint64_t handle;
+};
Same here.
Marek
Post by Samuel Pitoiset
+
+static void
+tc_call_delete_image_handle(struct pipe_context *pipe,
+ union tc_payload *payload)
+{
+ struct tc_delete_image_handle *p =
+ (struct tc_delete_image_handle *)payload;
+
+ pipe->delete_image_handle(pipe, p->handle);
+}
+
+static void
+tc_delete_image_handle(struct pipe_context *_pipe, uint64_t handle)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+ struct tc_delete_image_handle *p =
+ tc_add_struct_typed_call(tc, TC_CALL_delete_image_handle,
+ tc_delete_image_handle);
+
+ p->handle = handle;
+}
Samuel Pitoiset
2017-05-19 16:52:29 UTC
Permalink
Whether bindless texture operations are supported by the
underlying driver.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/docs/source/screen.rst | 2 ++
src/gallium/drivers/etnaviv/etnaviv_screen.c | 1 +
src/gallium/drivers/freedreno/freedreno_screen.c | 1 +
src/gallium/drivers/i915/i915_screen.c | 1 +
src/gallium/drivers/llvmpipe/lp_screen.c | 1 +
src/gallium/drivers/nouveau/nv30/nv30_screen.c | 1 +
src/gallium/drivers/nouveau/nv50/nv50_screen.c | 1 +
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 1 +
src/gallium/drivers/r300/r300_screen.c | 1 +
src/gallium/drivers/r600/r600_pipe.c | 1 +
src/gallium/drivers/radeonsi/si_pipe.c | 1 +
src/gallium/drivers/softpipe/sp_screen.c | 1 +
src/gallium/drivers/svga/svga_screen.c | 1 +
src/gallium/drivers/swr/swr_screen.cpp | 1 +
src/gallium/drivers/vc4/vc4_screen.c | 1 +
src/gallium/drivers/virgl/virgl_screen.c | 1 +
src/gallium/include/pipe/p_defines.h | 1 +
17 files changed, 18 insertions(+)

diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst
index 871669c0d9..fa524d419c 100644
--- a/src/gallium/docs/source/screen.rst
+++ b/src/gallium/docs/source/screen.rst
@@ -392,6 +392,8 @@ The integer capabilities:
* ``PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX``: Whether a buffer with just
PIPE_BIND_CONSTANT_BUFFER can be legally passed to set_vertex_buffers.
* ``PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION``: As the name says.
+* ``PIPE_CAP_BINDLESS_TEXTURE``: Whether bindless texture operations are
+ supported.


.. _pipe_capf:
diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c
index bf13184ad6..5d10f76815 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_screen.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c
@@ -256,6 +256,7 @@ etna_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;

/* Stream output. */
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c
index a00afd3fa4..eb3ac61d6c 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.c
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c
@@ -315,6 +315,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;

case PIPE_CAP_MAX_VIEWPORTS:
diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c
index 1cf9441ef1..3ee59ab9fb 100644
--- a/src/gallium/drivers/i915/i915_screen.c
+++ b/src/gallium/drivers/i915/i915_screen.c
@@ -308,6 +308,7 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap)
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;

case PIPE_CAP_MAX_VIEWPORTS:
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
index 656de49549..de954c44c0 100644
--- a/src/gallium/drivers/llvmpipe/lp_screen.c
+++ b/src/gallium/drivers/llvmpipe/lp_screen.c
@@ -354,6 +354,7 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;
}
/* should only get here on unhandled cases */
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c
index e8d14bfea4..58c4f42f13 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c
@@ -218,6 +218,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_TGSI_BALLOT:
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;

case PIPE_CAP_VENDOR_ID:
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
index 59afd14fac..e0b959cc4c 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
@@ -270,6 +270,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_SPARSE_BUFFER_PAGE_SIZE:
case PIPE_CAP_TGSI_BALLOT:
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;

case PIPE_CAP_VENDOR_ID:
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
index e1d0d1c2c4..7898afb94a 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
@@ -293,6 +293,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_SPARSE_BUFFER_PAGE_SIZE:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;

case PIPE_CAP_VENDOR_ID:
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index 3452d92d9d..c688d7da9c 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -240,6 +240,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_TGSI_BALLOT:
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;

/* SWTCL-only features. */
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index fd01672c1d..6b6404160f 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -388,6 +388,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_SPARSE_BUFFER_PAGE_SIZE:
case PIPE_CAP_TGSI_BALLOT:
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;

case PIPE_CAP_DOUBLES:
diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c
index eaa3348bcb..8e55b807ce 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.c
+++ b/src/gallium/drivers/radeonsi/si_pipe.c
@@ -534,6 +534,7 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_TGSI_MUL_ZERO_WINS:
case PIPE_CAP_UMA:
case PIPE_CAP_POLYGON_MODE_FILL_RECTANGLE:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;

case PIPE_CAP_QUERY_BUFFER_OBJECT:
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index 8789534068..b44fd80fe9 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -304,6 +304,7 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;
case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
return 4;
diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c
index b79d9e9a76..b28e9db2ed 100644
--- a/src/gallium/drivers/svga/svga_screen.c
+++ b/src/gallium/drivers/svga/svga_screen.c
@@ -435,6 +435,7 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;
}

diff --git a/src/gallium/drivers/swr/swr_screen.cpp b/src/gallium/drivers/swr/swr_screen.cpp
index cdb8165d3d..61e1c29ca8 100644
--- a/src/gallium/drivers/swr/swr_screen.cpp
+++ b/src/gallium/drivers/swr/swr_screen.cpp
@@ -339,6 +339,7 @@ swr_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;

case PIPE_CAP_VENDOR_ID:
diff --git a/src/gallium/drivers/vc4/vc4_screen.c b/src/gallium/drivers/vc4/vc4_screen.c
index 0d3eb3ce23..1130ad1abb 100644
--- a/src/gallium/drivers/vc4/vc4_screen.c
+++ b/src/gallium/drivers/vc4/vc4_screen.c
@@ -255,6 +255,7 @@ vc4_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;

/* Stream output. */
diff --git a/src/gallium/drivers/virgl/virgl_screen.c b/src/gallium/drivers/virgl/virgl_screen.c
index f1d41ba1d4..9d1dea046d 100644
--- a/src/gallium/drivers/virgl/virgl_screen.c
+++ b/src/gallium/drivers/virgl/virgl_screen.c
@@ -263,6 +263,7 @@ virgl_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
+ case PIPE_CAP_BINDLESS_TEXTURE:
return 0;
case PIPE_CAP_VENDOR_ID:
return 0x1af4;
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index 769c94f32e..475e61c196 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -772,6 +772,7 @@ enum pipe_cap
PIPE_CAP_TGSI_TES_LAYER_VIEWPORT,
PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX,
PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION,
+ PIPE_CAP_BINDLESS_TEXTURE,
};

#define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0)
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:34 UTC
Permalink
Old-style images are identified using TGSI_FILE_SAMPLER, but
bindless samplers can be TGSI_FILE_CONSTANT or TGSI_FILE_TEMPORARY.

To avoid backend compilers to be confused, this adds a new flag
that will only be set for bindless samplers.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/auxiliary/tgsi/tgsi_build.c | 4 ++++
src/gallium/auxiliary/tgsi/tgsi_ureg.c | 9 ++++++---
src/gallium/auxiliary/tgsi/tgsi_ureg.h | 10 ++++++----
src/gallium/include/pipe/p_shader_tokens.h | 3 ++-
src/mesa/state_tracker/st_atifs_to_tgsi.c | 2 +-
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 2 +-
src/mesa/state_tracker/st_mesa_to_tgsi.c | 2 +-
7 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c
index 00843241f8..be1931e482 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_build.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_build.c
@@ -721,6 +721,7 @@ tgsi_default_instruction_texture( void )
instruction_texture.Texture = TGSI_TEXTURE_UNKNOWN;
instruction_texture.NumOffsets = 0;
instruction_texture.ReturnType = TGSI_RETURN_TYPE_UNKNOWN;
+ instruction_texture.Bindless = 0;
instruction_texture.Padding = 0;

return instruction_texture;
@@ -731,6 +732,7 @@ tgsi_build_instruction_texture(
unsigned texture,
unsigned num_offsets,
unsigned return_type,
+ unsigned bindless,
struct tgsi_token *prev_token,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
@@ -740,6 +742,7 @@ tgsi_build_instruction_texture(
instruction_texture.Texture = texture;
instruction_texture.NumOffsets = num_offsets;
instruction_texture.ReturnType = return_type;
+ instruction_texture.Bindless = bindless;
instruction_texture.Padding = 0;
instruction->Texture = 1;

@@ -1095,6 +1098,7 @@ tgsi_build_full_instruction(
full_inst->Texture.Texture,
full_inst->Texture.NumOffsets,
full_inst->Texture.ReturnType,
+ full_inst->Texture.Bindless,
prev_token,
instruction,
header );
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
index 5bd779728a..8efa95f009 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
@@ -1289,7 +1289,8 @@ ureg_fixup_label(struct ureg_program *ureg,
void
ureg_emit_texture(struct ureg_program *ureg,
unsigned extended_token,
- unsigned target, unsigned return_type, unsigned num_offsets)
+ unsigned target, unsigned return_type, unsigned num_offsets,
+ unsigned bindless)
{
union tgsi_any_token *out, *insn;

@@ -1302,6 +1303,7 @@ ureg_emit_texture(struct ureg_program *ureg,
out[0].insn_texture.Texture = target;
out[0].insn_texture.NumOffsets = num_offsets;
out[0].insn_texture.ReturnType = return_type;
+ out[0].insn_texture.Bindless = bindless;
}

void
@@ -1391,7 +1393,8 @@ ureg_tex_insn(struct ureg_program *ureg,
const struct tgsi_texture_offset *texoffsets,
unsigned nr_offset,
const struct ureg_src *src,
- unsigned nr_src )
+ unsigned nr_src,
+ unsigned bindless)
{
struct ureg_emit_insn_result insn;
unsigned i;
@@ -1410,7 +1413,7 @@ ureg_tex_insn(struct ureg_program *ureg,
nr_src);

ureg_emit_texture( ureg, insn.extended_token, target, return_type,
- nr_offset );
+ nr_offset, bindless );

for (i = 0; i < nr_offset; i++)
ureg_emit_texture_offset( ureg, &texoffsets[i]);
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
index 54f95ba565..9e30a41ff7 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
@@ -559,7 +559,8 @@ ureg_tex_insn(struct ureg_program *ureg,
const struct tgsi_texture_offset *texoffsets,
unsigned nr_offset,
const struct ureg_src *src,
- unsigned nr_src );
+ unsigned nr_src,
+ unsigned bindless);


void
@@ -597,7 +598,8 @@ ureg_emit_label(struct ureg_program *ureg,
void
ureg_emit_texture(struct ureg_program *ureg,
unsigned insn_token,
- unsigned target, unsigned return_type, unsigned num_offsets);
+ unsigned target, unsigned return_type, unsigned num_offsets,
+ unsigned bindless);

void
ureg_emit_texture_offset(struct ureg_program *ureg,
@@ -759,7 +761,7 @@ static inline void ureg_##op( struct ureg_program *ureg, \
1, \
2); \
ureg_emit_texture( ureg, insn.extended_token, target, \
- return_type, 0 ); \
+ return_type, 0, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
@@ -809,7 +811,7 @@ static inline void ureg_##op( struct ureg_program *ureg, \
1, \
4); \
ureg_emit_texture( ureg, insn.extended_token, target, \
- return_type, 0 ); \
+ return_type, 0, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
index cb49e3b033..2665eb4235 100644
--- a/src/gallium/include/pipe/p_shader_tokens.h
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -696,7 +696,8 @@ struct tgsi_instruction_texture
unsigned Texture : 8; /* TGSI_TEXTURE_ */
unsigned NumOffsets : 4;
unsigned ReturnType : 3; /* TGSI_RETURN_TYPE_x */
- unsigned Padding : 17;
+ unsigned Bindless : 1;
+ unsigned Padding : 16;
};

/* for texture offsets in GLSL and DirectX.
diff --git a/src/mesa/state_tracker/st_atifs_to_tgsi.c b/src/mesa/state_tracker/st_atifs_to_tgsi.c
index 338ced56ed..92e91f5ce5 100644
--- a/src/mesa/state_tracker/st_atifs_to_tgsi.c
+++ b/src/mesa/state_tracker/st_atifs_to_tgsi.c
@@ -334,7 +334,7 @@ compile_setupinst(struct st_translate *t,
src[1] = t->samplers[r];
/* the texture target is still unknown, it will be fixed in the draw call */
ureg_tex_insn(t->ureg, TGSI_OPCODE_TEX, dst, 1, TGSI_TEXTURE_2D,
- TGSI_RETURN_TYPE_FLOAT, NULL, 0, src, 2);
+ TGSI_RETURN_TYPE_FLOAT, NULL, 0, src, 2, 0);
} else if (texinst->Opcode == ATI_FRAGMENT_SHADER_PASS_OP) {
ureg_insn(t->ureg, TGSI_OPCODE_MOV, dst, 1, src, 1);
}
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 7571e7d495..4e6678c8ac 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -5873,7 +5873,7 @@ compile_tgsi_instruction(struct st_translate *t,
tex_target,
st_translate_texture_type(inst->tex_type),
texoffsets, inst->tex_offset_num_offset,
- src, num_src);
+ src, num_src, 0);
return;

case TGSI_OPCODE_RESQ:
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c
index aad3c5b04c..b5184c7a3b 100644
--- a/src/mesa/state_tracker/st_mesa_to_tgsi.c
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c
@@ -558,7 +558,7 @@ compile_instruction(
inst->TexShadow ),
TGSI_RETURN_TYPE_FLOAT,
NULL, 0,
- src, num_src );
+ src, num_src, 0 );
return;

case OPCODE_SCS:
--
2.13.0
Marek Olšák
2017-05-22 17:06:06 UTC
Permalink
On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
Old-style images are identified using TGSI_FILE_SAMPLER, but
bindless samplers can be TGSI_FILE_CONSTANT or TGSI_FILE_TEMPORARY.
To avoid backend compilers to be confused, this adds a new flag
that will only be set for bindless samplers.
Sorry, I don't understand it. Why is it necessary? It seems to me that
this is enough to tell whether the sampler is bindless: File !=
TGSI_FILE_SAMPLER && File != TGSI_FILE_IMAGE.

Marek
Samuel Pitoiset
2017-05-23 12:29:54 UTC
Permalink
Post by Marek Olšák
On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
Old-style images are identified using TGSI_FILE_SAMPLER, but
bindless samplers can be TGSI_FILE_CONSTANT or TGSI_FILE_TEMPORARY.
To avoid backend compilers to be confused, this adds a new flag
that will only be set for bindless samplers.
Sorry, I don't understand it. Why is it necessary? It seems to me that
this is enough to tell whether the sampler is bindless: File !=
TGSI_FILE_SAMPLER && File != TGSI_FILE_IMAGE.
Initially, it seemed to work without the new Bindless flags but piglit
reported me some issues at some point. I don't remember exactly the
fails but I will try again without these flags. I do agree that should
work as-is.
Post by Marek Olšák
Marek
Marek Olšák
2017-05-23 17:31:06 UTC
Permalink
BTW patch 25 needs gallium docs, which you already know. Other than
that, patches 24-28 and 31 are:

Reviewed-by: Marek Olšák <***@amd.com>

Marek

On Tue, May 23, 2017 at 2:29 PM, Samuel Pitoiset
Post by Samuel Pitoiset
Post by Marek Olšák
On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
Old-style images are identified using TGSI_FILE_SAMPLER, but
bindless samplers can be TGSI_FILE_CONSTANT or TGSI_FILE_TEMPORARY.
To avoid backend compilers to be confused, this adds a new flag
that will only be set for bindless samplers.
Sorry, I don't understand it. Why is it necessary? It seems to me that
this is enough to tell whether the sampler is bindless: File !=
TGSI_FILE_SAMPLER && File != TGSI_FILE_IMAGE.
Initially, it seemed to work without the new Bindless flags but piglit
reported me some issues at some point. I don't remember exactly the fails
but I will try again without these flags. I do agree that should work as-is.
Post by Marek Olšák
Marek
Samuel Pitoiset
2017-05-19 16:52:54 UTC
Permalink
This will be used in order to initialize resident descriptors
for bindless textures/images.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_descriptors.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index d337fc3f11..b2fe6a3de7 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -95,6 +95,21 @@ static uint32_t null_image_descriptor[8] = {
* descriptor */
};

+static void si_init_descriptor_list(uint32_t *desc_list,
+ unsigned element_dw_size,
+ unsigned num_elements,
+ const uint32_t *null_descriptor)
+{
+ int i;
+
+ /* Initialize the array to NULL descriptors if the element size is 8. */
+ if (null_descriptor) {
+ assert(element_dw_size % 8 == 0);
+ for (i = 0; i < num_elements * element_dw_size / 8; i++)
+ memcpy(desc_list + i * 8, null_descriptor, 8 * 4);
+ }
+}
+
static void si_init_descriptors(struct si_context *sctx,
struct si_descriptors *desc,
unsigned shader_userdata_index,
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:57 UTC
Permalink
This implements the Gallium interface. Decompression of resident
textures/images will follow in the next patches.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_descriptors.c | 340 ++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_pipe.c | 12 +
src/gallium/drivers/radeonsi/si_pipe.h | 26 ++
3 files changed, 378 insertions(+)

diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index abe39de583..a687506f7f 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -60,6 +60,7 @@
#include "sid.h"
#include "gfx9d.h"

+#include "util/hash_table.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_upload_mgr.h"
@@ -2193,6 +2194,339 @@ void si_resident_descriptor_slab_free(void *priv, struct pb_slab *pslab)
FREE(slab);
}

+static int si_add_resident_tex_handle(struct si_context *sctx,
+ struct si_texture_handle *tex_handle)
+{
+ int idx;
+
+ /* New resident handle, check if the backing array is large enough. */
+ if (sctx->num_resident_tex_handles >= sctx->max_resident_tex_handles) {
+ unsigned new_max_handles =
+ MAX2(1, sctx->max_resident_tex_handles * 2);
+ struct si_texture_handle **new_handles =
+ REALLOC(sctx->resident_tex_handles,
+ sctx->num_resident_tex_handles * (sizeof(*new_handles)),
+ new_max_handles * sizeof(*new_handles));
+
+ if (new_handles) {
+ sctx->resident_tex_handles = new_handles;
+ sctx->max_resident_tex_handles = new_max_handles;
+ } else {
+ fprintf(stderr, "si_add_resident_tex_handle: "
+ "allocation failed\n");
+ return -1;
+ }
+ }
+
+ idx = sctx->num_resident_tex_handles;
+ sctx->resident_tex_handles[idx] = tex_handle;
+ sctx->num_resident_tex_handles++;
+
+ return 0;
+}
+
+static void si_del_resident_tex_handle(struct si_context *sctx,
+ struct si_texture_handle *tex_handle)
+{
+ unsigned i;
+ int size;
+
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ if (sctx->resident_tex_handles[i] != tex_handle)
+ continue;
+
+ if (i < sctx->num_resident_tex_handles - 1) {
+ size = sizeof(*sctx->resident_tex_handles) *
+ (sctx->num_resident_tex_handles - 1 - i);
+
+ memmove(&sctx->resident_tex_handles[i],
+ &sctx->resident_tex_handles[i + 1], size);
+ }
+
+ sctx->num_resident_tex_handles--;
+ return;
+ }
+}
+
+static int si_add_resident_img_handle(struct si_context *sctx,
+ struct si_image_handle *img_handle)
+{
+ int idx;
+
+ /* New resident handle, check if the backing array is large enough. */
+ if (sctx->num_resident_img_handles >= sctx->max_resident_img_handles) {
+ unsigned new_max_handles =
+ MAX2(1, sctx->max_resident_img_handles * 2);
+ struct si_image_handle **new_handles =
+ REALLOC(sctx->resident_img_handles,
+ sctx->num_resident_img_handles * (sizeof(*new_handles)),
+ new_max_handles * sizeof(*new_handles));
+
+ if (new_handles) {
+ sctx->resident_img_handles = new_handles;
+ sctx->max_resident_img_handles = new_max_handles;
+ } else {
+ fprintf(stderr, "si_add_resident_img_handle: "
+ "allocation failed\n");
+ return -1;
+ }
+ }
+
+ idx = sctx->num_resident_img_handles;
+ sctx->resident_img_handles[idx] = img_handle;
+ sctx->num_resident_img_handles++;
+
+ return 0;
+}
+
+static void si_del_resident_img_handle(struct si_context *sctx,
+ struct si_image_handle *img_handle)
+{
+ unsigned i;
+ int size;
+
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ if (sctx->resident_img_handles[i] != img_handle)
+ continue;
+
+ if (i < sctx->num_resident_img_handles - 1) {
+ size = sizeof(*sctx->resident_img_handles) *
+ (sctx->num_resident_img_handles - 1 - i);
+
+ memmove(&sctx->resident_img_handles[i],
+ &sctx->resident_img_handles[i + 1], size);
+ }
+
+ sctx->num_resident_img_handles--;
+ return;
+ }
+}
+
+static struct si_resident_descriptor *
+si_create_resident_descriptor(struct si_context *sctx, uint32_t *desc_list,
+ unsigned size)
+{
+ struct si_screen *sscreen = sctx->screen;
+ struct si_resident_descriptor *desc;
+ struct pb_slab_entry *entry;
+ void *ptr;
+
+ /* Sub-allocate the resident descriptor from slabs. */
+ entry = pb_slab_alloc(&sctx->resident_descriptor_slabs, 64, 0);
+ if (!entry)
+ return NULL;
+
+ desc = NULL;
+ desc = container_of(entry, desc, entry);
+
+ /* Upload the descriptor. */
+ ptr = sscreen->b.ws->buffer_map(desc->buffer->buf, NULL,
+ PIPE_TRANSFER_WRITE |
+ PIPE_TRANSFER_UNSYNCHRONIZED);
+ util_memcpy_cpu_to_le32(ptr + desc->offset, desc_list, size);
+ sscreen->b.ws->buffer_unmap(desc->buffer->buf);
+
+ return desc;
+}
+
+static uint64_t si_create_texture_handle(struct pipe_context *ctx,
+ struct pipe_resource *texture,
+ struct pipe_sampler_view *view,
+ const struct pipe_sampler_state *state)
+{
+ struct si_sampler_view *sview = (struct si_sampler_view *)view;
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct si_texture_handle *tex_handle;
+ struct si_sampler_state *sstate;
+ uint32_t desc_list[16];
+ uint64_t handle;
+
+ tex_handle = CALLOC_STRUCT(si_texture_handle);
+ if (!tex_handle)
+ return 0;
+
+ memset(desc_list, 0, sizeof(desc_list));
+ si_init_descriptor_list(&desc_list[0], 16, 1, null_texture_descriptor);
+
+ sstate = ctx->create_sampler_state(ctx, state);
+ if (!sstate) {
+ FREE(tex_handle);
+ return 0;
+ }
+
+ si_set_sampler_view_desc(sctx, sview, sstate, &desc_list[0]);
+ ctx->delete_sampler_state(ctx, sstate);
+
+ tex_handle->view = sview;
+ tex_handle->desc = si_create_resident_descriptor(sctx, desc_list,
+ sizeof(desc_list));
+ if (!tex_handle->desc) {
+ FREE(tex_handle);
+ return 0;
+ }
+
+ handle = tex_handle->desc->buffer->gpu_address +
+ tex_handle->desc->offset;
+
+ if (!_mesa_hash_table_insert(sctx->tex_handles, (void *)handle,
+ tex_handle)) {
+ pb_slab_free(&sctx->resident_descriptor_slabs,
+ &tex_handle->desc->entry);
+ FREE(tex_handle);
+ return 0;
+ }
+
+ return handle;
+}
+
+static void si_delete_texture_handle(struct pipe_context *ctx, uint64_t handle)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct si_texture_handle *tex_handle;
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(sctx->tex_handles, (void *)handle);
+ if (!entry)
+ return;
+
+ tex_handle = (struct si_texture_handle *)entry->data;
+
+ _mesa_hash_table_remove(sctx->tex_handles, entry);
+ pb_slab_free(&sctx->resident_descriptor_slabs,
+ &tex_handle->desc->entry);
+ FREE(tex_handle);
+}
+
+static void si_make_texture_handle_resident(struct pipe_context *ctx,
+ uint64_t handle, bool resident)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct si_texture_handle *tex_handle;
+ struct si_sampler_view *sview;
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(sctx->tex_handles, (void *)handle);
+ if (!entry)
+ return;
+
+ tex_handle = (struct si_texture_handle *)entry->data;
+ sview = tex_handle->view;
+
+ if (resident) {
+ si_add_resident_tex_handle(sctx, tex_handle);
+
+ /* Add the buffers to the current CS in case si_begin_new_cs()
+ * is not going to be called.
+ */
+ radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx,
+ tex_handle->desc->buffer,
+ RADEON_USAGE_READ,
+ RADEON_PRIO_DESCRIPTORS);
+
+ si_sampler_view_add_buffer(sctx, sview->base.texture,
+ RADEON_USAGE_READ,
+ sview->is_stencil_sampler, false);
+ } else {
+ si_del_resident_tex_handle(sctx, tex_handle);
+ }
+}
+
+static uint64_t si_create_image_handle(struct pipe_context *ctx,
+ const struct pipe_image_view *view)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct si_image_handle *img_handle;
+ uint32_t desc_list[16];
+ uint64_t handle;
+
+ if (!view || !view->resource)
+ return 0;
+
+ img_handle = CALLOC_STRUCT(si_image_handle);
+ if (!img_handle)
+ return 0;
+
+ memset(desc_list, 0, sizeof(desc_list));
+ si_init_descriptor_list(&desc_list[0], 8, 1, null_image_descriptor);
+
+ si_set_shader_image_desc(sctx, view, false, &desc_list[0]);
+
+ util_copy_image_view(&img_handle->view, view);
+ img_handle->desc = si_create_resident_descriptor(sctx, desc_list,
+ sizeof(desc_list));
+ if (!img_handle->desc) {
+ FREE(img_handle);
+ return 0;
+ }
+
+ handle = img_handle->desc->buffer->gpu_address +
+ img_handle->desc->offset;
+
+ if (!_mesa_hash_table_insert(sctx->img_handles, (void *)handle,
+ img_handle)) {
+ pb_slab_free(&sctx->resident_descriptor_slabs,
+ &img_handle->desc->entry);
+ FREE(img_handle);
+ return 0;
+ }
+
+ return handle;
+}
+
+static void si_delete_image_handle(struct pipe_context *ctx, uint64_t handle)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct si_image_handle *img_handle;
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(sctx->img_handles, (void *)handle);
+ if (!entry)
+ return;
+
+ img_handle = (struct si_image_handle *)entry->data;
+
+ _mesa_hash_table_remove(sctx->img_handles, entry);
+ pb_slab_free(&sctx->resident_descriptor_slabs,
+ &img_handle->desc->entry);
+ FREE(img_handle);
+}
+
+static void si_make_image_handle_resident(struct pipe_context *ctx,
+ uint64_t handle, unsigned access,
+ bool resident)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct si_image_handle *img_handle;
+ struct pipe_image_view *view;
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(sctx->img_handles, (void *)handle);
+ if (!entry)
+ return;
+
+ img_handle = (struct si_image_handle *)entry->data;
+ view = &img_handle->view;
+
+ if (resident) {
+ si_add_resident_img_handle(sctx, img_handle);
+
+ /* Add the buffers to the current CS in case si_begin_new_cs()
+ * is not going to be called.
+ */
+ radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx,
+ img_handle->desc->buffer,
+ RADEON_USAGE_READ,
+ RADEON_PRIO_DESCRIPTORS);
+
+ si_sampler_view_add_buffer(sctx, view->resource,
+ RADEON_USAGE_READWRITE,
+ false, false);
+ } else {
+ si_del_resident_img_handle(sctx, img_handle);
+ }
+}
+
+
/* INIT/DEINIT/UPLOAD */

/* GFX9 has only 4KB of CE, while previous chips had 32KB. In order
@@ -2332,6 +2666,12 @@ void si_init_all_descriptors(struct si_context *sctx)
sctx->b.b.set_shader_buffers = si_set_shader_buffers;
sctx->b.b.set_sampler_views = si_set_sampler_views;
sctx->b.b.set_stream_output_targets = si_set_streamout_targets;
+ sctx->b.b.create_texture_handle = si_create_texture_handle;
+ sctx->b.b.delete_texture_handle = si_delete_texture_handle;
+ sctx->b.b.make_texture_handle_resident = si_make_texture_handle_resident;
+ sctx->b.b.create_image_handle = si_create_image_handle;
+ sctx->b.b.delete_image_handle = si_delete_image_handle;
+ sctx->b.b.make_image_handle_resident = si_make_image_handle_resident;
sctx->b.invalidate_buffer = si_invalidate_buffer;
sctx->b.rebind_buffer = si_rebind_buffer;

diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c
index 5b1ddda321..2bb2b3baa7 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.c
+++ b/src/gallium/drivers/radeonsi/si_pipe.c
@@ -27,6 +27,7 @@
#include "sid.h"

#include "radeon/radeon_uvd.h"
+#include "util/hash_table.h"
#include "util/u_memory.h"
#include "util/u_suballoc.h"
#include "util/u_tests.h"
@@ -96,8 +97,13 @@ static void si_destroy_context(struct pipe_context *context)
r600_resource_reference(&sctx->last_trace_buf, NULL);
radeon_clear_saved_cs(&sctx->last_gfx);

+ _mesa_hash_table_destroy(sctx->tex_handles, NULL);
+ _mesa_hash_table_destroy(sctx->img_handles, NULL);
+
pb_slabs_deinit(&sctx->resident_descriptor_slabs);

+ FREE(sctx->resident_tex_handles);
+ FREE(sctx->resident_img_handles);
FREE(sctx->resident_descriptors);
FREE(sctx);
}
@@ -324,6 +330,12 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen,
si_resident_descriptor_slab_free))
goto fail;

+ /* Bindless handles. */
+ sctx->tex_handles = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+ sctx->img_handles = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
+
return &sctx->b.b;
fail:
fprintf(stderr, "radeonsi: Failed to create a context.\n");
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 41b0a2a79f..3a2487bff0 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -231,6 +231,18 @@ struct si_resident_descriptor
unsigned offset;
};

+struct si_texture_handle
+{
+ struct si_resident_descriptor *desc;
+ struct si_sampler_view *view;
+};
+
+struct si_image_handle
+{
+ struct si_resident_descriptor *desc;
+ struct pipe_image_view view;
+};
+
struct si_context {
struct r600_common_context b;
struct blitter_context *blitter;
@@ -399,6 +411,20 @@ struct si_context {
struct r600_resource **resident_descriptors;
unsigned num_resident_descriptors;
unsigned max_resident_descriptors;
+
+ /* Allocatd bindless handles */
+ struct hash_table *tex_handles;
+ struct hash_table *img_handles;
+
+ /* Resident texture handles */
+ struct si_texture_handle **resident_tex_handles;
+ unsigned num_resident_tex_handles;
+ unsigned max_resident_tex_handles;
+
+ /* Resident image handles */
+ struct si_image_handle **resident_img_handles;
+ unsigned num_resident_img_handles;
+ unsigned max_resident_img_handles;
};

/* cik_sdma.c */
--
2.13.0
Marek Olšák
2017-05-25 17:58:13 UTC
Permalink
Hi,

1) Patches 48 and 52 are missing code comments. I'd like to see code
comments about how things work and why it was designed like that.

2) There is a lot of code duplication regarding managing the resizable
arrays. I'd like to see some util module used here, e.g. u_vector or
you can add new macros for the array structure.

See also below.

On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
This implements the Gallium interface. Decompression of resident
textures/images will follow in the next patches.
---
src/gallium/drivers/radeonsi/si_descriptors.c | 340 ++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_pipe.c | 12 +
src/gallium/drivers/radeonsi/si_pipe.h | 26 ++
3 files changed, 378 insertions(+)
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index abe39de583..a687506f7f 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -60,6 +60,7 @@
#include "sid.h"
#include "gfx9d.h"
+#include "util/hash_table.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_upload_mgr.h"
@@ -2193,6 +2194,339 @@ void si_resident_descriptor_slab_free(void *priv, struct pb_slab *pslab)
FREE(slab);
}
+static int si_add_resident_tex_handle(struct si_context *sctx,
+ struct si_texture_handle *tex_handle)
+{
+ int idx;
+
+ /* New resident handle, check if the backing array is large enough. */
+ if (sctx->num_resident_tex_handles >= sctx->max_resident_tex_handles) {
+ unsigned new_max_handles =
+ MAX2(1, sctx->max_resident_tex_handles * 2);
+ struct si_texture_handle **new_handles =
+ REALLOC(sctx->resident_tex_handles,
+ sctx->num_resident_tex_handles * (sizeof(*new_handles)),
+ new_max_handles * sizeof(*new_handles));
+
+ if (new_handles) {
+ sctx->resident_tex_handles = new_handles;
+ sctx->max_resident_tex_handles = new_max_handles;
+ } else {
+ fprintf(stderr, "si_add_resident_tex_handle: "
+ "allocation failed\n");
+ return -1;
+ }
+ }
+
+ idx = sctx->num_resident_tex_handles;
+ sctx->resident_tex_handles[idx] = tex_handle;
+ sctx->num_resident_tex_handles++;
+
+ return 0;
+}
+
+static void si_del_resident_tex_handle(struct si_context *sctx,
+ struct si_texture_handle *tex_handle)
+{
+ unsigned i;
+ int size;
+
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ if (sctx->resident_tex_handles[i] != tex_handle)
+ continue;
+
+ if (i < sctx->num_resident_tex_handles - 1) {
+ size = sizeof(*sctx->resident_tex_handles) *
+ (sctx->num_resident_tex_handles - 1 - i);
+
+ memmove(&sctx->resident_tex_handles[i],
+ &sctx->resident_tex_handles[i + 1], size);
+ }
+
+ sctx->num_resident_tex_handles--;
+ return;
+ }
+}
+
+static int si_add_resident_img_handle(struct si_context *sctx,
+ struct si_image_handle *img_handle)
+{
+ int idx;
+
+ /* New resident handle, check if the backing array is large enough. */
+ if (sctx->num_resident_img_handles >= sctx->max_resident_img_handles) {
+ unsigned new_max_handles =
+ MAX2(1, sctx->max_resident_img_handles * 2);
+ struct si_image_handle **new_handles =
+ REALLOC(sctx->resident_img_handles,
+ sctx->num_resident_img_handles * (sizeof(*new_handles)),
+ new_max_handles * sizeof(*new_handles));
+
+ if (new_handles) {
+ sctx->resident_img_handles = new_handles;
+ sctx->max_resident_img_handles = new_max_handles;
+ } else {
+ fprintf(stderr, "si_add_resident_img_handle: "
+ "allocation failed\n");
+ return -1;
+ }
+ }
+
+ idx = sctx->num_resident_img_handles;
+ sctx->resident_img_handles[idx] = img_handle;
+ sctx->num_resident_img_handles++;
+
+ return 0;
+}
+
+static void si_del_resident_img_handle(struct si_context *sctx,
+ struct si_image_handle *img_handle)
+{
+ unsigned i;
+ int size;
+
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ if (sctx->resident_img_handles[i] != img_handle)
+ continue;
+
+ if (i < sctx->num_resident_img_handles - 1) {
+ size = sizeof(*sctx->resident_img_handles) *
+ (sctx->num_resident_img_handles - 1 - i);
+
+ memmove(&sctx->resident_img_handles[i],
+ &sctx->resident_img_handles[i + 1], size);
+ }
+
+ sctx->num_resident_img_handles--;
+ return;
+ }
+}
+
+static struct si_resident_descriptor *
+si_create_resident_descriptor(struct si_context *sctx, uint32_t *desc_list,
+ unsigned size)
This name is misleading, because the function is called by
si_create_texture_handle when the handle is not resident. This needs
code comments at least and maybe even some renaming if needed, because
I don't understand why the name "resident_descriptor" is used by
non-resident handles.
Post by Samuel Pitoiset
+{
+ struct si_screen *sscreen = sctx->screen;
+ struct si_resident_descriptor *desc;
+ struct pb_slab_entry *entry;
+ void *ptr;
+
+ /* Sub-allocate the resident descriptor from slabs. */
+ entry = pb_slab_alloc(&sctx->resident_descriptor_slabs, 64, 0);
+ if (!entry)
+ return NULL;
+
+ desc = NULL;
+ desc = container_of(entry, desc, entry);
+
+ /* Upload the descriptor. */
+ ptr = sscreen->b.ws->buffer_map(desc->buffer->buf, NULL,
+ PIPE_TRANSFER_WRITE |
+ PIPE_TRANSFER_UNSYNCHRONIZED);
This is using UNSYNCHRONIZED, but what guarantees that the buffer
isn't being used by the GPU?

can_reclaim_slab is only using cs_is_buffer_referenced, which only
guarantees that the buffer is not referenced by an unflushed command
buffer. It doesn't guarantee that the descriptor is not being used by
the GPU.

Marek
Marek Olšák
2017-05-25 20:45:32 UTC
Permalink
On Thu, May 25, 2017 at 9:56 PM, Samuel Pitoiset
Post by Marek Olšák
Hi,
1) Patches 48 and 52 are missing code comments. I'd like to see code
comments about how things work and why it was designed like that.
Okay, I will add some.
Post by Marek Olšák
2) There is a lot of code duplication regarding managing the resizable
arrays. I'd like to see some util module used here, e.g. u_vector or
you can add new macros for the array structure.
That's right. There is a dynarray stuf also, I will have a look.
Post by Marek Olšák
See also below.
On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
This implements the Gallium interface. Decompression of resident
textures/images will follow in the next patches.
---
src/gallium/drivers/radeonsi/si_descriptors.c | 340
++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_pipe.c | 12 +
src/gallium/drivers/radeonsi/si_pipe.h | 26 ++
3 files changed, 378 insertions(+)
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c
b/src/gallium/drivers/radeonsi/si_descriptors.c
index abe39de583..a687506f7f 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -60,6 +60,7 @@
#include "sid.h"
#include "gfx9d.h"
+#include "util/hash_table.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_upload_mgr.h"
@@ -2193,6 +2194,339 @@ void si_resident_descriptor_slab_free(void *priv,
struct pb_slab *pslab)
FREE(slab);
}
+static int si_add_resident_tex_handle(struct si_context *sctx,
+ struct si_texture_handle *tex_handle)
+{
+ int idx;
+
+ /* New resident handle, check if the backing array is large enough. */
+ if (sctx->num_resident_tex_handles >=
sctx->max_resident_tex_handles) {
+ unsigned new_max_handles =
+ MAX2(1, sctx->max_resident_tex_handles * 2);
+ struct si_texture_handle **new_handles =
+ REALLOC(sctx->resident_tex_handles,
+ sctx->num_resident_tex_handles *
(sizeof(*new_handles)),
+ new_max_handles * sizeof(*new_handles));
+
+ if (new_handles) {
+ sctx->resident_tex_handles = new_handles;
+ sctx->max_resident_tex_handles = new_max_handles;
+ } else {
+ fprintf(stderr, "si_add_resident_tex_handle: "
+ "allocation failed\n");
+ return -1;
+ }
+ }
+
+ idx = sctx->num_resident_tex_handles;
+ sctx->resident_tex_handles[idx] = tex_handle;
+ sctx->num_resident_tex_handles++;
+
+ return 0;
+}
+
+static void si_del_resident_tex_handle(struct si_context *sctx,
+ struct si_texture_handle *tex_handle)
+{
+ unsigned i;
+ int size;
+
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ if (sctx->resident_tex_handles[i] != tex_handle)
+ continue;
+
+ if (i < sctx->num_resident_tex_handles - 1) {
+ size = sizeof(*sctx->resident_tex_handles) *
+ (sctx->num_resident_tex_handles - 1 - i);
+
+ memmove(&sctx->resident_tex_handles[i],
+ &sctx->resident_tex_handles[i + 1], size);
+ }
+
+ sctx->num_resident_tex_handles--;
+ return;
+ }
+}
+
+static int si_add_resident_img_handle(struct si_context *sctx,
+ struct si_image_handle *img_handle)
+{
+ int idx;
+
+ /* New resident handle, check if the backing array is large enough. */
+ if (sctx->num_resident_img_handles >=
sctx->max_resident_img_handles) {
+ unsigned new_max_handles =
+ MAX2(1, sctx->max_resident_img_handles * 2);
+ struct si_image_handle **new_handles =
+ REALLOC(sctx->resident_img_handles,
+ sctx->num_resident_img_handles *
(sizeof(*new_handles)),
+ new_max_handles * sizeof(*new_handles));
+
+ if (new_handles) {
+ sctx->resident_img_handles = new_handles;
+ sctx->max_resident_img_handles = new_max_handles;
+ } else {
+ fprintf(stderr, "si_add_resident_img_handle: "
+ "allocation failed\n");
+ return -1;
+ }
+ }
+
+ idx = sctx->num_resident_img_handles;
+ sctx->resident_img_handles[idx] = img_handle;
+ sctx->num_resident_img_handles++;
+
+ return 0;
+}
+
+static void si_del_resident_img_handle(struct si_context *sctx,
+ struct si_image_handle *img_handle)
+{
+ unsigned i;
+ int size;
+
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ if (sctx->resident_img_handles[i] != img_handle)
+ continue;
+
+ if (i < sctx->num_resident_img_handles - 1) {
+ size = sizeof(*sctx->resident_img_handles) *
+ (sctx->num_resident_img_handles - 1 - i);
+
+ memmove(&sctx->resident_img_handles[i],
+ &sctx->resident_img_handles[i + 1], size);
+ }
+
+ sctx->num_resident_img_handles--;
+ return;
+ }
+}
+
+static struct si_resident_descriptor *
+si_create_resident_descriptor(struct si_context *sctx, uint32_t *desc_list,
+ unsigned size)
This name is misleading, because the function is called by
si_create_texture_handle when the handle is not resident. This needs
code comments at least and maybe even some renaming if needed, because
I don't understand why the name "resident_descriptor" is used by
non-resident handles.
Mmmh, it creates a descriptor which is going to be resident at some point.
Not sure about the function name, maybe si_create_descriptor()?
si_create_bindless_descriptor?
"bindless" in the name is better.
Post by Marek Olšák
Post by Samuel Pitoiset
+{
+ struct si_screen *sscreen = sctx->screen;
+ struct si_resident_descriptor *desc;
+ struct pb_slab_entry *entry;
+ void *ptr;
+
+ /* Sub-allocate the resident descriptor from slabs. */
+ entry = pb_slab_alloc(&sctx->resident_descriptor_slabs, 64, 0);
+ if (!entry)
+ return NULL;
+
+ desc = NULL;
+ desc = container_of(entry, desc, entry);
+
+ /* Upload the descriptor. */
+ ptr = sscreen->b.ws->buffer_map(desc->buffer->buf, NULL,
+ PIPE_TRANSFER_WRITE |
+ PIPE_TRANSFER_UNSYNCHRONIZED);
This is using UNSYNCHRONIZED, but what guarantees that the buffer
isn't being used by the GPU?
can_reclaim_slab is only using cs_is_buffer_referenced, which only
guarantees that the buffer is not referenced by an unflushed command
buffer. It doesn't guarantee that the descriptor is not being used by
the GPU.
Oh right. Actually, the resident descriptors are never reclaimed... because
they are added to every new CS, so can_reclaim_slab never returns TRUE. Yes,
it's dumb. :)
Though, I would like to find a way to release unused slabs when it's
possible.
The code should contain comments mentioning that.

Marek
Marek Olšák
2017-05-25 21:09:21 UTC
Permalink
On Thu, May 25, 2017 at 10:49 PM, Samuel Pitoiset
Post by Marek Olšák
On Thu, May 25, 2017 at 9:56 PM, Samuel Pitoiset
Post by Marek Olšák
Hi,
1) Patches 48 and 52 are missing code comments. I'd like to see code
comments about how things work and why it was designed like that.
Okay, I will add some.
Post by Marek Olšák
2) There is a lot of code duplication regarding managing the resizable
arrays. I'd like to see some util module used here, e.g. u_vector or
you can add new macros for the array structure.
That's right. There is a dynarray stuf also, I will have a look.
Post by Marek Olšák
See also below.
On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
This implements the Gallium interface. Decompression of resident
textures/images will follow in the next patches.
---
src/gallium/drivers/radeonsi/si_descriptors.c | 340
++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_pipe.c | 12 +
src/gallium/drivers/radeonsi/si_pipe.h | 26 ++
3 files changed, 378 insertions(+)
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c
b/src/gallium/drivers/radeonsi/si_descriptors.c
index abe39de583..a687506f7f 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -60,6 +60,7 @@
#include "sid.h"
#include "gfx9d.h"
+#include "util/hash_table.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_upload_mgr.h"
@@ -2193,6 +2194,339 @@ void si_resident_descriptor_slab_free(void *priv,
struct pb_slab *pslab)
FREE(slab);
}
+static int si_add_resident_tex_handle(struct si_context *sctx,
+ struct si_texture_handle *tex_handle)
+{
+ int idx;
+
+ /* New resident handle, check if the backing array is large enough. */
+ if (sctx->num_resident_tex_handles >=
sctx->max_resident_tex_handles) {
+ unsigned new_max_handles =
+ MAX2(1, sctx->max_resident_tex_handles * 2);
+ struct si_texture_handle **new_handles =
+ REALLOC(sctx->resident_tex_handles,
+ sctx->num_resident_tex_handles *
(sizeof(*new_handles)),
+ new_max_handles *
sizeof(*new_handles));
+
+ if (new_handles) {
+ sctx->resident_tex_handles = new_handles;
+ sctx->max_resident_tex_handles =
new_max_handles;
+ } else {
+ fprintf(stderr, "si_add_resident_tex_handle: "
+ "allocation failed\n");
+ return -1;
+ }
+ }
+
+ idx = sctx->num_resident_tex_handles;
+ sctx->resident_tex_handles[idx] = tex_handle;
+ sctx->num_resident_tex_handles++;
+
+ return 0;
+}
+
+static void si_del_resident_tex_handle(struct si_context *sctx,
+ struct si_texture_handle *tex_handle)
+{
+ unsigned i;
+ int size;
+
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ if (sctx->resident_tex_handles[i] != tex_handle)
+ continue;
+
+ if (i < sctx->num_resident_tex_handles - 1) {
+ size = sizeof(*sctx->resident_tex_handles) *
+ (sctx->num_resident_tex_handles - 1 - i);
+
+ memmove(&sctx->resident_tex_handles[i],
+ &sctx->resident_tex_handles[i + 1], size);
+ }
+
+ sctx->num_resident_tex_handles--;
+ return;
+ }
+}
+
+static int si_add_resident_img_handle(struct si_context *sctx,
+ struct si_image_handle *img_handle)
+{
+ int idx;
+
+ /* New resident handle, check if the backing array is large enough. */
+ if (sctx->num_resident_img_handles >=
sctx->max_resident_img_handles) {
+ unsigned new_max_handles =
+ MAX2(1, sctx->max_resident_img_handles * 2);
+ struct si_image_handle **new_handles =
+ REALLOC(sctx->resident_img_handles,
+ sctx->num_resident_img_handles *
(sizeof(*new_handles)),
+ new_max_handles *
sizeof(*new_handles));
+
+ if (new_handles) {
+ sctx->resident_img_handles = new_handles;
+ sctx->max_resident_img_handles =
new_max_handles;
+ } else {
+ fprintf(stderr, "si_add_resident_img_handle: "
+ "allocation failed\n");
+ return -1;
+ }
+ }
+
+ idx = sctx->num_resident_img_handles;
+ sctx->resident_img_handles[idx] = img_handle;
+ sctx->num_resident_img_handles++;
+
+ return 0;
+}
+
+static void si_del_resident_img_handle(struct si_context *sctx,
+ struct si_image_handle *img_handle)
+{
+ unsigned i;
+ int size;
+
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ if (sctx->resident_img_handles[i] != img_handle)
+ continue;
+
+ if (i < sctx->num_resident_img_handles - 1) {
+ size = sizeof(*sctx->resident_img_handles) *
+ (sctx->num_resident_img_handles - 1 - i);
+
+ memmove(&sctx->resident_img_handles[i],
+ &sctx->resident_img_handles[i + 1], size);
+ }
+
+ sctx->num_resident_img_handles--;
+ return;
+ }
+}
+
+static struct si_resident_descriptor *
+si_create_resident_descriptor(struct si_context *sctx, uint32_t *desc_list,
+ unsigned size)
This name is misleading, because the function is called by
si_create_texture_handle when the handle is not resident. This needs
code comments at least and maybe even some renaming if needed, because
I don't understand why the name "resident_descriptor" is used by
non-resident handles.
Mmmh, it creates a descriptor which is going to be resident at some point.
Not sure about the function name, maybe si_create_descriptor()?
si_create_bindless_descriptor?
"bindless" in the name is better.
Post by Marek Olšák
Post by Samuel Pitoiset
+{
+ struct si_screen *sscreen = sctx->screen;
+ struct si_resident_descriptor *desc;
+ struct pb_slab_entry *entry;
+ void *ptr;
+
+ /* Sub-allocate the resident descriptor from slabs. */
+ entry = pb_slab_alloc(&sctx->resident_descriptor_slabs, 64, 0);
+ if (!entry)
+ return NULL;
+
+ desc = NULL;
+ desc = container_of(entry, desc, entry);
+
+ /* Upload the descriptor. */
+ ptr = sscreen->b.ws->buffer_map(desc->buffer->buf, NULL,
+ PIPE_TRANSFER_WRITE |
+ PIPE_TRANSFER_UNSYNCHRONIZED);
This is using UNSYNCHRONIZED, but what guarantees that the buffer
isn't being used by the GPU?
can_reclaim_slab is only using cs_is_buffer_referenced, which only
guarantees that the buffer is not referenced by an unflushed command
buffer. It doesn't guarantee that the descriptor is not being used by
the GPU.
Oh right. Actually, the resident descriptors are never reclaimed... because
they are added to every new CS, so can_reclaim_slab never returns TRUE. Yes,
it's dumb. :)
Though, I would like to find a way to release unused slabs when it's
possible.
The code should contain comments mentioning that.
Sure. One solution, though definitely not ideal is to always return false in
can_reclaim_slab(). Maybe we can do that and improve later? Your call.
Yeah that would also make things clearer.

Marek
Samuel Pitoiset
2017-05-24 16:00:03 UTC
Permalink
Post by Marek Olšák
On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
This implements the Gallium interface. Decompression of resident
textures/images will follow in the next patches.
---
src/gallium/drivers/radeonsi/si_descriptors.c | 340 ++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_pipe.c | 12 +
src/gallium/drivers/radeonsi/si_pipe.h | 26 ++
3 files changed, 378 insertions(+)
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index abe39de583..a687506f7f 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -60,6 +60,7 @@
#include "sid.h"
#include "gfx9d.h"
+#include "util/hash_table.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_upload_mgr.h"
@@ -2193,6 +2194,339 @@ void si_resident_descriptor_slab_free(void *priv, struct pb_slab *pslab)
FREE(slab);
}
+static int si_add_resident_tex_handle(struct si_context *sctx,
+ struct si_texture_handle *tex_handle)
+{
+ int idx;
+
+ /* New resident handle, check if the backing array is large enough. */
+ if (sctx->num_resident_tex_handles >= sctx->max_resident_tex_handles) {
+ unsigned new_max_handles =
+ MAX2(1, sctx->max_resident_tex_handles * 2);
+ struct si_texture_handle **new_handles =
+ REALLOC(sctx->resident_tex_handles,
+ sctx->num_resident_tex_handles * (sizeof(*new_handles)),
+ new_max_handles * sizeof(*new_handles));
+
+ if (new_handles) {
+ sctx->resident_tex_handles = new_handles;
+ sctx->max_resident_tex_handles = new_max_handles;
+ } else {
+ fprintf(stderr, "si_add_resident_tex_handle: "
+ "allocation failed\n");
+ return -1;
+ }
+ }
+
+ idx = sctx->num_resident_tex_handles;
+ sctx->resident_tex_handles[idx] = tex_handle;
+ sctx->num_resident_tex_handles++;
+
+ return 0;
+}
+
+static void si_del_resident_tex_handle(struct si_context *sctx,
+ struct si_texture_handle *tex_handle)
+{
+ unsigned i;
+ int size;
+
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ if (sctx->resident_tex_handles[i] != tex_handle)
+ continue;
+
+ if (i < sctx->num_resident_tex_handles - 1) {
+ size = sizeof(*sctx->resident_tex_handles) *
+ (sctx->num_resident_tex_handles - 1 - i);
+
+ memmove(&sctx->resident_tex_handles[i],
+ &sctx->resident_tex_handles[i + 1], size);
+ }
+
+ sctx->num_resident_tex_handles--;
+ return;
+ }
+}
+
+static int si_add_resident_img_handle(struct si_context *sctx,
+ struct si_image_handle *img_handle)
+{
+ int idx;
+
+ /* New resident handle, check if the backing array is large enough. */
+ if (sctx->num_resident_img_handles >= sctx->max_resident_img_handles) {
+ unsigned new_max_handles =
+ MAX2(1, sctx->max_resident_img_handles * 2);
+ struct si_image_handle **new_handles =
+ REALLOC(sctx->resident_img_handles,
+ sctx->num_resident_img_handles * (sizeof(*new_handles)),
+ new_max_handles * sizeof(*new_handles));
+
+ if (new_handles) {
+ sctx->resident_img_handles = new_handles;
+ sctx->max_resident_img_handles = new_max_handles;
+ } else {
+ fprintf(stderr, "si_add_resident_img_handle: "
+ "allocation failed\n");
+ return -1;
+ }
+ }
+
+ idx = sctx->num_resident_img_handles;
+ sctx->resident_img_handles[idx] = img_handle;
+ sctx->num_resident_img_handles++;
+
+ return 0;
+}
+
+static void si_del_resident_img_handle(struct si_context *sctx,
+ struct si_image_handle *img_handle)
+{
+ unsigned i;
+ int size;
+
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ if (sctx->resident_img_handles[i] != img_handle)
+ continue;
+
+ if (i < sctx->num_resident_img_handles - 1) {
+ size = sizeof(*sctx->resident_img_handles) *
+ (sctx->num_resident_img_handles - 1 - i);
+
+ memmove(&sctx->resident_img_handles[i],
+ &sctx->resident_img_handles[i + 1], size);
+ }
+
+ sctx->num_resident_img_handles--;
+ return;
+ }
+}
+
+static struct si_resident_descriptor *
+si_create_resident_descriptor(struct si_context *sctx, uint32_t *desc_list,
+ unsigned size)
+{
+ struct si_screen *sscreen = sctx->screen;
+ struct si_resident_descriptor *desc;
+ struct pb_slab_entry *entry;
+ void *ptr;
+
+ /* Sub-allocate the resident descriptor from slabs. */
+ entry = pb_slab_alloc(&sctx->resident_descriptor_slabs, 64, 0);
+ if (!entry)
+ return NULL;
+
+ desc = NULL;
+ desc = container_of(entry, desc, entry);
+
+ /* Upload the descriptor. */
+ ptr = sscreen->b.ws->buffer_map(desc->buffer->buf, NULL,
+ PIPE_TRANSFER_WRITE |
+ PIPE_TRANSFER_UNSYNCHRONIZED);
+ util_memcpy_cpu_to_le32(ptr + desc->offset, desc_list, size);
+ sscreen->b.ws->buffer_unmap(desc->buffer->buf);
+
+ return desc;
+}
+
+static uint64_t si_create_texture_handle(struct pipe_context *ctx,
+ struct pipe_resource *texture,
+ struct pipe_sampler_view *view,
+ const struct pipe_sampler_state *state)
+{
+ struct si_sampler_view *sview = (struct si_sampler_view *)view;
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct si_texture_handle *tex_handle;
+ struct si_sampler_state *sstate;
+ uint32_t desc_list[16];
+ uint64_t handle;
+
+ tex_handle = CALLOC_STRUCT(si_texture_handle);
+ if (!tex_handle)
+ return 0;
+
+ memset(desc_list, 0, sizeof(desc_list));
+ si_init_descriptor_list(&desc_list[0], 16, 1, null_texture_descriptor);
+
+ sstate = ctx->create_sampler_state(ctx, state);
+ if (!sstate) {
+ FREE(tex_handle);
+ return 0;
+ }
+
+ si_set_sampler_view_desc(sctx, sview, sstate, &desc_list[0]);
+ ctx->delete_sampler_state(ctx, sstate);
+
+ tex_handle->view = sview;
+ tex_handle->desc = si_create_resident_descriptor(sctx, desc_list,
+ sizeof(desc_list));
+ if (!tex_handle->desc) {
+ FREE(tex_handle);
+ return 0;
+ }
+
+ handle = tex_handle->desc->buffer->gpu_address +
+ tex_handle->desc->offset;
+
+ if (!_mesa_hash_table_insert(sctx->tex_handles, (void *)handle,
+ tex_handle)) {
+ pb_slab_free(&sctx->resident_descriptor_slabs,
+ &tex_handle->desc->entry);
+ FREE(tex_handle);
+ return 0;
+ }
+
+ return handle;
Here's the reference counting issue. First of all, "texture" isn't
used, which is weird, because it's part of the interface. Then, the
"view" pointer is stored in tex_handle without incrementing the
reference counter, so st/mesa can release it.
It looks like the original idea was to use "texture" as the resource
and "view" as the view template, while this code ignores "texture" and
uses "view" as a full sampler view.
Exactly, in my first implementation, the sampler views were created
directly in si_create_texture_handle(). I will remove this useless
"texture" parameter and I will fix the refcount issue.
Post by Marek Olšák
Post by Samuel Pitoiset
+}
+
+static void si_delete_texture_handle(struct pipe_context *ctx, uint64_t handle)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct si_texture_handle *tex_handle;
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(sctx->tex_handles, (void *)handle);
+ if (!entry)
+ return;
+
+ tex_handle = (struct si_texture_handle *)entry->data;
+
+ _mesa_hash_table_remove(sctx->tex_handles, entry);
+ pb_slab_free(&sctx->resident_descriptor_slabs,
+ &tex_handle->desc->entry);
+ FREE(tex_handle);
+}
+
+static void si_make_texture_handle_resident(struct pipe_context *ctx,
+ uint64_t handle, bool resident)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct si_texture_handle *tex_handle;
+ struct si_sampler_view *sview;
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(sctx->tex_handles, (void *)handle);
+ if (!entry)
+ return;
+
+ tex_handle = (struct si_texture_handle *)entry->data;
+ sview = tex_handle->view;
+
+ if (resident) {
+ si_add_resident_tex_handle(sctx, tex_handle);
+
+ /* Add the buffers to the current CS in case si_begin_new_cs()
+ * is not going to be called.
+ */
+ radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx,
+ tex_handle->desc->buffer,
+ RADEON_USAGE_READ,
+ RADEON_PRIO_DESCRIPTORS);
+
+ si_sampler_view_add_buffer(sctx, sview->base.texture,
+ RADEON_USAGE_READ,
+ sview->is_stencil_sampler, false);
+ } else {
+ si_del_resident_tex_handle(sctx, tex_handle);
+ }
+}
+
+static uint64_t si_create_image_handle(struct pipe_context *ctx,
+ const struct pipe_image_view *view)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct si_image_handle *img_handle;
+ uint32_t desc_list[16];
+ uint64_t handle;
+
+ if (!view || !view->resource)
+ return 0;
+
+ img_handle = CALLOC_STRUCT(si_image_handle);
+ if (!img_handle)
+ return 0;
+
+ memset(desc_list, 0, sizeof(desc_list));
+ si_init_descriptor_list(&desc_list[0], 8, 1, null_image_descriptor);
+
+ si_set_shader_image_desc(sctx, view, false, &desc_list[0]);
+
+ util_copy_image_view(&img_handle->view, view);
+ img_handle->desc = si_create_resident_descriptor(sctx, desc_list,
+ sizeof(desc_list));
+ if (!img_handle->desc) {
+ FREE(img_handle);
This is a memory leak. util_copy_image_view increments the reference
counter of view->resource, which isn't cleared before FREE.
Post by Samuel Pitoiset
+ return 0;
+ }
+
+ handle = img_handle->desc->buffer->gpu_address +
+ img_handle->desc->offset;
+
+ if (!_mesa_hash_table_insert(sctx->img_handles, (void *)handle,
+ img_handle)) {
+ pb_slab_free(&sctx->resident_descriptor_slabs,
+ &img_handle->desc->entry);
+ FREE(img_handle);
+ return 0;
+ }
+
+ return handle;
+}
+
+static void si_delete_image_handle(struct pipe_context *ctx, uint64_t handle)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+ struct si_image_handle *img_handle;
+ struct hash_entry *entry;
+
+ entry = _mesa_hash_table_search(sctx->img_handles, (void *)handle);
+ if (!entry)
+ return;
+
+ img_handle = (struct si_image_handle *)entry->data;
+
+ _mesa_hash_table_remove(sctx->img_handles, entry);
+ pb_slab_free(&sctx->resident_descriptor_slabs,
+ &img_handle->desc->entry);
+ FREE(img_handle);
Same memory leak here.
I've not yet looked at this patch thoroughly. It's just what I've noticed now.
Good catch, fixed locally. Thanks!
Post by Marek Olšák
Marek
Samuel Pitoiset
2017-05-19 16:53:00 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_descriptors.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 44a4b16712..810dd8e89a 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -613,6 +613,13 @@ static void si_update_compressed_tex_shader_mask(struct si_context *sctx,
sctx->compressed_tex_shader_mask &= ~shader_bit;
}

+static void si_update_check_render_feedback(struct si_context *sctx,
+ struct r600_texture *rtex)
+{
+ if (rtex->dcc_offset && p_atomic_read(&rtex->framebuffers_bound))
+ sctx->need_check_render_feedback = true;
+}
+
static void si_set_sampler_views(struct pipe_context *ctx,
enum pipe_shader_type shader, unsigned start,
unsigned count,
@@ -653,9 +660,7 @@ static void si_set_sampler_views(struct pipe_context *ctx,
samplers->compressed_colortex_mask &= ~(1u << slot);
}

- if (rtex->dcc_offset &&
- p_atomic_read(&rtex->framebuffers_bound))
- sctx->need_check_render_feedback = true;
+ si_update_check_render_feedback(sctx, rtex);
} else {
samplers->depth_texture_mask &= ~(1u << slot);
samplers->compressed_colortex_mask &= ~(1u << slot);
@@ -861,9 +866,7 @@ static void si_set_shader_image(struct si_context *ctx,
images->compressed_colortex_mask &= ~(1 << slot);
}

- if (tex->dcc_offset &&
- p_atomic_read(&tex->framebuffers_bound))
- ctx->need_check_render_feedback = true;
+ si_update_check_render_feedback(ctx, tex);
}

images->enabled_mask |= 1u << slot;
--
2.13.0
Samuel Pitoiset
2017-05-19 16:53:01 UTC
Permalink
Analogous to bound textures/images. We should also update the
resident descriptors and disable COMPRESSION_EN for avoiding
useless DCC fetches, but I postpone this optimization for a
separate series.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_blit.c | 52 +++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_descriptors.c | 16 +++++++++
2 files changed, 68 insertions(+)

diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c
index 998288dba2..4078f2498b 100644
--- a/src/gallium/drivers/radeonsi/si_blit.c
+++ b/src/gallium/drivers/radeonsi/si_blit.c
@@ -611,6 +611,54 @@ static void si_check_render_feedback_images(struct si_context *sctx,
}
}

+static void si_check_render_feedback_resident_textures(struct si_context *sctx)
+{
+ unsigned i;
+
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ struct si_texture_handle *tex_handle =
+ sctx->resident_tex_handles[i];
+ struct pipe_sampler_view *view;
+ struct r600_texture *tex;
+
+ view = &tex_handle->view->base;
+ if (view->texture->target == PIPE_BUFFER)
+ continue;
+
+ tex = (struct r600_texture *)view->texture;
+
+ si_check_render_feedback_texture(sctx, tex,
+ view->u.tex.first_level,
+ view->u.tex.last_level,
+ view->u.tex.first_layer,
+ view->u.tex.last_layer);
+ }
+}
+
+static void si_check_render_feedback_resident_images(struct si_context *sctx)
+{
+ unsigned i;
+
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ struct si_image_handle *img_handle =
+ sctx->resident_img_handles[i];
+ struct pipe_image_view *view;
+ struct r600_texture *tex;
+
+ view = &img_handle->view;
+ if (view->resource->target == PIPE_BUFFER)
+ continue;
+
+ tex = (struct r600_texture *)view->resource;
+
+ si_check_render_feedback_texture(sctx, tex,
+ view->u.tex.level,
+ view->u.tex.level,
+ view->u.tex.first_layer,
+ view->u.tex.last_layer);
+ }
+}
+
static void si_check_render_feedback(struct si_context *sctx)
{

@@ -621,6 +669,10 @@ static void si_check_render_feedback(struct si_context *sctx)
si_check_render_feedback_images(sctx, &sctx->images[i]);
si_check_render_feedback_textures(sctx, &sctx->samplers[i]);
}
+
+ si_check_render_feedback_resident_images(sctx);
+ si_check_render_feedback_resident_textures(sctx);
+
sctx->need_check_render_feedback = false;
}

diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 810dd8e89a..e459f19d66 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -2416,6 +2416,13 @@ static void si_make_texture_handle_resident(struct pipe_context *ctx,
sview = tex_handle->view;

if (resident) {
+ if (sview->base.texture->target != PIPE_BUFFER) {
+ struct r600_texture *rtex =
+ (struct r600_texture *)sview->base.texture;
+
+ si_update_check_render_feedback(sctx, rtex);
+ }
+
si_add_resident_tex_handle(sctx, tex_handle);

/* Add the buffers to the current CS in case si_begin_new_cs()
@@ -2511,6 +2518,15 @@ static void si_make_image_handle_resident(struct pipe_context *ctx,
view = &img_handle->view;

if (resident) {
+ struct r600_resource *res =
+ (struct r600_resource *)view->resource;
+
+ if (res->b.b.target != PIPE_BUFFER) {
+ struct r600_texture *rtex = (struct r600_texture *)res;
+
+ si_update_check_render_feedback(sctx, rtex);
+ }
+
si_add_resident_img_handle(sctx, img_handle);

/* Add the buffers to the current CS in case si_begin_new_cs()
--
2.13.0
Samuel Pitoiset
2017-05-19 16:53:03 UTC
Permalink
When a stencil buffer is part of the framebuffer state, it is
decompressed but because it's bindles, all draw calls set
stencil_dirty_level_mask to 1.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_blit.c | 8 ++++++++
src/gallium/drivers/radeonsi/si_pipe.h | 1 +
src/gallium/drivers/radeonsi/si_state.c | 10 ++++++++--
3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c
index 32041695e2..0cf3ea79b9 100644
--- a/src/gallium/drivers/radeonsi/si_blit.c
+++ b/src/gallium/drivers/radeonsi/si_blit.c
@@ -235,12 +235,16 @@ si_blit_decompress_zs_planes_in_place(struct si_context *sctx,

zsurf = sctx->b.b.create_surface(&sctx->b.b, &texture->resource.b.b, &surf_tmpl);

+ sctx->decompression_enabled = true;
+
si_blitter_begin(&sctx->b.b, SI_DECOMPRESS);
util_blitter_custom_depth_stencil(sctx->blitter, zsurf, NULL, ~0,
sctx->custom_dsa_flush,
1.0f);
si_blitter_end(&sctx->b.b);

+ sctx->decompression_enabled = false;
+
pipe_surface_reference(&zsurf, NULL);
}

@@ -454,10 +458,14 @@ static void si_blit_decompress_color(struct pipe_context *ctx,
surf_tmpl.u.tex.last_layer = layer;
cbsurf = ctx->create_surface(ctx, &rtex->resource.b.b, &surf_tmpl);

+ sctx->decompression_enabled = true;
+
si_blitter_begin(ctx, SI_DECOMPRESS);
util_blitter_custom_color(sctx->blitter, cbsurf, custom_blend);
si_blitter_end(ctx);

+ sctx->decompression_enabled = false;
+
pipe_surface_reference(&cbsurf, NULL);
}

diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 7dafa77c37..8d8efbda1f 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -402,6 +402,7 @@ struct si_context {

/* Other state */
bool need_check_render_feedback;
+ bool decompression_enabled;

/* Precomputed IA_MULTI_VGT_PARAM */
union si_vgt_param_key ia_multi_vgt_param_key;
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index 363f32170a..7256ec0c62 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -2611,9 +2611,15 @@ static void si_set_framebuffer_state(struct pipe_context *ctx,
si_mark_atom_dirty(sctx, &sctx->msaa_sample_locs.atom);
}

- sctx->need_check_render_feedback = true;
sctx->do_update_shaders = true;
- sctx->framebuffer.do_update_surf_dirtiness = true;
+
+ if (!sctx->decompression_enabled) {
+ /* Prevent textures decompression when the framebuffer state
+ * changes come from the decompression passes themselves.
+ */
+ sctx->need_check_render_feedback = true;
+ sctx->framebuffer.do_update_surf_dirtiness = true;
+ }
}

static void si_emit_framebuffer_state(struct si_context *sctx, struct r600_atom *atom)
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:48 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_context.c | 2 +
src/mesa/state_tracker/st_context.h | 11 ++++++
src/mesa/state_tracker/st_texture.c | 77 +++++++++++++++++++++++++++++++++++++
src/mesa/state_tracker/st_texture.h | 5 +++
4 files changed, 95 insertions(+)

diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index c901764668..4dcc160b50 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -292,6 +292,8 @@ st_destroy_context_priv(struct st_context *st, bool destroy_pipe)
st_destroy_drawtex(st);
st_destroy_perfmon(st);
st_destroy_pbo_helpers(st);
+ st_destroy_bound_texture_handles(st);
+ st_destroy_bound_image_handles(st);

for (shader = 0; shader < ARRAY_SIZE(st->state.sampler_views); shader++) {
for (i = 0; i < ARRAY_SIZE(st->state.sampler_views[0]); i++) {
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 520cd8d462..16f29669be 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -79,6 +79,12 @@ struct st_bitmap_cache
ubyte *buffer;
};

+struct st_bound_handle
+{
+ unsigned num_handles;
+ uint64_t *handles;
+};
+
struct st_context
{
struct st_context_iface iface;
@@ -271,6 +277,11 @@ struct st_context
struct st_perf_monitor_group *perfmon;

enum pipe_reset_status reset_status;
+
+ /* Array of bound texture/image handles which are resident in the context.
+ */
+ struct st_bound_handle bound_texture_handles[PIPE_SHADER_TYPES];
+ struct st_bound_handle bound_image_handles[PIPE_SHADER_TYPES];
};


diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
index 65f86f2b4f..cde7759a61 100644
--- a/src/mesa/state_tracker/st_texture.c
+++ b/src/mesa/state_tracker/st_texture.c
@@ -421,6 +421,83 @@ st_create_color_map_texture(struct gl_context *ctx)
return pt;
}

+/**
+ * Destroy bound texture handles for the given stage.
+ */
+static void
+st_destroy_bound_texture_handles_per_stage(struct st_context *st,
+ enum pipe_shader_type shader)
+{
+ struct st_bound_handle *bound_handles = &st->bound_texture_handles[shader];
+ struct pipe_context *pipe = st->pipe;
+ unsigned i;
+
+ if (likely(!bound_handles->num_handles))
+ return;
+
+ for (i = 0; i < bound_handles->num_handles; i++) {
+ uint64_t handle = bound_handles->handles[i];
+
+ pipe->make_texture_handle_resident(pipe, handle, false);
+ pipe->delete_texture_handle(pipe, handle);
+ }
+ free(bound_handles->handles);
+ bound_handles->num_handles = 0;
+}
+
+
+/**
+ * Destroy all bound texture handles in the context.
+ */
+void
+st_destroy_bound_texture_handles(struct st_context *st)
+{
+ unsigned i;
+
+ for (i = 0; i < PIPE_SHADER_TYPES; i++) {
+ st_destroy_bound_texture_handles_per_stage(st, i);
+ }
+}
+
+
+/**
+ * Destroy bound image handles for the given stage.
+ */
+static void
+st_destroy_bound_image_handles_per_stage(struct st_context *st,
+ enum pipe_shader_type shader)
+{
+ struct st_bound_handle *bound_handles = &st->bound_image_handles[shader];
+ struct pipe_context *pipe = st->pipe;
+ unsigned i;
+
+ if (likely(!bound_handles->num_handles))
+ return;
+
+ for (i = 0; i < bound_handles->num_handles; i++) {
+ uint64_t handle = bound_handles->handles[i];
+
+ pipe->make_image_handle_resident(pipe, handle, GL_READ_WRITE, false);
+ pipe->delete_image_handle(pipe, handle);
+ }
+ free(bound_handles->handles);
+ bound_handles->num_handles = 0;
+}
+
+
+/**
+ * Destroy all bound image handles in the context.
+ */
+void
+st_destroy_bound_image_handles(struct st_context *st)
+{
+ unsigned i;
+
+ for (i = 0; i < PIPE_SHADER_TYPES; i++) {
+ st_destroy_bound_image_handles_per_stage(st, i);
+ }
+}
+

/**
* Create a texture handle from a texture unit.
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index 7f8a0cb841..b97814cb16 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -250,6 +250,11 @@ st_texture_image_copy(struct pipe_context *pipe,
extern struct pipe_resource *
st_create_color_map_texture(struct gl_context *ctx);

+void
+st_destroy_bound_texture_handles(struct st_context *st);
+
+void
+st_destroy_bound_image_handles(struct st_context *st);

bool
st_etc_fallback(struct st_context *st, struct gl_texture_image *texImage);
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:52 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_extensions.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
index 2fa7ba7797..80695580cb 100644
--- a/src/mesa/state_tracker/st_extensions.c
+++ b/src/mesa/state_tracker/st_extensions.c
@@ -577,6 +577,7 @@ void st_init_extensions(struct pipe_screen *screen,

static const struct st_extension_cap_mapping cap_mapping[] = {
{ o(ARB_base_instance), PIPE_CAP_START_INSTANCE },
+ { o(ARB_bindless_texture), PIPE_CAP_BINDLESS_TEXTURE },
{ o(ARB_buffer_storage), PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT },
{ o(ARB_clear_texture), PIPE_CAP_CLEAR_TEXTURE },
{ o(ARB_clip_control), PIPE_CAP_CLIP_HALFZ },
--
2.13.0
Marek Olšák
2017-05-23 20:22:41 UTC
Permalink
For patches 32-36, 38-41, 47:

Reviewed-by: Marek Olšák <***@amd.com>

Marek

On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
---
src/mesa/state_tracker/st_extensions.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
index 2fa7ba7797..80695580cb 100644
--- a/src/mesa/state_tracker/st_extensions.c
+++ b/src/mesa/state_tracker/st_extensions.c
@@ -577,6 +577,7 @@ void st_init_extensions(struct pipe_screen *screen,
static const struct st_extension_cap_mapping cap_mapping[] = {
{ o(ARB_base_instance), PIPE_CAP_START_INSTANCE },
+ { o(ARB_bindless_texture), PIPE_CAP_BINDLESS_TEXTURE },
{ o(ARB_buffer_storage), PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT },
{ o(ARB_clear_texture), PIPE_CAP_CLEAR_TEXTURE },
{ o(ARB_clip_control), PIPE_CAP_CLIP_HALFZ },
--
2.13.0
_______________________________________________
mesa-dev mailing list
https://lists.freedesktop.org/mailman/listinfo/mesa-dev
Samuel Pitoiset
2017-05-19 16:52:45 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_atom_sampler.c | 14 ++++++++------
src/mesa/state_tracker/st_texture.h | 5 +++++
2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c
index f33e334bb9..c6d992fbb0 100644
--- a/src/mesa/state_tracker/st_atom_sampler.c
+++ b/src/mesa/state_tracker/st_atom_sampler.c
@@ -230,11 +230,13 @@ st_convert_sampler(const struct st_context *st,
ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless;
}

-
-static void
-convert_sampler_from_unit(const struct st_context *st,
- struct pipe_sampler_state *sampler,
- GLuint texUnit)
+/**
+ * Get a pipe_sampler_state object from a texture unit.
+ */
+void
+st_convert_sampler_from_unit(const struct st_context *st,
+ struct pipe_sampler_state *sampler,
+ GLuint texUnit)
{
const struct gl_texture_object *texobj;
struct gl_context *ctx = st->ctx;
@@ -282,7 +284,7 @@ update_shader_samplers(struct st_context *st,
if (samplers_used & 1) {
const GLuint texUnit = prog->SamplerUnits[unit];

- convert_sampler_from_unit(st, sampler, texUnit);
+ st_convert_sampler_from_unit(st, sampler, texUnit);
states[unit] = sampler;
*num_samplers = unit + 1;
}
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index 8eb0b4be47..e73de2f1d3 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -264,6 +264,11 @@ st_convert_sampler(const struct st_context *st,
const struct gl_sampler_object *msamp,
struct pipe_sampler_state *sampler);

+void
+st_convert_sampler_from_unit(const struct st_context *st,
+ struct pipe_sampler_state *sampler,
+ GLuint texUnit);
+
GLboolean
st_update_single_texture(struct st_context *st,
struct pipe_sampler_view **sampler_view,
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:47 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_texture.c | 42 +++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)

diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
index 2e9856dcdf..65f86f2b4f 100644
--- a/src/mesa/state_tracker/st_texture.c
+++ b/src/mesa/state_tracker/st_texture.c
@@ -420,3 +420,45 @@ st_create_color_map_texture(struct gl_context *ctx)
texSize, texSize, 1, 1, 0, PIPE_BIND_SAMPLER_VIEW);
return pt;
}
+
+
+/**
+ * Create a texture handle from a texture unit.
+ */
+static GLuint64
+st_create_texture_handle_from_unit(struct st_context *st,
+ struct gl_program *prog, GLuint texUnit)
+{
+ struct gl_context *ctx = st->ctx;
+ struct gl_texture_object *texObj;
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_sampler_view *view;
+ struct pipe_sampler_state sampler;
+
+ if (!st_update_single_texture(st, &view, texUnit, prog->sh.data->Version))
+ return 0;
+
+ st_convert_sampler_from_unit(st, &sampler, texUnit);
+
+ texObj = ctx->Texture.Unit[texUnit]._Current;
+ assert(texObj);
+
+ return pipe->create_texture_handle(pipe, st_texture_object(texObj)->pt,
+ view, &sampler);
+}
+
+
+/**
+ * Create an image handle from an image unit.
+ */
+static GLuint64
+st_create_image_handle_from_unit(struct st_context *st,
+ struct gl_program *prog, GLuint imgUnit)
+{
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_image_view img;
+
+ st_convert_image_from_unit(st, &img, imgUnit);
+
+ return pipe->create_image_handle(pipe, &img);
+}
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:46 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_atom_image.c | 33 ++++++++++++++++++++++-----------
src/mesa/state_tracker/st_texture.h | 5 +++++
2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_image.c b/src/mesa/state_tracker/st_atom_image.c
index 381eca191a..5b914637a2 100644
--- a/src/mesa/state_tracker/st_atom_image.c
+++ b/src/mesa/state_tracker/st_atom_image.c
@@ -102,6 +102,27 @@ st_convert_image(const struct st_context *st, const struct gl_image_unit *u,
}
}

+/**
+ * Get a pipe_image_view object from an image unit.
+ */
+void
+st_convert_image_from_unit(const struct st_context *st,
+ struct pipe_image_view *img,
+ GLuint imgUnit)
+{
+ struct gl_image_unit *u = &st->ctx->ImageUnits[imgUnit];
+ struct st_texture_object *stObj = st_texture_object(u->TexObj);
+
+ if (!_mesa_is_image_unit_valid(st->ctx, u) ||
+ !st_finalize_texture(st->ctx, st->pipe, u->TexObj, 0) ||
+ !stObj->pt) {
+ memset(img, 0, sizeof(*img));
+ return;
+ }
+
+ st_convert_image(st, u, img);
+}
+
static void
st_bind_images(struct st_context *st, struct gl_program *prog,
enum pipe_shader_type shader_type)
@@ -116,19 +137,9 @@ st_bind_images(struct st_context *st, struct gl_program *prog,
c = &st->ctx->Const.Program[prog->info.stage];

for (i = 0; i < prog->info.num_images; i++) {
- struct gl_image_unit *u =
- &st->ctx->ImageUnits[prog->sh.ImageUnits[i]];
- struct st_texture_object *stObj = st_texture_object(u->TexObj);
struct pipe_image_view *img = &images[i];

- if (!_mesa_is_image_unit_valid(st->ctx, u) ||
- !st_finalize_texture(st->ctx, st->pipe, u->TexObj, 0) ||
- !stObj->pt) {
- memset(img, 0, sizeof(*img));
- continue;
- }
-
- st_convert_image(st, u, img);
+ st_convert_image_from_unit(st, img, prog->sh.ImageUnits[i]);
}
cso_set_shader_images(st->cso_context, shader_type, 0,
prog->info.num_images, images);
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index e73de2f1d3..7f8a0cb841 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -259,6 +259,11 @@ st_convert_image(const struct st_context *st, const struct gl_image_unit *u,
struct pipe_image_view *img);

void
+st_convert_image_from_unit(const struct st_context *st,
+ struct pipe_image_view *img,
+ GLuint imgUnit);
+
+void
st_convert_sampler(const struct st_context *st,
const struct gl_texture_object *texobj,
const struct gl_sampler_object *msamp,
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:43 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_cb_texture.c | 84 ++++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)

diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 99c59f77a3..fabf78e7a7 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -2880,6 +2880,82 @@ st_TexParameter(struct gl_context *ctx,
}


+static GLuint64
+st_NewTextureHandle(struct gl_context *ctx, struct gl_texture_object *texObj,
+ struct gl_sampler_object *sampObj)
+{
+ struct st_context *st = st_context(ctx);
+ struct st_texture_object *stObj = st_texture_object(texObj);
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_sampler_view *view;
+ struct pipe_sampler_state sampler;
+
+ if (!st_finalize_texture(ctx, pipe, texObj, 0))
+ return 0;
+
+ st_convert_sampler(st, texObj, sampObj, &sampler);
+
+ view = st_get_texture_sampler_view_from_stobj(st, stObj, sampObj, 0);
+
+ return pipe->create_texture_handle(pipe, stObj->pt, view, &sampler);
+}
+
+
+static void
+st_DeleteTextureHandle(struct gl_context *ctx, GLuint64 handle)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+
+ pipe->delete_texture_handle(pipe, handle);
+}
+
+
+static void
+st_MakeTextureHandleResident(struct gl_context *ctx, GLuint64 handle,
+ bool resident)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+
+ pipe->make_texture_handle_resident(pipe, handle, resident);
+}
+
+
+static GLuint64
+st_NewImageHandle(struct gl_context *ctx, struct gl_image_unit *imgObj)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct pipe_image_view image;
+
+ st_convert_image(st, imgObj, &image);
+
+ return pipe->create_image_handle(pipe, &image);
+}
+
+
+static void
+st_DeleteImageHandle(struct gl_context *ctx, GLuint64 handle)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+
+ pipe->delete_image_handle(pipe, handle);
+}
+
+
+static void
+st_MakeImageHandleResident(struct gl_context *ctx, GLuint64 handle,
+ GLenum access, bool resident)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+
+ pipe->make_image_handle_resident(pipe, handle, access, resident);
+}
+
+
void
st_init_texture_functions(struct dd_function_table *functions)
{
@@ -2914,4 +2990,12 @@ st_init_texture_functions(struct dd_function_table *functions)
functions->ClearTexSubImage = st_ClearTexSubImage;

functions->TexParameter = st_TexParameter;
+
+ /* bindless functions */
+ functions->NewTextureHandle = st_NewTextureHandle;
+ functions->DeleteTextureHandle = st_DeleteTextureHandle;
+ functions->MakeTextureHandleResident = st_MakeTextureHandleResident;
+ functions->NewImageHandle = st_NewImageHandle;
+ functions->DeleteImageHandle = st_DeleteImageHandle;
+ functions->MakeImageHandleResident = st_MakeImageHandleResident;
}
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:32 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/trace/tr_context.c | 114 +++++++++++++++++++++++++++++++++
1 file changed, 114 insertions(+)

diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index c5563a4844..6639f783a5 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -1704,6 +1704,114 @@ static void trace_context_launch_grid(struct pipe_context *_pipe,
trace_dump_call_end();
}

+static uint64_t trace_context_create_texture_handle(struct pipe_context *_pipe,
+ struct pipe_resource *res,
+ struct pipe_sampler_view *view,
+ const struct pipe_sampler_state *state)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ uint64_t handle;
+
+ trace_dump_call_begin("pipe_context", "create_texture_handle");
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(ptr, res);
+ trace_dump_arg(ptr, view);
+ trace_dump_arg_begin("state");
+ trace_dump_arg(sampler_state, state);
+ trace_dump_arg_end();
+
+ handle = pipe->create_texture_handle(pipe, res, view, state);
+
+ trace_dump_ret(uint, handle);
+ trace_dump_call_end();
+
+ return handle;
+}
+
+static void trace_context_delete_texture_handle(struct pipe_context *_pipe,
+ uint64_t handle)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "delete_texture_handle");
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, handle);
+ trace_dump_call_end();
+
+ pipe->delete_texture_handle(pipe, handle);
+}
+
+static void trace_context_make_texture_handle_resident(struct pipe_context *_pipe,
+ uint64_t handle,
+ bool resident)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "make_texture_handle_resident");
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, handle);
+ trace_dump_arg(bool, resident);
+ trace_dump_call_end();
+
+ pipe->make_texture_handle_resident(pipe, handle, resident);
+}
+
+static uint64_t trace_context_create_image_handle(struct pipe_context *_pipe,
+ const struct pipe_image_view *image)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+ uint64_t handle;
+
+ trace_dump_call_begin("pipe_context", "create_image_handle");
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg_begin("image");
+ trace_dump_image_view(image);
+ trace_dump_arg_end();
+
+ handle = pipe->create_image_handle(pipe, image);
+
+ trace_dump_ret(uint, handle);
+ trace_dump_call_end();
+
+ return handle;
+}
+
+static void trace_context_delete_image_handle(struct pipe_context *_pipe,
+ uint64_t handle)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "delete_image_handle");
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, handle);
+ trace_dump_call_end();
+
+ pipe->delete_image_handle(pipe, handle);
+}
+
+static void trace_context_make_image_handle_resident(struct pipe_context *_pipe,
+ uint64_t handle,
+ unsigned access,
+ bool resident)
+{
+ struct trace_context *tr_ctx = trace_context(_pipe);
+ struct pipe_context *pipe = tr_ctx->pipe;
+
+ trace_dump_call_begin("pipe_context", "make_image_handle_resident");
+ trace_dump_arg(ptr, pipe);
+ trace_dump_arg(uint, handle);
+ trace_dump_arg(uint, access);
+ trace_dump_arg(bool, resident);
+ trace_dump_call_end();
+
+ pipe->make_image_handle_resident(pipe, handle, access, resident);
+}
+
struct pipe_context *
trace_context_create(struct trace_screen *tr_scr,
struct pipe_context *pipe)
@@ -1805,6 +1913,12 @@ trace_context_create(struct trace_screen *tr_scr,
TR_CTX_INIT(set_shader_buffers);
TR_CTX_INIT(launch_grid);
TR_CTX_INIT(set_shader_images);
+ TR_CTX_INIT(create_texture_handle);
+ TR_CTX_INIT(delete_texture_handle);
+ TR_CTX_INIT(make_texture_handle_resident);
+ TR_CTX_INIT(create_image_handle);
+ TR_CTX_INIT(delete_image_handle);
+ TR_CTX_INIT(make_image_handle_resident);

TR_CTX_INIT(transfer_map);
TR_CTX_INIT(transfer_unmap);
--
2.13.0
Samuel Pitoiset
2017-05-19 16:53:09 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c | 31 ++++++++++++++++++-----
1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c b/src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c
index c9397c2fb8..1447a552b9 100644
--- a/src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c
+++ b/src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c
@@ -184,7 +184,10 @@ image_fetch_rsrc(
LLVMValueRef index;
bool dcc_off = is_store;

- assert(image->Register.File == TGSI_FILE_IMAGE);
+ assert(image->Register.File == TGSI_FILE_IMAGE ||
+ image->Register.File == TGSI_FILE_CONSTANT ||
+ image->Register.File == TGSI_FILE_TEMPORARY ||
+ image->Register.File == TGSI_FILE_INPUT);

if (!image->Register.Indirect) {
const struct tgsi_shader_info *info = bld_base->info;
@@ -214,6 +217,18 @@ image_fetch_rsrc(
index, "");
}

+ if (image->Register.File != TGSI_FILE_IMAGE) {
+ struct gallivm_state *gallivm = &ctx->gallivm;
+ LLVMBuilderRef builder = gallivm->builder;
+
+ LLVMValueRef ptr =
+ lp_build_emit_fetch_src(bld_base, image,
+ TGSI_TYPE_UNSIGNED64, 0);
+ rsrc_ptr = LLVMBuildIntToPtr(builder, ptr,
+ si_const_array(ctx->v8i32, 0), "");
+ index = LLVMConstInt(ctx->i32, 0, 0);
+ }
+
*rsrc = load_image_desc(ctx, rsrc_ptr, index, target);
if (dcc_off && target != TGSI_TEXTURE_BUFFER)
*rsrc = force_dcc_off(ctx, *rsrc);
@@ -373,7 +388,8 @@ static void load_fetch_args(

buffer_append_args(ctx, emit_data, rsrc, ctx->i32_0,
offset, false, false);
- } else if (inst->Src[0].Register.File == TGSI_FILE_IMAGE) {
+ } else if (inst->Src[0].Register.File == TGSI_FILE_IMAGE ||
+ inst->Memory.Bindless) {
LLVMValueRef coords;

image_fetch_rsrc(bld_base, &inst->Src[0], false, target, &rsrc);
@@ -538,8 +554,9 @@ static bool is_oneway_access_only(const struct tgsi_full_instruction *inst,
* images.
*/
if (inst->Src[0].Register.File == TGSI_FILE_BUFFER ||
- (inst->Src[0].Register.File == TGSI_FILE_IMAGE &&
- inst->Memory.Texture == TGSI_TEXTURE_BUFFER)) {
+ (inst->Memory.Texture == TGSI_TEXTURE_BUFFER &&
+ (inst->Src[0].Register.File == TGSI_FILE_IMAGE ||
+ inst->Memory.Bindless))) {
if (!shader_buffers_reverse_access_mask &&
!(info->images_buffers & images_reverse_access_mask))
return true;
@@ -640,7 +657,8 @@ static void store_fetch_args(

buffer_append_args(ctx, emit_data, rsrc, ctx->i32_0,
offset, false, false);
- } else if (inst->Dst[0].Register.File == TGSI_FILE_IMAGE) {
+ } else if (inst->Dst[0].Register.File == TGSI_FILE_IMAGE ||
+ inst->Memory.Bindless) {
unsigned target = inst->Memory.Texture;
LLVMValueRef coords;

@@ -859,7 +877,8 @@ static void atomic_fetch_args(

buffer_append_args(ctx, emit_data, rsrc, ctx->i32_0,
offset, true, false);
- } else if (inst->Src[0].Register.File == TGSI_FILE_IMAGE) {
+ } else if (inst->Src[0].Register.File == TGSI_FILE_IMAGE ||
+ inst->Memory.Bindless) {
unsigned target = inst->Memory.Texture;
LLVMValueRef coords;
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:39 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 264b43c10b..f30544eb4c 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -2328,6 +2328,10 @@ glsl_to_tgsi_visitor::visit_expression(ir_expression* ir, st_src_reg *op)
case ir_unop_pack_int_2x32:
case ir_unop_unpack_uint_2x32:
case ir_unop_pack_uint_2x32:
+ case ir_unop_unpack_sampler_2x32:
+ case ir_unop_pack_sampler_2x32:
+ case ir_unop_unpack_image_2x32:
+ case ir_unop_pack_image_2x32:
emit_asm(ir, TGSI_OPCODE_MOV, result_dst, op[0]);
break;

@@ -2486,11 +2490,6 @@ glsl_to_tgsi_visitor::visit_expression(ir_expression* ir, st_src_reg *op)
case ir_unop_unpack_snorm_4x8:
case ir_unop_unpack_unorm_4x8:

- case ir_unop_unpack_sampler_2x32:
- case ir_unop_pack_sampler_2x32:
- case ir_unop_unpack_image_2x32:
- case ir_unop_pack_image_2x32:
-
case ir_quadop_vector:
case ir_binop_vector_extract:
case ir_triop_vector_insert:
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:56 UTC
Permalink
To share some common code between bound and bindless images.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_descriptors.c | 78 ++++++++++++++++-----------
1 file changed, 46 insertions(+), 32 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index e73dbc9f9f..abe39de583 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -748,28 +748,16 @@ si_mark_image_range_valid(const struct pipe_image_view *view)
view->u.buf.offset + view->u.buf.size);
}

-static void si_set_shader_image(struct si_context *ctx,
- unsigned shader,
- unsigned slot, const struct pipe_image_view *view,
- bool skip_decompress)
+static void si_set_shader_image_desc(struct si_context *ctx,
+ const struct pipe_image_view *view,
+ bool skip_decompress,
+ uint32_t *desc)
{
struct si_screen *screen = ctx->screen;
- struct si_images_info *images = &ctx->images[shader];
- struct si_descriptors *descs = si_sampler_and_image_descriptors(ctx, shader);
struct r600_resource *res;
- unsigned desc_slot = si_get_image_slot(slot);
- uint32_t *desc = descs->list + desc_slot * 8;
-
- if (!view || !view->resource) {
- si_disable_shader_image(ctx, shader, slot);
- return;
- }

res = (struct r600_resource *)view->resource;

- if (&images->views[slot] != view)
- util_copy_image_view(&images->views[slot], view);
-
if (res->b.b.target == PIPE_BUFFER) {
if (view->access & PIPE_IMAGE_ACCESS_WRITE)
si_mark_image_range_valid(view);
@@ -779,9 +767,6 @@ static void si_set_shader_image(struct si_context *ctx,
view->u.buf.offset,
view->u.buf.size, desc);
si_set_buf_desc_address(res, view->u.buf.offset, desc + 4);
-
- images->compressed_colortex_mask &= ~(1 << slot);
- res->bind_history |= PIPE_BIND_SHADER_IMAGE;
} else {
static const unsigned char swizzle[4] = { 0, 1, 2, 3 };
struct r600_texture *tex = (struct r600_texture *)res;
@@ -799,22 +784,10 @@ static void si_set_shader_image(struct si_context *ctx,
* The decompression is relatively cheap if the surface
* has been decompressed already.
*/
- if (r600_texture_disable_dcc(&ctx->b, tex))
- uses_dcc = false;
- else
+ if (!r600_texture_disable_dcc(&ctx->b, tex))
ctx->b.decompress_dcc(&ctx->b.b, tex);
}

- if (is_compressed_colortex(tex)) {
- images->compressed_colortex_mask |= 1 << slot;
- } else {
- images->compressed_colortex_mask &= ~(1 << slot);
- }
-
- if (uses_dcc &&
- p_atomic_read(&tex->framebuffers_bound))
- ctx->need_check_render_feedback = true;
-
if (ctx->b.chip_class >= GFX9) {
/* Always set the base address. The swizzle modes don't
* allow setting mipmap level offsets as the base.
@@ -850,6 +823,47 @@ static void si_set_shader_image(struct si_context *ctx,
util_format_get_blockwidth(view->format),
false, desc);
}
+}
+
+static void si_set_shader_image(struct si_context *ctx,
+ unsigned shader,
+ unsigned slot, const struct pipe_image_view *view,
+ bool skip_decompress)
+{
+ struct si_images_info *images = &ctx->images[shader];
+ struct si_descriptors *descs = si_sampler_and_image_descriptors(ctx, shader);
+ struct r600_resource *res;
+ unsigned desc_slot = si_get_image_slot(slot);
+ uint32_t *desc = descs->list + desc_slot * 8;
+
+ if (!view || !view->resource) {
+ si_disable_shader_image(ctx, shader, slot);
+ return;
+ }
+
+ res = (struct r600_resource *)view->resource;
+
+ if (&images->views[slot] != view)
+ util_copy_image_view(&images->views[slot], view);
+
+ si_set_shader_image_desc(ctx, view, skip_decompress, desc);
+
+ if (res->b.b.target == PIPE_BUFFER) {
+ images->compressed_colortex_mask &= ~(1 << slot);
+ res->bind_history |= PIPE_BIND_SHADER_IMAGE;
+ } else {
+ struct r600_texture *tex = (struct r600_texture *)res;
+
+ if (is_compressed_colortex(tex)) {
+ images->compressed_colortex_mask |= 1 << slot;
+ } else {
+ images->compressed_colortex_mask &= ~(1 << slot);
+ }
+
+ if (tex->dcc_offset &&
+ p_atomic_read(&tex->framebuffers_bound))
+ ctx->need_check_render_feedback = true;
+ }

images->enabled_mask |= 1u << slot;
/* two 8-byte images share one 16-byte slot */
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:53 UTC
Permalink
For each texture/image handles, we need to allocate a new
buffer for the resident descriptor. But when the number of
buffers added to the current CS becomes high, the overhead
in the winsys (and in the kernel) is important.

To reduce this bottleneck, the idea is to suballocate the
resident descriptors using a slab similar to the one used
in the winsys.

Currently, a buffer can hold 1024 resident descriptors but
this limit is arbitrary and could be changed in the future
for some reasons. Once a slab is allocated the "base" buffer
is added to a per-context residency list.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_descriptors.c | 150 ++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_pipe.c | 10 ++
src/gallium/drivers/radeonsi/si_pipe.h | 15 +++
src/gallium/drivers/radeonsi/si_state.h | 8 ++
4 files changed, 183 insertions(+)

diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 61eb2f10be..d337fc3f11 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -2005,6 +2005,156 @@ void si_emit_compute_shader_userdata(struct si_context *sctx)
sctx->shader_pointers_dirty &= ~compute_mask;
}

+/* BINDLESS */
+
+static int si_add_resident_descriptor(struct si_context *sctx,
+ struct r600_resource *desc)
+{
+ int idx;
+
+ /* New resident descriptor, check if the backing array is large enough. */
+ if (sctx->num_resident_descriptors >= sctx->max_resident_descriptors) {
+ unsigned new_max_descriptors =
+ MAX2(1, sctx->max_resident_descriptors * 2);
+ struct r600_resource **new_descriptors =
+ REALLOC(sctx->resident_descriptors,
+ sctx->num_resident_descriptors * (sizeof(*new_descriptors)),
+ new_max_descriptors * sizeof(*new_descriptors));
+
+ if (new_descriptors) {
+ sctx->resident_descriptors = new_descriptors;
+ sctx->max_resident_descriptors = new_max_descriptors;
+ } else {
+ fprintf(stderr, "si_add_resident_descriptor: "
+ "allocation failed\n");
+ return -1;
+ }
+ }
+
+ idx = sctx->num_resident_descriptors;
+ sctx->resident_descriptors[idx] = desc;
+ sctx->num_resident_descriptors++;
+
+ return 0;
+}
+
+static void si_del_resident_descriptor(struct si_context *sctx,
+ struct r600_resource *desc)
+{
+ unsigned i;
+ int size;
+
+ for (i = 0; i < sctx->num_resident_descriptors; i++) {
+ if (sctx->resident_descriptors[i] != desc)
+ continue;
+
+ if (i < sctx->num_resident_descriptors - 1) {
+ size = sizeof(*sctx->resident_descriptors) *
+ (sctx->num_resident_descriptors - 1 - i);
+
+ memmove(&sctx->resident_descriptors[i],
+ &sctx->resident_descriptors[i + 1], size);
+ }
+
+ sctx->num_resident_descriptors--;
+ return;
+ }
+}
+
+struct si_resident_descriptor_slab
+{
+ struct pb_slab base;
+ struct r600_resource *buffer;
+ struct si_resident_descriptor *entries;
+};
+
+bool si_resident_descriptor_can_reclaim_slab(void *priv,
+ struct pb_slab_entry *entry)
+{
+ struct si_context *sctx = priv;
+ struct radeon_winsys *ws = sctx->b.ws;
+ struct si_resident_descriptor *desc = NULL; /* fix container_of */
+
+ desc = container_of(entry, desc, entry);
+
+ if (ws->cs_is_buffer_referenced(sctx->b.gfx.cs, desc->buffer->buf,
+ RADEON_USAGE_READ)) {
+ /* Do not allow to reclaim the buffer if the resident
+ * descriptor is currently used.
+ */
+ return false;
+ }
+
+ return true;
+}
+
+struct pb_slab *si_resident_descriptor_slab_alloc(void *priv, unsigned heap,
+ unsigned entry_size,
+ unsigned group_index)
+{
+ struct si_context *sctx = priv;
+ struct si_screen *sscreen = sctx->screen;
+ struct si_resident_descriptor_slab *slab;
+
+ slab = CALLOC_STRUCT(si_resident_descriptor_slab);
+ if (!slab)
+ return NULL;
+
+ /* Create a buffer in VRAM for 1024 resident descriptors. */
+ slab->buffer = (struct r600_resource *)
+ pipe_buffer_create(&sscreen->b.b, 0,
+ PIPE_USAGE_IMMUTABLE, 64 * 1024);
+ if (!slab->buffer)
+ goto fail;
+
+ slab->base.num_entries = slab->buffer->bo_size / entry_size;
+ slab->base.num_free = slab->base.num_entries;
+ slab->entries = CALLOC(slab->base.num_entries, sizeof(*slab->entries));
+ if (!slab->entries)
+ goto fail_buffer;
+
+ LIST_INITHEAD(&slab->base.free);
+
+ for (unsigned i = 0; i < slab->base.num_entries; ++i) {
+ struct si_resident_descriptor *desc = &slab->entries[i];
+
+ desc->entry.slab = &slab->base;
+ desc->entry.group_index = group_index;
+ desc->buffer = slab->buffer;
+ desc->offset = i * entry_size;
+
+ LIST_ADDTAIL(&desc->entry.head, &slab->base.free);
+ }
+
+ /* Add the descriptor to the per-context residency list. */
+ if (si_add_resident_descriptor(sctx, slab->buffer))
+ goto fail_desc;
+
+ return &slab->base;
+
+fail_desc:
+ FREE(slab->entries);
+fail_buffer:
+ r600_resource_reference(&slab->buffer, NULL);
+fail:
+ FREE(slab);
+ return NULL;
+}
+
+void si_resident_descriptor_slab_free(void *priv, struct pb_slab *pslab)
+{
+ struct si_context *sctx = priv;
+ struct si_resident_descriptor_slab *slab =
+ (struct si_resident_descriptor_slab *)pslab;
+
+ /* Remove the descriptor from the per-context residency list. */
+ si_del_resident_descriptor(sctx, slab->buffer);
+
+ r600_resource_reference(&slab->buffer, NULL);
+ FREE(slab->entries);
+ FREE(slab);
+}
+
/* INIT/DEINIT/UPLOAD */

/* GFX9 has only 4KB of CE, while previous chips had 32KB. In order
diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c
index 8e55b807ce..5b1ddda321 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.c
+++ b/src/gallium/drivers/radeonsi/si_pipe.c
@@ -96,6 +96,9 @@ static void si_destroy_context(struct pipe_context *context)
r600_resource_reference(&sctx->last_trace_buf, NULL);
radeon_clear_saved_cs(&sctx->last_gfx);

+ pb_slabs_deinit(&sctx->resident_descriptor_slabs);
+
+ FREE(sctx->resident_descriptors);
FREE(sctx);
}

@@ -314,6 +317,13 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen,

sctx->tm = si_create_llvm_target_machine(sscreen);

+ /* Create a slab allocator for all resident descriptors. */
+ if (!pb_slabs_init(&sctx->resident_descriptor_slabs, 6, 6, 1, sctx,
+ si_resident_descriptor_can_reclaim_slab,
+ si_resident_descriptor_slab_alloc,
+ si_resident_descriptor_slab_free))
+ goto fail;
+
return &sctx->b.b;
fail:
fprintf(stderr, "radeonsi: Failed to create a context.\n");
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 13ec0729b1..41b0a2a79f 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -224,6 +224,13 @@ union si_vgt_param_key {
uint32_t index;
};

+struct si_resident_descriptor
+{
+ struct pb_slab_entry entry;
+ struct r600_resource *buffer;
+ unsigned offset;
+};
+
struct si_context {
struct r600_common_context b;
struct blitter_context *blitter;
@@ -384,6 +391,14 @@ struct si_context {
/* Precomputed IA_MULTI_VGT_PARAM */
union si_vgt_param_key ia_multi_vgt_param_key;
unsigned ia_multi_vgt_param[SI_NUM_VGT_PARAM_STATES];
+
+ /* Slab allocator for resident descriptors. */
+ struct pb_slabs resident_descriptor_slabs;
+
+ /* Resident descriptors. */
+ struct r600_resource **resident_descriptors;
+ unsigned num_resident_descriptors;
+ unsigned max_resident_descriptors;
};

/* cik_sdma.c */
diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h
index 275f830613..3e9016c84a 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -30,6 +30,8 @@
#include "si_pm4.h"
#include "radeon/r600_pipe_common.h"

+#include "pipebuffer/pb_slab.h"
+
#define SI_NUM_GRAPHICS_SHADERS (PIPE_SHADER_TESS_EVAL+1)
#define SI_NUM_SHADERS (PIPE_SHADER_COMPUTE+1)

@@ -335,6 +337,12 @@ void si_set_active_descriptors(struct si_context *sctx, unsigned desc_idx,
uint64_t new_active_mask);
void si_set_active_descriptors_for_shader(struct si_context *sctx,
struct si_shader_selector *sel);
+bool si_resident_descriptor_can_reclaim_slab(void *priv,
+ struct pb_slab_entry *entry);
+struct pb_slab *si_resident_descriptor_slab_alloc(void *priv, unsigned heap,
+ unsigned entry_size,
+ unsigned group_index);
+void si_resident_descriptor_slab_free(void *priv, struct pb_slab *pslab);

/* si_state.c */
struct si_shader_selector;
--
2.13.0
Marek Olšák
2017-05-26 14:39:30 UTC
Permalink
FYI, I've replied on some radeonsi patches and skimmed through the
rest without Rbs. I'll do another review once there is version 2.

Marek

On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
For each texture/image handles, we need to allocate a new
buffer for the resident descriptor. But when the number of
buffers added to the current CS becomes high, the overhead
in the winsys (and in the kernel) is important.
To reduce this bottleneck, the idea is to suballocate the
resident descriptors using a slab similar to the one used
in the winsys.
Currently, a buffer can hold 1024 resident descriptors but
this limit is arbitrary and could be changed in the future
for some reasons. Once a slab is allocated the "base" buffer
is added to a per-context residency list.
---
src/gallium/drivers/radeonsi/si_descriptors.c | 150 ++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_pipe.c | 10 ++
src/gallium/drivers/radeonsi/si_pipe.h | 15 +++
src/gallium/drivers/radeonsi/si_state.h | 8 ++
4 files changed, 183 insertions(+)
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 61eb2f10be..d337fc3f11 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -2005,6 +2005,156 @@ void si_emit_compute_shader_userdata(struct si_context *sctx)
sctx->shader_pointers_dirty &= ~compute_mask;
}
+/* BINDLESS */
+
+static int si_add_resident_descriptor(struct si_context *sctx,
+ struct r600_resource *desc)
+{
+ int idx;
+
+ /* New resident descriptor, check if the backing array is large enough. */
+ if (sctx->num_resident_descriptors >= sctx->max_resident_descriptors) {
+ unsigned new_max_descriptors =
+ MAX2(1, sctx->max_resident_descriptors * 2);
+ struct r600_resource **new_descriptors =
+ REALLOC(sctx->resident_descriptors,
+ sctx->num_resident_descriptors * (sizeof(*new_descriptors)),
+ new_max_descriptors * sizeof(*new_descriptors));
+
+ if (new_descriptors) {
+ sctx->resident_descriptors = new_descriptors;
+ sctx->max_resident_descriptors = new_max_descriptors;
+ } else {
+ fprintf(stderr, "si_add_resident_descriptor: "
+ "allocation failed\n");
+ return -1;
+ }
+ }
+
+ idx = sctx->num_resident_descriptors;
+ sctx->resident_descriptors[idx] = desc;
+ sctx->num_resident_descriptors++;
+
+ return 0;
+}
+
+static void si_del_resident_descriptor(struct si_context *sctx,
+ struct r600_resource *desc)
+{
+ unsigned i;
+ int size;
+
+ for (i = 0; i < sctx->num_resident_descriptors; i++) {
+ if (sctx->resident_descriptors[i] != desc)
+ continue;
+
+ if (i < sctx->num_resident_descriptors - 1) {
+ size = sizeof(*sctx->resident_descriptors) *
+ (sctx->num_resident_descriptors - 1 - i);
+
+ memmove(&sctx->resident_descriptors[i],
+ &sctx->resident_descriptors[i + 1], size);
+ }
+
+ sctx->num_resident_descriptors--;
+ return;
+ }
+}
+
+struct si_resident_descriptor_slab
+{
+ struct pb_slab base;
+ struct r600_resource *buffer;
+ struct si_resident_descriptor *entries;
+};
+
+bool si_resident_descriptor_can_reclaim_slab(void *priv,
+ struct pb_slab_entry *entry)
+{
+ struct si_context *sctx = priv;
+ struct radeon_winsys *ws = sctx->b.ws;
+ struct si_resident_descriptor *desc = NULL; /* fix container_of */
+
+ desc = container_of(entry, desc, entry);
+
+ if (ws->cs_is_buffer_referenced(sctx->b.gfx.cs, desc->buffer->buf,
+ RADEON_USAGE_READ)) {
+ /* Do not allow to reclaim the buffer if the resident
+ * descriptor is currently used.
+ */
+ return false;
+ }
+
+ return true;
+}
+
+struct pb_slab *si_resident_descriptor_slab_alloc(void *priv, unsigned heap,
+ unsigned entry_size,
+ unsigned group_index)
+{
+ struct si_context *sctx = priv;
+ struct si_screen *sscreen = sctx->screen;
+ struct si_resident_descriptor_slab *slab;
+
+ slab = CALLOC_STRUCT(si_resident_descriptor_slab);
+ if (!slab)
+ return NULL;
+
+ /* Create a buffer in VRAM for 1024 resident descriptors. */
+ slab->buffer = (struct r600_resource *)
+ pipe_buffer_create(&sscreen->b.b, 0,
+ PIPE_USAGE_IMMUTABLE, 64 * 1024);
+ if (!slab->buffer)
+ goto fail;
+
+ slab->base.num_entries = slab->buffer->bo_size / entry_size;
+ slab->base.num_free = slab->base.num_entries;
+ slab->entries = CALLOC(slab->base.num_entries, sizeof(*slab->entries));
+ if (!slab->entries)
+ goto fail_buffer;
+
+ LIST_INITHEAD(&slab->base.free);
+
+ for (unsigned i = 0; i < slab->base.num_entries; ++i) {
+ struct si_resident_descriptor *desc = &slab->entries[i];
+
+ desc->entry.slab = &slab->base;
+ desc->entry.group_index = group_index;
+ desc->buffer = slab->buffer;
+ desc->offset = i * entry_size;
+
+ LIST_ADDTAIL(&desc->entry.head, &slab->base.free);
+ }
+
+ /* Add the descriptor to the per-context residency list. */
+ if (si_add_resident_descriptor(sctx, slab->buffer))
+ goto fail_desc;
+
+ return &slab->base;
+
+ FREE(slab->entries);
+ r600_resource_reference(&slab->buffer, NULL);
+ FREE(slab);
+ return NULL;
+}
+
+void si_resident_descriptor_slab_free(void *priv, struct pb_slab *pslab)
+{
+ struct si_context *sctx = priv;
+ struct si_resident_descriptor_slab *slab =
+ (struct si_resident_descriptor_slab *)pslab;
+
+ /* Remove the descriptor from the per-context residency list. */
+ si_del_resident_descriptor(sctx, slab->buffer);
+
+ r600_resource_reference(&slab->buffer, NULL);
+ FREE(slab->entries);
+ FREE(slab);
+}
+
/* INIT/DEINIT/UPLOAD */
/* GFX9 has only 4KB of CE, while previous chips had 32KB. In order
diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c
index 8e55b807ce..5b1ddda321 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.c
+++ b/src/gallium/drivers/radeonsi/si_pipe.c
@@ -96,6 +96,9 @@ static void si_destroy_context(struct pipe_context *context)
r600_resource_reference(&sctx->last_trace_buf, NULL);
radeon_clear_saved_cs(&sctx->last_gfx);
+ pb_slabs_deinit(&sctx->resident_descriptor_slabs);
+
+ FREE(sctx->resident_descriptors);
FREE(sctx);
}
@@ -314,6 +317,13 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen,
sctx->tm = si_create_llvm_target_machine(sscreen);
+ /* Create a slab allocator for all resident descriptors. */
+ if (!pb_slabs_init(&sctx->resident_descriptor_slabs, 6, 6, 1, sctx,
+ si_resident_descriptor_can_reclaim_slab,
+ si_resident_descriptor_slab_alloc,
+ si_resident_descriptor_slab_free))
+ goto fail;
+
return &sctx->b.b;
fprintf(stderr, "radeonsi: Failed to create a context.\n");
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 13ec0729b1..41b0a2a79f 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -224,6 +224,13 @@ union si_vgt_param_key {
uint32_t index;
};
+struct si_resident_descriptor
+{
+ struct pb_slab_entry entry;
+ struct r600_resource *buffer;
+ unsigned offset;
+};
+
struct si_context {
struct r600_common_context b;
struct blitter_context *blitter;
@@ -384,6 +391,14 @@ struct si_context {
/* Precomputed IA_MULTI_VGT_PARAM */
union si_vgt_param_key ia_multi_vgt_param_key;
unsigned ia_multi_vgt_param[SI_NUM_VGT_PARAM_STATES];
+
+ /* Slab allocator for resident descriptors. */
+ struct pb_slabs resident_descriptor_slabs;
+
+ /* Resident descriptors. */
+ struct r600_resource **resident_descriptors;
+ unsigned num_resident_descriptors;
+ unsigned max_resident_descriptors;
};
/* cik_sdma.c */
diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h
index 275f830613..3e9016c84a 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -30,6 +30,8 @@
#include "si_pm4.h"
#include "radeon/r600_pipe_common.h"
+#include "pipebuffer/pb_slab.h"
+
#define SI_NUM_GRAPHICS_SHADERS (PIPE_SHADER_TESS_EVAL+1)
#define SI_NUM_SHADERS (PIPE_SHADER_COMPUTE+1)
@@ -335,6 +337,12 @@ void si_set_active_descriptors(struct si_context *sctx, unsigned desc_idx,
uint64_t new_active_mask);
void si_set_active_descriptors_for_shader(struct si_context *sctx,
struct si_shader_selector *sel);
+bool si_resident_descriptor_can_reclaim_slab(void *priv,
+ struct pb_slab_entry *entry);
+struct pb_slab *si_resident_descriptor_slab_alloc(void *priv, unsigned heap,
+ unsigned entry_size,
+ unsigned group_index);
+void si_resident_descriptor_slab_free(void *priv, struct pb_slab *pslab);
/* si_state.c */
struct si_shader_selector;
--
2.13.0
_______________________________________________
mesa-dev mailing list
https://lists.freedesktop.org/mailman/listinfo/mesa-dev
Samuel Pitoiset
2017-05-19 16:52:51 UTC
Permalink
The ARB_bindless_texture spec say:

"If ARB_seamless_cubemap (or OpenGL 4.0, which includes it) is
supported, the per-context seamless cubemap enable is ignored
and treated as disabled when using texture handles."

"If AMD_seamless_cubemap_per_texture is supported, the seamless
cube map texture parameter of the underlying texture does apply
when texture handles are used."

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_atom_sampler.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c
index c6d992fbb0..116c5380cf 100644
--- a/src/mesa/state_tracker/st_atom_sampler.c
+++ b/src/mesa/state_tracker/st_atom_sampler.c
@@ -226,8 +226,22 @@ st_convert_sampler(const struct st_context *st,
sampler->compare_func = st_compare_func_to_pipe(msamp->CompareFunc);
}

- sampler->seamless_cube_map =
- ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless;
+ if (msamp->HandleAllocated) {
+ /* The ARB_bindless_texture spec says:
+ *
+ * "If ARB_seamless_cubemap (or OpenGL 4.0, which includes it) is
+ * supported, the per-context seamless cubemap enable is ignored and
+ * treated as disabled when using texture handles."
+ *
+ * "If AMD_seamless_cubemap_per_texture is supported, the seamless cube
+ * map texture parameter of the underlying texture does apply when
+ * texture handles are used."
+ */
+ sampler->seamless_cube_map = msamp->CubeMapSeamless;
+ } else {
+ sampler->seamless_cube_map =
+ ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless;
+ }
}

/**
--
2.13.0
Samuel Pitoiset
2017-05-19 16:53:08 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c b/src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c
index bd8ecb70f8..c9397c2fb8 100644
--- a/src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c
+++ b/src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c
@@ -1207,6 +1207,20 @@ static void tex_fetch_ptrs(
si_get_sampler_slot(reg->Register.Index), 0);
}

+ if (reg->Register.File != TGSI_FILE_SAMPLER) {
+ struct gallivm_state *gallivm = &ctx->gallivm;
+ LLVMBuilderRef builder = gallivm->builder;
+
+ assert(inst->Texture.Bindless);
+
+ LLVMValueRef ptr =
+ lp_build_emit_fetch_src(bld_base, reg,
+ TGSI_TYPE_UNSIGNED64, 0);
+ list = LLVMBuildIntToPtr(builder, ptr,
+ si_const_array(ctx->v8i32, 0), "");
+ index = LLVMConstInt(ctx->i32, 0, 0);
+ }
+
if (target == TGSI_TEXTURE_BUFFER)
*res_ptr = load_sampler_desc(ctx, list, index, DESC_BUFFER);
else
@@ -1786,7 +1800,8 @@ static void build_tex_intrinsic(const struct lp_build_tgsi_action *action,
opcode == TGSI_OPCODE_TG4) {
const unsigned src_idx = 2;

- assert(inst->Src[src_idx].Register.File == TGSI_FILE_SAMPLER);
+ assert(inst->Src[src_idx].Register.File == TGSI_FILE_SAMPLER ||
+ inst->Texture.Bindless);
assert(inst->Texture.ReturnType != TGSI_RETURN_TYPE_UNKNOWN);

if (inst->Texture.ReturnType == TGSI_RETURN_TYPE_SINT ||
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:50 UTC
Permalink
This post might be inappropriate. Click to display it.
Marek Olšák
2017-05-23 20:11:45 UTC
Permalink
I don't think this change is necessary. Releasing sampler views
doesn't release textures.

Marek

On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
When a texture is referenced by one or more texture handles,
it might be resident and we shouldn't release the sampler views.
---
src/mesa/state_tracker/st_sampler_view.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/mesa/state_tracker/st_sampler_view.c b/src/mesa/state_tracker/st_sampler_view.c
index c78a987486..690b50087c 100644
--- a/src/mesa/state_tracker/st_sampler_view.c
+++ b/src/mesa/state_tracker/st_sampler_view.c
@@ -115,6 +115,12 @@ st_texture_release_all_sampler_views(struct st_context *st,
{
GLuint i;
+ if (stObj->base.HandleAllocated) {
+ /* Do not release sampler views when a texture is referenced by one or
+ * more texture handles because the texture might be resident. */
+ return;
+ }
+
/* XXX This should use sampler_views[i]->pipe, not st->pipe */
for (i = 0; i < stObj->num_sampler_views; ++i)
pipe_sampler_view_release(st->pipe, &stObj->sampler_views[i]);
--
2.13.0
_______________________________________________
mesa-dev mailing list
https://lists.freedesktop.org/mailman/listinfo/mesa-dev
Samuel Pitoiset
2017-05-24 08:50:15 UTC
Permalink
Post by Marek Olšák
I don't think this change is necessary. Releasing sampler views
doesn't release textures.
This issued has been reported by Feral directly. It happens in the
following scenario:

1) create a texture
2) get a texture handle
3) make it resident
4) bind the texture to a unit
5) draw

The sampler views are then released and this ended up with a
use-after-free at decompression time for the resident texture handle.
Post by Marek Olšák
Marek
On Fri, May 19, 2017 at 6:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
When a texture is referenced by one or more texture handles,
it might be resident and we shouldn't release the sampler views.
---
src/mesa/state_tracker/st_sampler_view.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/mesa/state_tracker/st_sampler_view.c b/src/mesa/state_tracker/st_sampler_view.c
index c78a987486..690b50087c 100644
--- a/src/mesa/state_tracker/st_sampler_view.c
+++ b/src/mesa/state_tracker/st_sampler_view.c
@@ -115,6 +115,12 @@ st_texture_release_all_sampler_views(struct st_context *st,
{
GLuint i;
+ if (stObj->base.HandleAllocated) {
+ /* Do not release sampler views when a texture is referenced by one or
+ * more texture handles because the texture might be resident. */
+ return;
+ }
+
/* XXX This should use sampler_views[i]->pipe, not st->pipe */
for (i = 0; i < stObj->num_sampler_views; ++i)
pipe_sampler_view_release(st->pipe, &stObj->sampler_views[i]);
--
2.13.0
_______________________________________________
mesa-dev mailing list
https://lists.freedesktop.org/mailman/listinfo/mesa-dev
Samuel Pitoiset
2017-05-19 16:53:04 UTC
Permalink
This adds some new helper functions to know if the current draw
call (or dispatch compute) is using bindless samplers/images,
based on TGSI analysis.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_compute.c | 2 ++
src/gallium/drivers/radeonsi/si_compute.h | 14 ++++++++++++++
src/gallium/drivers/radeonsi/si_pipe.h | 20 ++++++++++++++++++++
src/gallium/drivers/radeonsi/si_shader.h | 12 ++++++++++++
4 files changed, 48 insertions(+)

diff --git a/src/gallium/drivers/radeonsi/si_compute.c b/src/gallium/drivers/radeonsi/si_compute.c
index 4c980668d3..61fab7ddb0 100644
--- a/src/gallium/drivers/radeonsi/si_compute.c
+++ b/src/gallium/drivers/radeonsi/si_compute.c
@@ -108,6 +108,8 @@ static void si_create_compute_state_async(void *job, int thread_index)
program->shader.is_monolithic = true;
program->uses_grid_size = sel.info.uses_grid_size;
program->uses_block_size = sel.info.uses_block_size;
+ program->uses_bindless_samplers = sel.info.uses_bindless_samplers;
+ program->uses_bindless_images = sel.info.uses_bindless_images;

if (si_shader_create(program->screen, tm, &program->shader, debug)) {
program->shader.compilation_failed = true;
diff --git a/src/gallium/drivers/radeonsi/si_compute.h b/src/gallium/drivers/radeonsi/si_compute.h
index 764d708c4f..3cf1538267 100644
--- a/src/gallium/drivers/radeonsi/si_compute.h
+++ b/src/gallium/drivers/radeonsi/si_compute.h
@@ -49,6 +49,20 @@ struct si_compute {
unsigned variable_group_size : 1;
unsigned uses_grid_size:1;
unsigned uses_block_size:1;
+ unsigned uses_bindless_samplers:1;
+ unsigned uses_bindless_images:1;
};

+static inline bool
+si_compute_uses_bindless_samplers(struct si_context *sctx)
+{
+ return sctx->cs_shader_state.program->uses_bindless_samplers;
+}
+
+static inline bool
+si_compute_uses_bindless_images(struct si_context *sctx)
+{
+ return sctx->cs_shader_state.program->uses_bindless_images;
+}
+
#endif /* SI_COMPUTE_H */
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 8d8efbda1f..c52b364959 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -544,6 +544,26 @@ static inline struct tgsi_shader_info *si_get_vs_info(struct si_context *sctx)
return NULL;
}

+static inline bool
+si_graphics_uses_bindless_samplers(struct si_context *sctx)
+{
+ return si_shader_uses_bindless_samplers(sctx->vs_shader.cso) ||
+ si_shader_uses_bindless_samplers(sctx->gs_shader.cso) ||
+ si_shader_uses_bindless_samplers(sctx->ps_shader.cso) ||
+ si_shader_uses_bindless_samplers(sctx->tcs_shader.cso) ||
+ si_shader_uses_bindless_samplers(sctx->tes_shader.cso);
+}
+
+static inline bool
+si_graphics_uses_bindless_images(struct si_context *sctx)
+{
+ return si_shader_uses_bindless_images(sctx->vs_shader.cso) ||
+ si_shader_uses_bindless_images(sctx->gs_shader.cso) ||
+ si_shader_uses_bindless_images(sctx->ps_shader.cso) ||
+ si_shader_uses_bindless_images(sctx->tcs_shader.cso) ||
+ si_shader_uses_bindless_images(sctx->tes_shader.cso);
+}
+
static inline struct si_shader* si_get_vs_state(struct si_context *sctx)
{
if (sctx->gs_shader.current)
diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h
index aab902b4c7..87bbbf9c2a 100644
--- a/src/gallium/drivers/radeonsi/si_shader.h
+++ b/src/gallium/drivers/radeonsi/si_shader.h
@@ -622,4 +622,16 @@ si_get_main_shader_part(struct si_shader_selector *sel,
return &sel->main_shader_part;
}

+static inline bool
+si_shader_uses_bindless_samplers(struct si_shader_selector *selector)
+{
+ return selector ? selector->info.uses_bindless_samplers : false;
+}
+
+static inline bool
+si_shader_uses_bindless_images(struct si_shader_selector *selector)
+{
+ return selector ? selector->info.uses_bindless_images : false;
+}
+
#endif
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:59 UTC
Permalink
This won't help much except for applications that use a ton
of resident handles. Though, this will reduce the winsys
overhead a little bit.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_descriptors.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 12f7ead619..44a4b16712 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -2531,6 +2531,11 @@ void si_all_resident_buffers_begin_new_cs(struct si_context *sctx)
{
unsigned i;

+ /* Skip adding the resident descriptors when no handles are resident.
+ */
+ if (!sctx->num_resident_tex_handles && !sctx->num_resident_img_handles)
+ return;
+
/* Add all resident descriptors. */
for (i = 0; i < sctx->num_resident_descriptors; i++) {
struct r600_resource *desc = sctx->resident_descriptors[i];
--
2.13.0
Samuel Pitoiset
2017-05-19 16:53:07 UTC
Permalink
When a buffer becomes resident, check if it has been invalidated,
if so update the descriptor and the dirty flag.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_descriptors.c | 34 +++++++++++++++++++++++++++
1 file changed, 34 insertions(+)

diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 6adad06757..0866c54c23 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -2419,6 +2419,32 @@ si_create_resident_descriptor(struct si_context *sctx, uint32_t *desc_list,
return desc;
}

+static void si_invalidate_resident_buf_desc(struct si_context *sctx,
+ struct si_resident_descriptor *desc,
+ struct pipe_resource *resource,
+ uint64_t offset)
+{
+ struct r600_resource *buf = r600_resource(resource);
+ uint32_t *desc_list = desc->desc_list;
+ uint64_t old_desc_va;
+
+ assert(resource->target == PIPE_BUFFER);
+
+ /* Retrieve the old buffer addr from the descriptor. */
+ old_desc_va = desc_list[0];
+ old_desc_va |= ((uint64_t)G_008F04_BASE_ADDRESS_HI(desc_list[1]) << 32);
+
+ if (old_desc_va != buf->gpu_address + offset) {
+ /* The buffer has been invalidated when the handle wasn't
+ * resident, update the descriptor and the dirty flag.
+ */
+ si_set_buf_desc_address(buf, offset, &desc_list[4]);
+
+ desc->dirty = true;
+ sctx->resident_descriptors_dirty = true;
+ }
+}
+
static uint64_t si_create_texture_handle(struct pipe_context *ctx,
struct pipe_resource *texture,
struct pipe_sampler_view *view,
@@ -2515,6 +2541,10 @@ static void si_make_texture_handle_resident(struct pipe_context *ctx,
is_compressed_colortex(rtex);

si_update_check_render_feedback(sctx, rtex);
+ } else {
+ si_invalidate_resident_buf_desc(sctx, tex_handle->desc,
+ sview->base.texture,
+ sview->base.u.buf.offset);
}

si_add_resident_tex_handle(sctx, tex_handle);
@@ -2624,6 +2654,10 @@ static void si_make_image_handle_resident(struct pipe_context *ctx,
is_compressed_colortex(rtex);

si_update_check_render_feedback(sctx, rtex);
+ } else {
+ si_invalidate_resident_buf_desc(sctx, img_handle->desc,
+ view->resource,
+ view->u.buf.offset);
}

si_add_resident_img_handle(sctx, img_handle);
--
2.13.0
Samuel Pitoiset
2017-05-19 16:53:05 UTC
Permalink
When current bound shaders don't use any bindless textures or
images, we shouldn't try to decompress the resident resources.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_blit.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c
index 0cf3ea79b9..299a52a0da 100644
--- a/src/gallium/drivers/radeonsi/si_blit.c
+++ b/src/gallium/drivers/radeonsi/si_blit.c
@@ -773,8 +773,10 @@ void si_decompress_graphics_textures(struct si_context *sctx)

si_decompress_textures(sctx, u_bit_consecutive(0, SI_NUM_GRAPHICS_SHADERS));

- si_decompress_resident_textures(sctx);
- si_decompress_resident_images(sctx);
+ if (si_graphics_uses_bindless_samplers(sctx))
+ si_decompress_resident_textures(sctx);
+ if (si_graphics_uses_bindless_images(sctx))
+ si_decompress_resident_images(sctx);
}

void si_decompress_compute_textures(struct si_context *sctx)
@@ -784,8 +786,10 @@ void si_decompress_compute_textures(struct si_context *sctx)

si_decompress_textures(sctx, 1 << PIPE_SHADER_COMPUTE);

- si_decompress_resident_textures(sctx);
- si_decompress_resident_images(sctx);
+ if (si_compute_uses_bindless_samplers(sctx))
+ si_decompress_resident_textures(sctx);
+ if (si_compute_uses_bindless_images(sctx))
+ si_decompress_resident_images(sctx);
}

static void si_clear(struct pipe_context *ctx, unsigned buffers,
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:58 UTC
Permalink
Resident buffers have to be added to every new command stream.
Though, this could be slightly improved when current shaders
don't use any bindless textures/images but usually applications
tend to use bindless for almost every draw call, and the winsys
thread might help when buffers are added early.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_descriptors.c | 36 +++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_hw_context.c | 1 +
src/gallium/drivers/radeonsi/si_state.h | 1 +
3 files changed, 38 insertions(+)

diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index a687506f7f..12f7ead619 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -2527,6 +2527,42 @@ static void si_make_image_handle_resident(struct pipe_context *ctx,
}


+void si_all_resident_buffers_begin_new_cs(struct si_context *sctx)
+{
+ unsigned i;
+
+ /* Add all resident descriptors. */
+ for (i = 0; i < sctx->num_resident_descriptors; i++) {
+ struct r600_resource *desc = sctx->resident_descriptors[i];
+
+ radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx, desc,
+ RADEON_USAGE_READ,
+ RADEON_PRIO_DESCRIPTORS);
+ }
+
+ /* Add all resident texture handles. */
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ struct si_texture_handle *tex_handle =
+ sctx->resident_tex_handles[i];
+ struct si_sampler_view *sview = tex_handle->view;
+
+ si_sampler_view_add_buffer(sctx, sview->base.texture,
+ RADEON_USAGE_READ,
+ sview->is_stencil_sampler, false);
+ }
+
+ /* Add all resident image handles. */
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ struct si_image_handle *img_handle =
+ sctx->resident_img_handles[i];
+ struct pipe_image_view *view = &img_handle->view;
+
+ si_sampler_view_add_buffer(sctx, view->resource,
+ RADEON_USAGE_READWRITE,
+ false, false);
+ }
+}
+
/* INIT/DEINIT/UPLOAD */

/* GFX9 has only 4KB of CE, while previous chips had 32KB. In order
diff --git a/src/gallium/drivers/radeonsi/si_hw_context.c b/src/gallium/drivers/radeonsi/si_hw_context.c
index 92c09cb633..345825af00 100644
--- a/src/gallium/drivers/radeonsi/si_hw_context.c
+++ b/src/gallium/drivers/radeonsi/si_hw_context.c
@@ -235,6 +235,7 @@ void si_begin_new_cs(struct si_context *ctx)
si_mark_atom_dirty(ctx, &ctx->b.streamout.enable_atom);
si_mark_atom_dirty(ctx, &ctx->b.render_cond_atom);
si_all_descriptors_begin_new_cs(ctx);
+ si_all_resident_buffers_begin_new_cs(ctx);

ctx->b.scissors.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
ctx->b.viewports.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h
index 3e9016c84a..e46af570d4 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -323,6 +323,7 @@ bool si_upload_graphics_shader_descriptors(struct si_context *sctx);
bool si_upload_compute_shader_descriptors(struct si_context *sctx);
void si_release_all_descriptors(struct si_context *sctx);
void si_all_descriptors_begin_new_cs(struct si_context *sctx);
+void si_all_resident_buffers_begin_new_cs(struct si_context *sctx);
void si_upload_const_buffer(struct si_context *sctx, struct r600_resource **rbuffer,
const uint8_t *ptr, unsigned size, uint32_t *const_offset);
void si_update_all_texture_descriptors(struct si_context *sctx);
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:41 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index ee1afdcd08..c69eefe013 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -4797,6 +4797,12 @@ glsl_to_tgsi_visitor::rename_temp_registers(int num_renames, struct rename_reg_p
inst->tex_offsets[j].index = renames[k].new_reg;
}

+ if (inst->resource.file == PROGRAM_TEMPORARY) {
+ for (k = 0; k < num_renames; k++)
+ if (inst->resource.index == renames[k].old_reg)
+ inst->resource.index = renames[k].new_reg;
+ }
+
for (j = 0; j < num_inst_dst_regs(inst); j++) {
if (inst->dst[j].file == PROGRAM_TEMPORARY)
for (k = 0; k < num_renames; k++)
--
2.13.0
Samuel Pitoiset
2017-05-19 16:53:06 UTC
Permalink
When texture buffers are invalidated the addr in the resident
descriptor has to be updated but we can't create a new descriptor
because the resident handle has to be the same.

Instead, use the WRITE_DATA packet which allows to update memory
directly but graphics/compute have to be idle in case the GPU is
reading the descriptor.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeon/r600_pipe_common.h | 4 +
src/gallium/drivers/radeonsi/si_descriptors.c | 121 ++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_pipe.h | 3 +
3 files changed, 128 insertions(+)

diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index b17b690fab..6c4df2e733 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -181,6 +181,10 @@ struct r600_resource {

/* Whether the resource has been exported via resource_get_handle. */
unsigned external_usage; /* PIPE_HANDLE_USAGE_* */
+
+ /* Whether this resource is referenced by bindless handles. */
+ bool texture_handle_allocated;
+ bool image_handle_allocated;
};

struct r600_transfer {
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 05559d90d7..6adad06757 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -1849,6 +1849,55 @@ static void si_rebind_buffer(struct pipe_context *ctx, struct pipe_resource *buf
}
}
}
+
+ /* Bindless texture handles */
+ if (rbuffer->texture_handle_allocated) {
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ struct si_texture_handle *tex_handle =
+ sctx->resident_tex_handles[i];
+ struct si_sampler_view *sview = tex_handle->view;
+ struct si_resident_descriptor *desc = tex_handle->desc;
+
+ if (sview->base.texture == buf) {
+ si_set_buf_desc_address(rbuffer,
+ sview->base.u.buf.offset,
+ &desc->desc_list[4]);
+ desc->dirty = true;
+ sctx->resident_descriptors_dirty = true;
+
+ radeon_add_to_buffer_list_check_mem(
+ &sctx->b, &sctx->b.gfx, rbuffer,
+ RADEON_USAGE_READ,
+ RADEON_PRIO_SAMPLER_BUFFER, true);
+ }
+ }
+ }
+
+ /* Bindless image handles */
+ if (rbuffer->image_handle_allocated) {
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ struct si_image_handle *img_handle =
+ sctx->resident_img_handles[i];
+ struct pipe_image_view *view = &img_handle->view;
+ struct si_resident_descriptor *desc = img_handle->desc;
+
+ if (view->resource == buf) {
+ if (view->access & PIPE_IMAGE_ACCESS_WRITE)
+ si_mark_image_range_valid(view);
+
+ si_set_buf_desc_address(rbuffer,
+ view->u.buf.offset,
+ &desc->desc_list[4]);
+ desc->dirty = true;
+ sctx->resident_descriptors_dirty = true;
+
+ radeon_add_to_buffer_list_check_mem(
+ &sctx->b, &sctx->b.gfx, rbuffer,
+ RADEON_USAGE_READWRITE,
+ RADEON_PRIO_SAMPLER_BUFFER, true);
+ }
+ }
+ }
}

/* Reallocate a buffer a update all resource bindings where the buffer is
@@ -2365,6 +2414,8 @@ si_create_resident_descriptor(struct si_context *sctx, uint32_t *desc_list,
util_memcpy_cpu_to_le32(ptr + desc->offset, desc_list, size);
sscreen->b.ws->buffer_unmap(desc->buffer->buf);

+ memcpy(desc->desc_list, desc_list, sizeof(desc->desc_list));
+
return desc;
}

@@ -2415,6 +2466,8 @@ static uint64_t si_create_texture_handle(struct pipe_context *ctx,
return 0;
}

+ r600_resource(sview->base.texture)->texture_handle_allocated = true;
+
return handle;
}

@@ -2521,6 +2574,8 @@ static uint64_t si_create_image_handle(struct pipe_context *ctx,
return 0;
}

+ r600_resource(view->resource)->image_handle_allocated = true;
+
return handle;
}

@@ -2800,6 +2855,67 @@ void si_init_all_descriptors(struct si_context *sctx)
si_set_user_data_base(sctx, PIPE_SHADER_FRAGMENT, R_00B030_SPI_SHADER_USER_DATA_PS_0);
}

+static void si_upload_resident_descriptor(struct si_context *sctx,
+ struct si_resident_descriptor *desc)
+{
+ struct radeon_winsys_cs *cs = sctx->b.gfx.cs;
+ uint64_t va = desc->buffer->gpu_address + desc->offset;
+ unsigned num_dwords = sizeof(desc->desc_list) / 4;
+
+ radeon_emit(cs, PKT3(PKT3_WRITE_DATA, 2 + num_dwords, 0));
+ radeon_emit(cs, S_370_DST_SEL(V_370_TC_L2) |
+ S_370_WR_CONFIRM(1) |
+ S_370_ENGINE_SEL(V_370_PFP));
+ radeon_emit(cs, va);
+ radeon_emit(cs, va >> 32);
+ radeon_emit_array(cs, desc->desc_list, num_dwords);
+}
+
+static void si_upload_resident_descriptors(struct si_context *sctx)
+{
+ unsigned i;
+
+ if (!sctx->resident_descriptors_dirty)
+ return;
+
+ /* Wait for graphics/compute to be idle before updating the resident
+ * descriptors directly in memory, in case the GPU is using them.
+ */
+ sctx->b.flags |= SI_CONTEXT_PS_PARTIAL_FLUSH;
+ sctx->b.flags |= SI_CONTEXT_CS_PARTIAL_FLUSH;
+ si_emit_cache_flush(sctx);
+
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ struct si_texture_handle *tex_handle =
+ sctx->resident_tex_handles[i];
+ struct si_resident_descriptor *desc = tex_handle->desc;
+
+ if (!desc->dirty)
+ continue;
+
+ si_upload_resident_descriptor(sctx, desc);
+ desc->dirty = false;
+ }
+
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ struct si_image_handle *img_handle =
+ sctx->resident_img_handles[i];
+ struct si_resident_descriptor *desc = img_handle->desc;
+
+ if (!desc->dirty)
+ continue;
+
+ si_upload_resident_descriptor(sctx, desc);
+ desc->dirty = false;
+ }
+
+ /* Invalidate L1 because it doesn't know that L2 changed. */
+ sctx->b.flags |= SI_CONTEXT_INV_SMEM_L1;
+ si_emit_cache_flush(sctx);
+
+ sctx->resident_descriptors_dirty = false;
+}
+
bool si_upload_graphics_shader_descriptors(struct si_context *sctx)
{
const unsigned mask = u_bit_consecutive(0, SI_DESCS_FIRST_COMPUTE);
@@ -2817,6 +2933,9 @@ bool si_upload_graphics_shader_descriptors(struct si_context *sctx)
}

sctx->descriptors_dirty &= ~mask;
+
+ si_upload_resident_descriptors(sctx);
+
return true;
}

@@ -2841,6 +2960,8 @@ bool si_upload_compute_shader_descriptors(struct si_context *sctx)

sctx->descriptors_dirty &= ~mask;

+ si_upload_resident_descriptors(sctx);
+
return true;
}

diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index c52b364959..f15881c51f 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -229,6 +229,8 @@ struct si_resident_descriptor
struct pb_slab_entry entry;
struct r600_resource *buffer;
unsigned offset;
+ uint32_t desc_list[16];
+ bool dirty;
};

struct si_texture_handle
@@ -415,6 +417,7 @@ struct si_context {
struct r600_resource **resident_descriptors;
unsigned num_resident_descriptors;
unsigned max_resident_descriptors;
+ bool resident_descriptors_dirty;

/* Allocatd bindless handles */
struct hash_table *tex_handles;
--
2.13.0
Samuel Pitoiset
2017-05-19 16:53:02 UTC
Permalink
Similar to the existing decompression code path except that it
loops over the list of resident textures/images.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_blit.c | 67 +++++++++++++++++++++++++--
src/gallium/drivers/radeonsi/si_descriptors.c | 44 ++++++++++++++++++
src/gallium/drivers/radeonsi/si_pipe.h | 3 ++
3 files changed, 111 insertions(+), 3 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c
index 4078f2498b..32041695e2 100644
--- a/src/gallium/drivers/radeonsi/si_blit.c
+++ b/src/gallium/drivers/radeonsi/si_blit.c
@@ -22,6 +22,7 @@
*/

#include "si_pipe.h"
+#include "si_compute.h"
#include "util/u_format.h"
#include "util/u_surface.h"

@@ -680,9 +681,6 @@ static void si_decompress_textures(struct si_context *sctx, unsigned shader_mask
{
unsigned compressed_colortex_counter, mask;

- if (sctx->blitter->running)
- return;
-
/* Update the compressed_colortex_mask if necessary. */
compressed_colortex_counter = p_atomic_read(&sctx->screen->b.compressed_colortex_counter);
if (compressed_colortex_counter != sctx->b.last_compressed_colortex_counter) {
@@ -709,14 +707,77 @@ static void si_decompress_textures(struct si_context *sctx, unsigned shader_mask
si_check_render_feedback(sctx);
}

+static void si_decompress_resident_textures(struct si_context *sctx)
+{
+ unsigned i;
+
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ struct si_texture_handle *tex_handle =
+ sctx->resident_tex_handles[i];
+ struct si_sampler_view *sview = tex_handle->view;
+ struct pipe_sampler_view *view = &sview->base;
+ struct r600_texture *tex;
+
+ assert(view);
+ tex = (struct r600_texture *)view->texture;
+
+ if (view->texture->target == PIPE_BUFFER)
+ continue;
+
+ if (tex_handle->compressed_colortex)
+ si_decompress_color_texture(sctx, tex, view->u.tex.first_level,
+ view->u.tex.last_level);
+
+ if (tex_handle->depth_texture)
+ si_flush_depth_texture(sctx, tex,
+ sview->is_stencil_sampler ? PIPE_MASK_S : PIPE_MASK_Z,
+ view->u.tex.first_level, view->u.tex.last_level,
+ 0, util_max_layer(&tex->resource.b.b, view->u.tex.first_level));
+ }
+}
+
+static void si_decompress_resident_images(struct si_context *sctx)
+{
+ unsigned i;
+
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ struct si_image_handle *img_handle =
+ sctx->resident_img_handles[i];
+ struct pipe_image_view *view = &img_handle->view;
+ struct r600_texture *tex;
+
+ assert(view);
+ tex = (struct r600_texture *)view->resource;
+
+ if (view->resource->target == PIPE_BUFFER)
+ continue;
+
+ if (img_handle->compressed_colortex)
+ si_decompress_color_texture(sctx, tex, view->u.tex.level,
+ view->u.tex.level);
+ }
+}
+
void si_decompress_graphics_textures(struct si_context *sctx)
{
+ if (sctx->blitter->running)
+ return;
+
si_decompress_textures(sctx, u_bit_consecutive(0, SI_NUM_GRAPHICS_SHADERS));
+
+ si_decompress_resident_textures(sctx);
+ si_decompress_resident_images(sctx);
}

void si_decompress_compute_textures(struct si_context *sctx)
{
+ if (sctx->blitter->running)
+ return;
+
si_decompress_textures(sctx, 1 << PIPE_SHADER_COMPUTE);
+
+ si_decompress_resident_textures(sctx);
+ si_decompress_resident_images(sctx);
}

static void si_clear(struct pipe_context *ctx, unsigned buffers,
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index e459f19d66..05559d90d7 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -1624,6 +1624,40 @@ static void si_set_polygon_stipple(struct pipe_context *ctx,

/* TEXTURE METADATA ENABLE/DISABLE */

+static void
+si_resident_handles_update_compressed_colortex(struct si_context *sctx)
+{
+ unsigned i;
+
+ for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+ struct si_texture_handle *tex_handle =
+ sctx->resident_tex_handles[i];
+ struct si_sampler_view *sview = tex_handle->view;
+ struct pipe_resource *res = sview->base.texture;
+
+ if (res && res->target != PIPE_BUFFER) {
+ struct r600_texture *rtex = (struct r600_texture *)res;
+
+ tex_handle->compressed_colortex =
+ is_compressed_colortex(rtex);
+ }
+ }
+
+ for (i = 0; i < sctx->num_resident_img_handles; i++) {
+ struct si_image_handle *img_handle =
+ sctx->resident_img_handles[i];
+ struct pipe_image_view *view = &img_handle->view;
+ struct pipe_resource *res = view->resource;
+
+ if (res && res->target != PIPE_BUFFER) {
+ struct r600_texture *rtex = (struct r600_texture *)res;
+
+ img_handle->compressed_colortex =
+ is_compressed_colortex(rtex);
+ }
+ }
+}
+
/* CMASK can be enabled (for fast clear) and disabled (for texture export)
* while the texture is bound, possibly by a different context. In that case,
* call this function to update compressed_colortex_masks.
@@ -1635,6 +1669,8 @@ void si_update_compressed_colortex_masks(struct si_context *sctx)
si_images_update_compressed_colortex_mask(&sctx->images[i]);
si_update_compressed_tex_shader_mask(sctx, i);
}
+
+ si_resident_handles_update_compressed_colortex(sctx);
}

/* BUFFER DISCARD/INVALIDATION */
@@ -2420,6 +2456,11 @@ static void si_make_texture_handle_resident(struct pipe_context *ctx,
struct r600_texture *rtex =
(struct r600_texture *)sview->base.texture;

+ tex_handle->depth_texture =
+ depth_needs_decompression(rtex, sview);
+ tex_handle->compressed_colortex =
+ is_compressed_colortex(rtex);
+
si_update_check_render_feedback(sctx, rtex);
}

@@ -2524,6 +2565,9 @@ static void si_make_image_handle_resident(struct pipe_context *ctx,
if (res->b.b.target != PIPE_BUFFER) {
struct r600_texture *rtex = (struct r600_texture *)res;

+ img_handle->compressed_colortex =
+ is_compressed_colortex(rtex);
+
si_update_check_render_feedback(sctx, rtex);
}

diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 3a2487bff0..7dafa77c37 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -235,12 +235,15 @@ struct si_texture_handle
{
struct si_resident_descriptor *desc;
struct si_sampler_view *view;
+ bool compressed_colortex;
+ bool depth_texture;
};

struct si_image_handle
{
struct si_resident_descriptor *desc;
struct pipe_image_view view;
+ bool compressed_colortex;
};

struct si_context {
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:55 UTC
Permalink
To share some common code between bound and bindless textures.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/drivers/radeonsi/si_descriptors.c | 95 +++++++++++++++------------
1 file changed, 52 insertions(+), 43 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index b2fe6a3de7..e73dbc9f9f 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -488,6 +488,54 @@ void si_set_mutable_tex_desc_fields(struct si_screen *sscreen,
}
}

+static void si_set_sampler_view_desc(struct si_context *sctx,
+ struct si_sampler_view *sview,
+ struct si_sampler_state *sstate,
+ uint32_t *desc)
+{
+ struct pipe_sampler_view *view = &sview->base;
+ struct r600_texture *rtex = (struct r600_texture *)view->texture;
+ bool is_buffer = rtex->resource.b.b.target == PIPE_BUFFER;
+
+ if (unlikely(!is_buffer && sview->dcc_incompatible)) {
+ if (vi_dcc_enabled(rtex, view->u.tex.first_level))
+ if (!r600_texture_disable_dcc(&sctx->b, rtex))
+ sctx->b.decompress_dcc(&sctx->b.b, rtex);
+
+ sview->dcc_incompatible = false;
+ }
+
+ assert(rtex); /* views with texture == NULL aren't supported */
+ memcpy(desc, sview->state, 8*4);
+
+ if (is_buffer) {
+ si_set_buf_desc_address(&rtex->resource,
+ sview->base.u.buf.offset,
+ desc + 4);
+ } else {
+ bool is_separate_stencil = rtex->db_compatible &&
+ sview->is_stencil_sampler;
+
+ si_set_mutable_tex_desc_fields(sctx->screen, rtex,
+ sview->base_level_info,
+ sview->base_level,
+ sview->base.u.tex.first_level,
+ sview->block_width,
+ is_separate_stencil,
+ desc);
+ }
+
+ if (!is_buffer && rtex->fmask.size) {
+ memcpy(desc + 8, sview->fmask_state, 8*4);
+ } else {
+ /* Disable FMASK and bind sampler state in [12:15]. */
+ memcpy(desc + 8, null_texture_descriptor, 4*4);
+
+ if (sstate)
+ memcpy(desc + 12, sstate->val, 4*4);
+ }
+}
+
static void si_set_sampler_view(struct si_context *sctx,
unsigned shader,
unsigned slot, struct pipe_sampler_view *view,
@@ -504,53 +552,14 @@ static void si_set_sampler_view(struct si_context *sctx,

if (view) {
struct r600_texture *rtex = (struct r600_texture *)view->texture;
- bool is_buffer = rtex->resource.b.b.target == PIPE_BUFFER;
-
- if (unlikely(!is_buffer && rview->dcc_incompatible)) {
- if (vi_dcc_enabled(rtex, view->u.tex.first_level))
- if (!r600_texture_disable_dcc(&sctx->b, rtex))
- sctx->b.decompress_dcc(&sctx->b.b, rtex);

- rview->dcc_incompatible = false;
- }
+ si_set_sampler_view_desc(sctx, rview,
+ views->sampler_states[slot], desc);

- assert(rtex); /* views with texture == NULL aren't supported */
- pipe_sampler_view_reference(&views->views[slot], view);
- memcpy(desc, rview->state, 8*4);
-
- if (is_buffer) {
+ if (rtex->resource.b.b.target == PIPE_BUFFER)
rtex->resource.bind_history |= PIPE_BIND_SAMPLER_VIEW;

- si_set_buf_desc_address(&rtex->resource,
- view->u.buf.offset,
- desc + 4);
- } else {
- bool is_separate_stencil =
- rtex->db_compatible &&
- rview->is_stencil_sampler;
-
- si_set_mutable_tex_desc_fields(sctx->screen, rtex,
- rview->base_level_info,
- rview->base_level,
- rview->base.u.tex.first_level,
- rview->block_width,
- is_separate_stencil,
- desc);
- }
-
- if (!is_buffer && rtex->fmask.size) {
- memcpy(desc + 8,
- rview->fmask_state, 8*4);
- } else {
- /* Disable FMASK and bind sampler state in [12:15]. */
- memcpy(desc + 8,
- null_texture_descriptor, 4*4);
-
- if (views->sampler_states[slot])
- memcpy(desc + 12,
- views->sampler_states[slot]->val, 4*4);
- }
-
+ pipe_sampler_view_reference(&views->views[slot], view);
views->enabled_mask |= 1u << slot;

/* Since this can flush, it must be done after enabled_mask is
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:30 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/include/pipe/p_context.h | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 4b75386a65..83eb1c9b08 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -766,6 +766,22 @@ struct pipe_context {
unsigned last_level,
unsigned first_layer,
unsigned last_layer);
+
+ /**
+ * Bindless texture/image handles interface.
+ */
+ uint64_t (*create_texture_handle)(struct pipe_context *ctx,
+ struct pipe_resource *res,
+ struct pipe_sampler_view *view,
+ const struct pipe_sampler_state *state);
+ void (*delete_texture_handle)(struct pipe_context *ctx, uint64_t handle);
+ void (*make_texture_handle_resident)(struct pipe_context *ctx,
+ uint64_t handle, bool resident);
+ uint64_t (*create_image_handle)(struct pipe_context *ctx,
+ const struct pipe_image_view *image);
+ void (*delete_image_handle)(struct pipe_context *ctx, uint64_t handle);
+ void (*make_image_handle_resident)(struct pipe_context *ctx, uint64_t handle,
+ unsigned access, bool resident);
};
--
2.13.0
Roland Scheidegger
2017-05-21 23:26:49 UTC
Permalink
Clearly, you forgot the doc bits...

Roland
Post by Samuel Pitoiset
---
src/gallium/include/pipe/p_context.h | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 4b75386a65..83eb1c9b08 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -766,6 +766,22 @@ struct pipe_context {
unsigned last_level,
unsigned first_layer,
unsigned last_layer);
+
+ /**
+ * Bindless texture/image handles interface.
+ */
+ uint64_t (*create_texture_handle)(struct pipe_context *ctx,
+ struct pipe_resource *res,
+ struct pipe_sampler_view *view,
+ const struct pipe_sampler_state *state);
+ void (*delete_texture_handle)(struct pipe_context *ctx, uint64_t handle);
+ void (*make_texture_handle_resident)(struct pipe_context *ctx,
+ uint64_t handle, bool resident);
+ uint64_t (*create_image_handle)(struct pipe_context *ctx,
+ const struct pipe_image_view *image);
+ void (*delete_image_handle)(struct pipe_context *ctx, uint64_t handle);
+ void (*make_image_handle_resident)(struct pipe_context *ctx, uint64_t handle,
+ unsigned access, bool resident);
};
Samuel Pitoiset
2017-05-22 08:22:18 UTC
Permalink
Post by Roland Scheidegger
Clearly, you forgot the doc bits...
Yes, some doc bits could be helpful. :)
Post by Roland Scheidegger
Roland
Post by Samuel Pitoiset
---
src/gallium/include/pipe/p_context.h | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 4b75386a65..83eb1c9b08 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -766,6 +766,22 @@ struct pipe_context {
unsigned last_level,
unsigned first_layer,
unsigned last_layer);
+
+ /**
+ * Bindless texture/image handles interface.
+ */
+ uint64_t (*create_texture_handle)(struct pipe_context *ctx,
+ struct pipe_resource *res,
+ struct pipe_sampler_view *view,
+ const struct pipe_sampler_state *state);
+ void (*delete_texture_handle)(struct pipe_context *ctx, uint64_t handle);
+ void (*make_texture_handle_resident)(struct pipe_context *ctx,
+ uint64_t handle, bool resident);
+ uint64_t (*create_image_handle)(struct pipe_context *ctx,
+ const struct pipe_image_view *image);
+ void (*delete_image_handle)(struct pipe_context *ctx, uint64_t handle);
+ void (*make_image_handle_resident)(struct pipe_context *ctx, uint64_t handle,
+ unsigned access, bool resident);
};
Marek Olšák
2017-05-25 13:53:26 UTC
Permalink
Post by Samuel Pitoiset
---
src/gallium/include/pipe/p_context.h | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/src/gallium/include/pipe/p_context.h
b/src/gallium/include/pipe/p_context.h
index 4b75386a65..83eb1c9b08 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -766,6 +766,22 @@ struct pipe_context {
unsigned last_level,
unsigned first_layer,
unsigned last_layer);
+
+ /**
+ * Bindless texture/image handles interface.
+ */
+ uint64_t (*create_texture_handle)(struct pipe_context *ctx,
+ struct pipe_resource *res,
+ struct pipe_sampler_view *view,
+ const struct pipe_sampler_state *state);
+ void (*delete_texture_handle)(struct pipe_context *ctx, uint64_t handle);
+ void (*make_texture_handle_resident)(struct pipe_context *ctx,
+ uint64_t handle, bool resident);
+ uint64_t (*create_image_handle)(struct pipe_context *ctx,
+ const struct pipe_image_view *image);
+ void (*delete_image_handle)(struct pipe_context *ctx, uint64_t handle);
+ void (*make_image_handle_resident)(struct pipe_context *ctx, uint64_t handle,
+ unsigned access, bool resident);
Should the create/delete functions be pipe_screen functions? Handles are
shared across a GL share group, so the current implementation with a
per-context hash of handles is definitely wrong. I still need to go over it
in detail.
BTW, shaders and sampler views are shared across a GL share group too.
I think this is the same as sampler views. radeonsi is OK with that. I
don't think any other drivers except nouveau will want to support
bindless textures.

Marek
Samuel Pitoiset
2017-05-19 16:52:44 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_atom_texture.c | 15 +++++++++------
src/mesa/state_tracker/st_texture.h | 5 +++++
2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c
index a99bc1a188..f9d726a609 100644
--- a/src/mesa/state_tracker/st_atom_texture.c
+++ b/src/mesa/state_tracker/st_atom_texture.c
@@ -52,10 +52,13 @@
#include "cso_cache/cso_context.h"


-static GLboolean
-update_single_texture(struct st_context *st,
- struct pipe_sampler_view **sampler_view,
- GLuint texUnit, unsigned glsl_version)
+/**
+ * Get a pipe_sampler_view object from a texture unit.
+ */
+GLboolean
+st_update_single_texture(struct st_context *st,
+ struct pipe_sampler_view **sampler_view,
+ GLuint texUnit, unsigned glsl_version)
{
struct gl_context *ctx = st->ctx;
const struct gl_sampler_object *samp;
@@ -129,8 +132,8 @@ update_textures(struct st_context *st,
const GLuint texUnit = prog->SamplerUnits[unit];
GLboolean retval;

- retval = update_single_texture(st, &sampler_view, texUnit,
- glsl_version);
+ retval = st_update_single_texture(st, &sampler_view, texUnit,
+ glsl_version);
if (retval == GL_FALSE)
continue;

diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index 1b4d1a3ea2..8eb0b4be47 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -264,4 +264,9 @@ st_convert_sampler(const struct st_context *st,
const struct gl_sampler_object *msamp,
struct pipe_sampler_state *sampler);

+GLboolean
+st_update_single_texture(struct st_context *st,
+ struct pipe_sampler_view **sampler_view,
+ GLuint texUnit, unsigned glsl_version);
+
#endif
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:42 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/gallium/auxiliary/tgsi/tgsi_scan.c | 37 ++++++++++++++++++++++++++++++++++
src/gallium/auxiliary/tgsi/tgsi_scan.h | 2 ++
2 files changed, 39 insertions(+)

diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c
index d1ef769ec4..d9c8db7c78 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_scan.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c
@@ -367,6 +367,43 @@ scan_instruction(struct tgsi_shader_info *info,
case TGSI_OPCODE_ENDLOOP:
(*current_depth)--;
break;
+ case TGSI_OPCODE_TEX:
+ case TGSI_OPCODE_TEX_LZ:
+ case TGSI_OPCODE_TXB:
+ case TGSI_OPCODE_TXD:
+ case TGSI_OPCODE_TXL:
+ case TGSI_OPCODE_TXP:
+ case TGSI_OPCODE_TXQ:
+ case TGSI_OPCODE_TXQS:
+ case TGSI_OPCODE_TXF:
+ case TGSI_OPCODE_TXF_LZ:
+ case TGSI_OPCODE_TEX2:
+ case TGSI_OPCODE_TXB2:
+ case TGSI_OPCODE_TXL2:
+ case TGSI_OPCODE_TG4:
+ case TGSI_OPCODE_LODQ:
+ if (fullinst->Texture.Bindless)
+ info->uses_bindless_samplers = true;
+ break;
+ case TGSI_OPCODE_RESQ:
+ case TGSI_OPCODE_LOAD:
+ case TGSI_OPCODE_ATOMUADD:
+ case TGSI_OPCODE_ATOMXCHG:
+ case TGSI_OPCODE_ATOMCAS:
+ case TGSI_OPCODE_ATOMAND:
+ case TGSI_OPCODE_ATOMOR:
+ case TGSI_OPCODE_ATOMXOR:
+ case TGSI_OPCODE_ATOMUMIN:
+ case TGSI_OPCODE_ATOMUMAX:
+ case TGSI_OPCODE_ATOMIMIN:
+ case TGSI_OPCODE_ATOMIMAX:
+ if (fullinst->Memory.Bindless)
+ info->uses_bindless_images = true;
+ break;
+ case TGSI_OPCODE_STORE:
+ if (fullinst->Memory.Bindless)
+ info->uses_bindless_images = true;
+ break;
default:
break;
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.h b/src/gallium/auxiliary/tgsi/tgsi_scan.h
index 98387c982c..473a0b6568 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_scan.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_scan.h
@@ -135,6 +135,8 @@ struct tgsi_shader_info
boolean is_msaa_sampler[PIPE_MAX_SAMPLERS];
boolean uses_doubles; /**< uses any of the double instructions */
boolean uses_derivatives;
+ boolean uses_bindless_samplers;
+ boolean uses_bindless_images;
unsigned clipdist_writemask;
unsigned culldist_writemask;
unsigned num_written_culldistance;
--
2.13.0
Samuel Pitoiset
2017-05-19 16:53:10 UTC
Permalink
This has only been tested on RX480.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
docs/features.txt | 2 +-
docs/relnotes/17.2.0.html | 1 +
src/gallium/drivers/radeonsi/si_pipe.c | 4 +++-
3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/docs/features.txt b/docs/features.txt
index e18bf54a48..bbf81d45f0 100644
--- a/docs/features.txt
+++ b/docs/features.txt
@@ -277,7 +277,7 @@ GLES3.2, GLSL ES 3.2 -- all DONE: i965/gen9+

Khronos, ARB, and OES extensions that are not part of any OpenGL or OpenGL ES version:

- GL_ARB_bindless_texture started (airlied)
+ GL_ARB_bindless_texture DONE (radeonsi)
GL_ARB_cl_event not started
GL_ARB_compute_variable_group_size DONE (nvc0, radeonsi)
GL_ARB_ES3_2_compatibility DONE (i965/gen8+)
diff --git a/docs/relnotes/17.2.0.html b/docs/relnotes/17.2.0.html
index 426bb72a51..4561451186 100644
--- a/docs/relnotes/17.2.0.html
+++ b/docs/relnotes/17.2.0.html
@@ -44,6 +44,7 @@ Note: some of the new features are only available with certain drivers.
</p>

<ul>
+<li>GL_ARB_bindless_texture on radeonsi</li>
<li>GL_ARB_shader_viewport_layer_array on nvc0 (GM200+)</li>
<li>GL_AMD_vertex_shader_layer on nvc0 (GM200+)</li>
<li>GL_AMD_vertex_shader_viewport_index on nvc0 (GM200+)</li>
diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c
index 2bb2b3baa7..c071973f87 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.c
+++ b/src/gallium/drivers/radeonsi/si_pipe.c
@@ -475,6 +475,9 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_DOUBLES:
case PIPE_CAP_TGSI_TEX_TXF_LZ:
case PIPE_CAP_TGSI_TES_LAYER_VIEWPORT:
+ case PIPE_CAP_BINDLESS_TEXTURE:
+ return 1;
+
case PIPE_CAP_INT64:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_TGSI_CLOCK:
@@ -556,7 +559,6 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_TGSI_MUL_ZERO_WINS:
case PIPE_CAP_UMA:
case PIPE_CAP_POLYGON_MODE_FILL_RECTANGLE:
- case PIPE_CAP_BINDLESS_TEXTURE:
return 0;

case PIPE_CAP_QUERY_BUFFER_OBJECT:
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:49 UTC
Permalink
Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/state_tracker/st_atom_constbuf.c | 6 ++
src/mesa/state_tracker/st_texture.c | 94 +++++++++++++++++++++++++++++++
src/mesa/state_tracker/st_texture.h | 8 +++
3 files changed, 108 insertions(+)

diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c
index 0c66994066..e4b585101d 100644
--- a/src/mesa/state_tracker/st_atom_constbuf.c
+++ b/src/mesa/state_tracker/st_atom_constbuf.c
@@ -80,6 +80,12 @@ void st_upload_constants(struct st_context *st, struct gl_program *prog)
}
}

+ /* Make all bindless samplers/images bound texture/image units resident in
+ * the context.
+ */
+ st_make_bound_samplers_resident(st, prog);
+ st_make_bound_images_resident(st, prog);
+
/* update constants */
if (params && params->NumParameters) {
struct pipe_constant_buffer cb;
diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
index cde7759a61..74704b5c87 100644
--- a/src/mesa/state_tracker/st_texture.c
+++ b/src/mesa/state_tracker/st_texture.c
@@ -539,3 +539,97 @@ st_create_image_handle_from_unit(struct st_context *st,

return pipe->create_image_handle(pipe, &img);
}
+
+
+/**
+ * Make all bindless samplers bound to texture units resident in the context.
+ */
+void
+st_make_bound_samplers_resident(struct st_context *st,
+ struct gl_program *prog)
+{
+ enum pipe_shader_type shader = st_shader_stage_to_ptarget(prog->info.stage);
+ struct st_bound_handle *bound_handles = &st->bound_texture_handles[shader];
+ struct pipe_context *pipe = st->pipe;
+ GLuint64 handle;
+ int i;
+
+ /* Remove previous bound texture handles for this stage. */
+ st_destroy_bound_texture_handles_per_stage(st, shader);
+
+ if (likely(!prog->sh.HasBoundBindlessSampler))
+ return;
+
+ for (i = 0; i < prog->sh.NumBindlessSamplers; i++) {
+ struct gl_bindless_sampler *sampler = &prog->sh.BindlessSamplers[i];
+
+ if (!sampler->bound)
+ continue;
+
+ /* Request a new texture handle from the driver and make it resident. */
+ handle = st_create_texture_handle_from_unit(st, prog, sampler->unit);
+ if (!handle)
+ continue;
+
+ pipe->make_texture_handle_resident(st->pipe, handle, true);
+
+ /* Overwrite the texture unit value by the resident handle before
+ * uploading the constant buffer.
+ */
+ *(uint64_t *)sampler->data = handle;
+
+ /* Store the handle in the context. */
+ bound_handles->handles = (uint64_t *)
+ realloc(bound_handles->handles,
+ (bound_handles->num_handles + 1) * sizeof(uint64_t));
+ bound_handles->handles[bound_handles->num_handles] = handle;
+ bound_handles->num_handles++;
+ }
+}
+
+
+/**
+ * Make all bindless images bound to image units resident in the context.
+ */
+void
+st_make_bound_images_resident(struct st_context *st,
+ struct gl_program *prog)
+{
+ enum pipe_shader_type shader = st_shader_stage_to_ptarget(prog->info.stage);
+ struct st_bound_handle *bound_handles = &st->bound_image_handles[shader];
+ struct pipe_context *pipe = st->pipe;
+ GLuint64 handle;
+ int i;
+
+ /* Remove previous bound image handles for this stage. */
+ st_destroy_bound_image_handles_per_stage(st, shader);
+
+ if (likely(!prog->sh.HasBoundBindlessImage))
+ return;
+
+ for (i = 0; i < prog->sh.NumBindlessImages; i++) {
+ struct gl_bindless_image *image = &prog->sh.BindlessImages[i];
+
+ if (!image->bound)
+ continue;
+
+ /* Request a new image handle from the driver and make it resident. */
+ handle = st_create_image_handle_from_unit(st, prog, image->unit);
+ if (!handle)
+ continue;
+
+ pipe->make_image_handle_resident(st->pipe, handle, GL_READ_WRITE, true);
+
+ /* Overwrite the image unit value by the resident handle before uploading
+ * the constant buffer.
+ */
+ *(uint64_t *)image->data = handle;
+
+ /* Store the handle in the context. */
+ bound_handles->handles = (uint64_t *)
+ realloc(bound_handles->handles,
+ (bound_handles->num_handles + 1) * sizeof(uint64_t));
+ bound_handles->handles[bound_handles->num_handles] = handle;
+ bound_handles->num_handles++;
+ }
+}
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index b97814cb16..c9b778bcb6 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -284,4 +284,12 @@ st_update_single_texture(struct st_context *st,
struct pipe_sampler_view **sampler_view,
GLuint texUnit, unsigned glsl_version);

+void
+st_make_bound_samplers_resident(struct st_context *st,
+ struct gl_program *prog);
+
+void
+st_make_bound_images_resident(struct st_context *st,
+ struct gl_program *prog);
+
#endif
--
2.13.0
Samuel Pitoiset
2017-05-19 16:52:23 UTC
Permalink
This will also be used for looping over bindless samplers bound
to texture units.

Signed-off-by: Samuel Pitoiset <***@gmail.com>
---
src/mesa/main/texstate.c | 36 +++++++++++++++++++++++-------------
1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index 1aac3cdbd8..4fd853f386 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -612,15 +612,13 @@ update_texgen(struct gl_context *ctx)

static struct gl_texture_object *
update_single_program_texture(struct gl_context *ctx, struct gl_program *prog,
- int s)
+ int unit)
{
gl_texture_index target_index;
struct gl_texture_unit *texUnit;
struct gl_texture_object *texObj;
struct gl_sampler_object *sampler;
- int unit;

- unit = prog->SamplerUnits[s];
texUnit = &ctx->Texture.Unit[unit];

/* Note: If more than one bit was set in TexturesUsed[unit], then we should
@@ -666,6 +664,24 @@ update_single_program_texture(struct gl_context *ctx, struct gl_program *prog,
return texObj;
}

+static inline void
+update_single_program_texture_state(struct gl_context *ctx,
+ struct gl_program *prog,
+ int unit,
+ BITSET_WORD *enabled_texture_units)
+{
+ struct gl_texture_object *texObj;
+
+ texObj = update_single_program_texture(ctx, prog, unit);
+ if (!texObj)
+ return;
+
+ _mesa_reference_texobj(&ctx->Texture.Unit[unit]._Current, texObj);
+ BITSET_SET(enabled_texture_units, unit);
+ ctx->Texture._MaxEnabledTexImageUnit =
+ MAX2(ctx->Texture._MaxEnabledTexImageUnit, (int)unit);
+}
+
static void
update_program_texture_state(struct gl_context *ctx, struct gl_program **prog,
BITSET_WORD *enabled_texture_units)
@@ -682,16 +698,10 @@ update_program_texture_state(struct gl_context *ctx, struct gl_program **prog,

while (mask) {
const int s = u_bit_scan(&mask);
- struct gl_texture_object *texObj;
-
- texObj = update_single_program_texture(ctx, prog[i], s);
- if (texObj) {
- int unit = prog[i]->SamplerUnits[s];
- _mesa_reference_texobj(&ctx->Texture.Unit[unit]._Current, texObj);
- BITSET_SET(enabled_texture_units, unit);
- ctx->Texture._MaxEnabledTexImageUnit =
- MAX2(ctx->Texture._MaxEnabledTexImageUnit, (int)unit);
- }
+
+ update_single_program_texture_state(ctx, prog[i],
+ prog[i]->SamplerUnits[s],
+ enabled_texture_units);
}
}
--
2.13.0
Ilia Mirkin
2017-05-19 17:05:16 UTC
Permalink
Great work, Samuel! Is this available in a branch somewhere?

On Fri, May 19, 2017 at 12:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
Hi,
This series implements ARB_bindless_texture for RadeonSI.
Reminder: the GLSL compiler part is already upstream.
This series has been mainly tested with Feral games, here's the list of
- DXMD
- Hitman
- Dirt Rally
- Mad Max
Today, Feral announced "Warhammer 40,000: Dawn of War III" (called DOW3) which
is going to be released next month. This game *requires* ARB_bindless_texture,
that now explains why I did all this work. :-) So, we have ~3 weeks for merging
this whole series. It would be very nice to have DOW3 support at day one!
=== Tracking bindless problems ===
- Dirt Rally
- Hitman
- Mad Max
- DOW3
- No rendering issues
- No VM faults (ie. amdgpu.vm_debug=1)
However, DXMD is currently broken because the bindless_sampler layout qualifier
is missing, which ends up by reporting a ton of INVALID_OPERATION errors. Note
that Feral implemented bindless support against NV_bindless_texture and not
ARB_bindless_texture. The main difference is that bindless_sampler is implicit
for NV_* while it's required for ARB_*. Feral plan to fix this soon.
All ARB_bindless_texture piglit tests pass with this series.
=== Tracking regressions/changes ===
- No regressions with the Intel CI system
- One piglit regression that needs to be fixed
(arb_texture_multisample-sample-position)
- No shader-db changes
- No CPU overhead (glxgears and Heaven in low)
=== Performance results for DOW3 ===
- mode 1: all bindless (ie. no bound samplers)
- mode 2: bound/bindless (ie. only bindless when the limit is reached)
NVIDIA blob: 381.22
== GTX 1060 ==
- mode 1: 89 FPS
- mode 2: 51 FPS
- mode 1: 49 FPS
- mode 2: 28 FPS
- mode 1: 32 FPS
- mode 2: 19 FPS
The GTX 1060 performs very well with the all bindless mode (default), while
the bound/bindless mode is not good at all.
== RX480 ==
- mode 1: 67 FPS (-32%)
- mode 2: 75 FPS (+32%)
- mode 1: 38 FPS (-28%)
- mode 2: 44 FPS (+57%)
- mode 1: 26 FPS (-23%)
- mode 2: 29 FPS (+52%)
The RX 480 performs very well with the bound/bindless mode (default), while
the all bindless mode still has to be improved.
The most important bottleneck with the all bindless mode is the number of
buffers that have to be added for every command stream. The overhead in the
winsys and in the kernel (amdgpu_cs_ioctl) becomes important in this situation.
This mode is still clearly CPU bound and should be improved (see the "Future
work" section).
Btw, without any optimisations, it was around 35FPS in low (mode 1).
=== Performance results for other Feral titles ===
I didn't record any numbers because these games have been initially
developed/tested against the NVIDIA blob which it's unaffected by a VERY huge
number of resident handles. While the AMD stack is really slow in this
situation. Though, as I said, all Feral games that use bindless work fine, we
just need to improve perf on both sides.
=== Future work ===
I have some ideas to try in order to improve performance with RadeonSI. I will
work on this once this series is upstream.
Please review,
Thanks!
mapi: add GL_ARB_bindless_texture entry points
mesa: implement ARB_bindless_texture
mesa: add support for unsigned 64-bit vertex attributes
mesa: add support for glUniformHandleui64*ARB()
mesa: refuse to update sampler parameters when a handle is allocated
mesa: refuse to update tex parameters when a handle is allocated
mesa: refuse to change textures when a handle is allocated
mesa: refuse to change tex buffers when a handle is allocated
mesa: keep track of the current variable in add_uniform_to_shader
mesa: store bindless samplers as PROGRAM_UNIFORM
mesa: add infrastructure for bindless samplers/images bound to units
glsl: process uniform samplers declared bindless
glsl: process uniform images declared bindless
glsl: pass the ir_variable object to set_opaque_binding()
glsl: set the explicit binding value for bindless samplers/images
glsl: add ir_variable::is_bindless()
mesa: add update_single_shader_texture_used() helper
mesa: add update_single_program_texture_state() helper
mesa: update textures for bindless samplers bound to texture units
mesa: pass gl_program to _mesa_associate_uniform_storage()
mesa: associate uniform storage to bindless samplers/images
mesa: handle bindless uniforms bound to texture/image units
mesa: get rid of a workaround for bindless in _mesa_get_uniform()
gallium: add PIPE_CAP_BINDLESS_TEXTURE
gallium: add ARB_bindless_texture interface
ddebug: add ARB_bindless_texture support
trace: add ARB_bindless_texture support
tc: add ARB_bindless_texture support
tgsi: add new Bindless flag to tgsi_instruction_texture
tgsi: add new Bindless flag to tgsi_instruction_memory
tgsi/ureg: accept TGSI_FILE_{CONSTANT,INPUT} for dst registers
st/glsl_to_tgsi: add support for bindless samplers
st/glsl_to_tgsi: add support for bindless images
st/glsl_to_tgsi: add support for bindless pack/unpack operations
st/glsl_to_tgsi: teach the DCE pass about bindless samplers/images
st/glsl_to_tgsi: teach rename_temp_registers() about bindless samplers
tgsi/scan: record bindless samplers/images usage
st/mesa: implement ARB_bindless_texture
st/mesa: make update_single_texture() non-static
st/mesa: make convert_sampler_from_unit() non-static
st/mesa: add st_convert_image_from_unit() helper
st/mesa: add st_create_{texture,image}_handle_from_unit() helper
st/mesa: add infrastructure for storing bound texture/image handles
st/mesa: make bindless samplers/images bound to units resident
st/mesa: do not release sampler views for resident textures
st/mesa: disable per-context seamless cubemap when using texture
handles
st/mesa: enable ARB_bindless_texture
radeonsi: add a slab allocator for resident descriptors
radeonsi: add si_init_descriptor_list() helper
radeonsi: add si_set_sampler_view_desc() helper
radeonsi: add si_set_shader_image_desc() helper
radeonsi: implement ARB_bindless_texture
radeonsi: add all resident buffers to the current CS
radeonsi: only add descriptors in presence of resident handles
radeonsi: add si_update_check_render_feedback() helper
radeonsi: decompress DCC for resident textures/images
radeonsi: decompress resident textures/images before graphics/compute
radeonsi: isolate real framebuffer changes from the decompression
passes
radeonsi: track use of bindless samplers/images from tgsi_shader_info
radeonsi: only decompress resident textures/images when used
radeonsi: upload new descriptors when resident buffers are invalidated
radeonsi: invalidate buffers which are made resident if needed
radeonsi: add support for loading bindless samplers
radeonsi: add support for loading bindless images
radeonsi: enable ARB_bindless_texture
docs/features.txt | 2 +-
docs/relnotes/17.2.0.html | 1 +
src/compiler/glsl/ir.h | 11 +
src/compiler/glsl/ir_uniform.h | 12 +
src/compiler/glsl/link_uniform_initializers.cpp | 42 +-
src/compiler/glsl/link_uniforms.cpp | 156 +++-
src/compiler/glsl/shader_cache.cpp | 47 +
src/gallium/auxiliary/tgsi/tgsi_build.c | 8 +
src/gallium/auxiliary/tgsi/tgsi_scan.c | 37 +
src/gallium/auxiliary/tgsi/tgsi_scan.h | 2 +
src/gallium/auxiliary/tgsi/tgsi_ureg.c | 21 +-
src/gallium/auxiliary/tgsi/tgsi_ureg.h | 16 +-
src/gallium/auxiliary/util/u_threaded_context.c | 147 ++++
.../auxiliary/util/u_threaded_context_calls.h | 4 +
src/gallium/docs/source/screen.rst | 2 +
src/gallium/drivers/ddebug/dd_context.c | 61 ++
src/gallium/drivers/etnaviv/etnaviv_screen.c | 1 +
src/gallium/drivers/freedreno/freedreno_screen.c | 1 +
src/gallium/drivers/i915/i915_screen.c | 1 +
src/gallium/drivers/llvmpipe/lp_screen.c | 1 +
src/gallium/drivers/nouveau/nv30/nv30_screen.c | 1 +
src/gallium/drivers/nouveau/nv50/nv50_screen.c | 1 +
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 1 +
src/gallium/drivers/r300/r300_screen.c | 1 +
src/gallium/drivers/r600/r600_pipe.c | 1 +
src/gallium/drivers/radeon/r600_pipe_common.h | 4 +
src/gallium/drivers/radeonsi/si_blit.c | 131 ++-
src/gallium/drivers/radeonsi/si_compute.c | 2 +
src/gallium/drivers/radeonsi/si_compute.h | 14 +
src/gallium/drivers/radeonsi/si_descriptors.c | 943 +++++++++++++++++++--
src/gallium/drivers/radeonsi/si_hw_context.c | 1 +
src/gallium/drivers/radeonsi/si_pipe.c | 25 +
src/gallium/drivers/radeonsi/si_pipe.h | 68 ++
src/gallium/drivers/radeonsi/si_shader.h | 12 +
src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c | 48 +-
src/gallium/drivers/radeonsi/si_state.c | 10 +-
src/gallium/drivers/radeonsi/si_state.h | 9 +
src/gallium/drivers/softpipe/sp_screen.c | 1 +
src/gallium/drivers/svga/svga_screen.c | 1 +
src/gallium/drivers/swr/swr_screen.cpp | 1 +
src/gallium/drivers/trace/tr_context.c | 114 +++
src/gallium/drivers/vc4/vc4_screen.c | 1 +
src/gallium/drivers/virgl/virgl_screen.c | 1 +
src/gallium/include/pipe/p_context.h | 16 +
src/gallium/include/pipe/p_defines.h | 1 +
src/gallium/include/pipe/p_shader_tokens.h | 6 +-
src/mapi/glapi/gen/ARB_bindless_texture.xml | 100 +++
src/mapi/glapi/gen/Makefile.am | 1 +
src/mapi/glapi/gen/apiexec.py | 3 +
src/mapi/glapi/gen/gl_API.xml | 4 +-
src/mapi/glapi/gen/gl_genexec.py | 1 +
src/mesa/Makefile.sources | 2 +
src/mesa/main/api_loopback.c | 18 +
src/mesa/main/api_loopback.h | 6 +
src/mesa/main/bufferobj.c | 4 +-
src/mesa/main/context.c | 3 +
src/mesa/main/dd.h | 19 +
src/mesa/main/mtypes.h | 86 ++
src/mesa/main/samplerobj.c | 48 ++
src/mesa/main/shared.c | 12 +
src/mesa/main/tests/dispatch_sanity.cpp | 18 +
src/mesa/main/teximage.c | 25 +-
src/mesa/main/texobj.c | 12 +
src/mesa/main/texparam.c | 61 ++
src/mesa/main/texstate.c | 52 +-
src/mesa/main/texturebindless.c | 902 ++++++++++++++++++++
src/mesa/main/texturebindless.h | 96 +++
src/mesa/main/uniform_query.cpp | 208 ++++-
src/mesa/main/uniforms.c | 119 ++-
src/mesa/main/uniforms.h | 16 +
src/mesa/main/varray.c | 23 +
src/mesa/main/varray.h | 3 +
src/mesa/main/vtxfmt.c | 4 +
src/mesa/program/ir_to_mesa.cpp | 36 +-
src/mesa/program/ir_to_mesa.h | 4 +-
src/mesa/program/program.c | 8 +
src/mesa/state_tracker/st_atifs_to_tgsi.c | 2 +-
src/mesa/state_tracker/st_atom_constbuf.c | 6 +
src/mesa/state_tracker/st_atom_image.c | 33 +-
src/mesa/state_tracker/st_atom_sampler.c | 32 +-
src/mesa/state_tracker/st_atom_texture.c | 15 +-
src/mesa/state_tracker/st_cb_texture.c | 84 ++
src/mesa/state_tracker/st_context.c | 2 +
src/mesa/state_tracker/st_context.h | 11 +
src/mesa/state_tracker/st_extensions.c | 1 +
src/mesa/state_tracker/st_glsl_to_nir.cpp | 3 +-
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 138 ++-
src/mesa/state_tracker/st_mesa_to_tgsi.c | 2 +-
src/mesa/state_tracker/st_pbo.c | 2 +-
src/mesa/state_tracker/st_sampler_view.c | 6 +
src/mesa/state_tracker/st_shader_cache.c | 3 +-
src/mesa/state_tracker/st_texture.c | 213 +++++
src/mesa/state_tracker/st_texture.h | 28 +
src/mesa/vbo/vbo_attrib_tmp.h | 28 +
src/mesa/vbo/vbo_context.h | 2 +
src/mesa/vbo/vbo_exec_api.c | 15 +-
src/mesa/vbo/vbo_save_api.c | 3 +
97 files changed, 4250 insertions(+), 260 deletions(-)
create mode 100644 src/mapi/glapi/gen/ARB_bindless_texture.xml
create mode 100644 src/mesa/main/texturebindless.c
create mode 100644 src/mesa/main/texturebindless.h
--
2.13.0
_______________________________________________
mesa-dev mailing list
https://lists.freedesktop.org/mailman/listinfo/mesa-dev
Samuel Pitoiset
2017-05-19 17:06:05 UTC
Permalink
Post by Ilia Mirkin
Great work, Samuel! Is this available in a branch somewhere?
Thanks Ilia!

Here's the branch:
https://cgit.freedesktop.org/~hakzsam/mesa/log/?h=arb_bindless_texture
Post by Ilia Mirkin
On Fri, May 19, 2017 at 12:52 PM, Samuel Pitoiset
Post by Samuel Pitoiset
Hi,
This series implements ARB_bindless_texture for RadeonSI.
Reminder: the GLSL compiler part is already upstream.
This series has been mainly tested with Feral games, here's the list of
- DXMD
- Hitman
- Dirt Rally
- Mad Max
Today, Feral announced "Warhammer 40,000: Dawn of War III" (called DOW3) which
is going to be released next month. This game *requires* ARB_bindless_texture,
that now explains why I did all this work. :-) So, we have ~3 weeks for merging
this whole series. It would be very nice to have DOW3 support at day one!
=== Tracking bindless problems ===
- Dirt Rally
- Hitman
- Mad Max
- DOW3
- No rendering issues
- No VM faults (ie. amdgpu.vm_debug=1)
However, DXMD is currently broken because the bindless_sampler layout qualifier
is missing, which ends up by reporting a ton of INVALID_OPERATION errors. Note
that Feral implemented bindless support against NV_bindless_texture and not
ARB_bindless_texture. The main difference is that bindless_sampler is implicit
for NV_* while it's required for ARB_*. Feral plan to fix this soon.
All ARB_bindless_texture piglit tests pass with this series.
=== Tracking regressions/changes ===
- No regressions with the Intel CI system
- One piglit regression that needs to be fixed
(arb_texture_multisample-sample-position)
- No shader-db changes
- No CPU overhead (glxgears and Heaven in low)
=== Performance results for DOW3 ===
- mode 1: all bindless (ie. no bound samplers)
- mode 2: bound/bindless (ie. only bindless when the limit is reached)
NVIDIA blob: 381.22
== GTX 1060 ==
- mode 1: 89 FPS
- mode 2: 51 FPS
- mode 1: 49 FPS
- mode 2: 28 FPS
- mode 1: 32 FPS
- mode 2: 19 FPS
The GTX 1060 performs very well with the all bindless mode (default), while
the bound/bindless mode is not good at all.
== RX480 ==
- mode 1: 67 FPS (-32%)
- mode 2: 75 FPS (+32%)
- mode 1: 38 FPS (-28%)
- mode 2: 44 FPS (+57%)
- mode 1: 26 FPS (-23%)
- mode 2: 29 FPS (+52%)
The RX 480 performs very well with the bound/bindless mode (default), while
the all bindless mode still has to be improved.
The most important bottleneck with the all bindless mode is the number of
buffers that have to be added for every command stream. The overhead in the
winsys and in the kernel (amdgpu_cs_ioctl) becomes important in this situation.
This mode is still clearly CPU bound and should be improved (see the "Future
work" section).
Btw, without any optimisations, it was around 35FPS in low (mode 1).
=== Performance results for other Feral titles ===
I didn't record any numbers because these games have been initially
developed/tested against the NVIDIA blob which it's unaffected by a VERY huge
number of resident handles. While the AMD stack is really slow in this
situation. Though, as I said, all Feral games that use bindless work fine, we
just need to improve perf on both sides.
=== Future work ===
I have some ideas to try in order to improve performance with RadeonSI. I will
work on this once this series is upstream.
Please review,
Thanks!
mapi: add GL_ARB_bindless_texture entry points
mesa: implement ARB_bindless_texture
mesa: add support for unsigned 64-bit vertex attributes
mesa: add support for glUniformHandleui64*ARB()
mesa: refuse to update sampler parameters when a handle is allocated
mesa: refuse to update tex parameters when a handle is allocated
mesa: refuse to change textures when a handle is allocated
mesa: refuse to change tex buffers when a handle is allocated
mesa: keep track of the current variable in add_uniform_to_shader
mesa: store bindless samplers as PROGRAM_UNIFORM
mesa: add infrastructure for bindless samplers/images bound to units
glsl: process uniform samplers declared bindless
glsl: process uniform images declared bindless
glsl: pass the ir_variable object to set_opaque_binding()
glsl: set the explicit binding value for bindless samplers/images
glsl: add ir_variable::is_bindless()
mesa: add update_single_shader_texture_used() helper
mesa: add update_single_program_texture_state() helper
mesa: update textures for bindless samplers bound to texture units
mesa: pass gl_program to _mesa_associate_uniform_storage()
mesa: associate uniform storage to bindless samplers/images
mesa: handle bindless uniforms bound to texture/image units
mesa: get rid of a workaround for bindless in _mesa_get_uniform()
gallium: add PIPE_CAP_BINDLESS_TEXTURE
gallium: add ARB_bindless_texture interface
ddebug: add ARB_bindless_texture support
trace: add ARB_bindless_texture support
tc: add ARB_bindless_texture support
tgsi: add new Bindless flag to tgsi_instruction_texture
tgsi: add new Bindless flag to tgsi_instruction_memory
tgsi/ureg: accept TGSI_FILE_{CONSTANT,INPUT} for dst registers
st/glsl_to_tgsi: add support for bindless samplers
st/glsl_to_tgsi: add support for bindless images
st/glsl_to_tgsi: add support for bindless pack/unpack operations
st/glsl_to_tgsi: teach the DCE pass about bindless samplers/images
st/glsl_to_tgsi: teach rename_temp_registers() about bindless samplers
tgsi/scan: record bindless samplers/images usage
st/mesa: implement ARB_bindless_texture
st/mesa: make update_single_texture() non-static
st/mesa: make convert_sampler_from_unit() non-static
st/mesa: add st_convert_image_from_unit() helper
st/mesa: add st_create_{texture,image}_handle_from_unit() helper
st/mesa: add infrastructure for storing bound texture/image handles
st/mesa: make bindless samplers/images bound to units resident
st/mesa: do not release sampler views for resident textures
st/mesa: disable per-context seamless cubemap when using texture
handles
st/mesa: enable ARB_bindless_texture
radeonsi: add a slab allocator for resident descriptors
radeonsi: add si_init_descriptor_list() helper
radeonsi: add si_set_sampler_view_desc() helper
radeonsi: add si_set_shader_image_desc() helper
radeonsi: implement ARB_bindless_texture
radeonsi: add all resident buffers to the current CS
radeonsi: only add descriptors in presence of resident handles
radeonsi: add si_update_check_render_feedback() helper
radeonsi: decompress DCC for resident textures/images
radeonsi: decompress resident textures/images before graphics/compute
radeonsi: isolate real framebuffer changes from the decompression
passes
radeonsi: track use of bindless samplers/images from tgsi_shader_info
radeonsi: only decompress resident textures/images when used
radeonsi: upload new descriptors when resident buffers are invalidated
radeonsi: invalidate buffers which are made resident if needed
radeonsi: add support for loading bindless samplers
radeonsi: add support for loading bindless images
radeonsi: enable ARB_bindless_texture
docs/features.txt | 2 +-
docs/relnotes/17.2.0.html | 1 +
src/compiler/glsl/ir.h | 11 +
src/compiler/glsl/ir_uniform.h | 12 +
src/compiler/glsl/link_uniform_initializers.cpp | 42 +-
src/compiler/glsl/link_uniforms.cpp | 156 +++-
src/compiler/glsl/shader_cache.cpp | 47 +
src/gallium/auxiliary/tgsi/tgsi_build.c | 8 +
src/gallium/auxiliary/tgsi/tgsi_scan.c | 37 +
src/gallium/auxiliary/tgsi/tgsi_scan.h | 2 +
src/gallium/auxiliary/tgsi/tgsi_ureg.c | 21 +-
src/gallium/auxiliary/tgsi/tgsi_ureg.h | 16 +-
src/gallium/auxiliary/util/u_threaded_context.c | 147 ++++
.../auxiliary/util/u_threaded_context_calls.h | 4 +
src/gallium/docs/source/screen.rst | 2 +
src/gallium/drivers/ddebug/dd_context.c | 61 ++
src/gallium/drivers/etnaviv/etnaviv_screen.c | 1 +
src/gallium/drivers/freedreno/freedreno_screen.c | 1 +
src/gallium/drivers/i915/i915_screen.c | 1 +
src/gallium/drivers/llvmpipe/lp_screen.c | 1 +
src/gallium/drivers/nouveau/nv30/nv30_screen.c | 1 +
src/gallium/drivers/nouveau/nv50/nv50_screen.c | 1 +
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 1 +
src/gallium/drivers/r300/r300_screen.c | 1 +
src/gallium/drivers/r600/r600_pipe.c | 1 +
src/gallium/drivers/radeon/r600_pipe_common.h | 4 +
src/gallium/drivers/radeonsi/si_blit.c | 131 ++-
src/gallium/drivers/radeonsi/si_compute.c | 2 +
src/gallium/drivers/radeonsi/si_compute.h | 14 +
src/gallium/drivers/radeonsi/si_descriptors.c | 943 +++++++++++++++++++--
src/gallium/drivers/radeonsi/si_hw_context.c | 1 +
src/gallium/drivers/radeonsi/si_pipe.c | 25 +
src/gallium/drivers/radeonsi/si_pipe.h | 68 ++
src/gallium/drivers/radeonsi/si_shader.h | 12 +
src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c | 48 +-
src/gallium/drivers/radeonsi/si_state.c | 10 +-
src/gallium/drivers/radeonsi/si_state.h | 9 +
src/gallium/drivers/softpipe/sp_screen.c | 1 +
src/gallium/drivers/svga/svga_screen.c | 1 +
src/gallium/drivers/swr/swr_screen.cpp | 1 +
src/gallium/drivers/trace/tr_context.c | 114 +++
src/gallium/drivers/vc4/vc4_screen.c | 1 +
src/gallium/drivers/virgl/virgl_screen.c | 1 +
src/gallium/include/pipe/p_context.h | 16 +
src/gallium/include/pipe/p_defines.h | 1 +
src/gallium/include/pipe/p_shader_tokens.h | 6 +-
src/mapi/glapi/gen/ARB_bindless_texture.xml | 100 +++
src/mapi/glapi/gen/Makefile.am | 1 +
src/mapi/glapi/gen/apiexec.py | 3 +
src/mapi/glapi/gen/gl_API.xml | 4 +-
src/mapi/glapi/gen/gl_genexec.py | 1 +
src/mesa/Makefile.sources | 2 +
src/mesa/main/api_loopback.c | 18 +
src/mesa/main/api_loopback.h | 6 +
src/mesa/main/bufferobj.c | 4 +-
src/mesa/main/context.c | 3 +
src/mesa/main/dd.h | 19 +
src/mesa/main/mtypes.h | 86 ++
src/mesa/main/samplerobj.c | 48 ++
src/mesa/main/shared.c | 12 +
src/mesa/main/tests/dispatch_sanity.cpp | 18 +
src/mesa/main/teximage.c | 25 +-
src/mesa/main/texobj.c | 12 +
src/mesa/main/texparam.c | 61 ++
src/mesa/main/texstate.c | 52 +-
src/mesa/main/texturebindless.c | 902 ++++++++++++++++++++
src/mesa/main/texturebindless.h | 96 +++
src/mesa/main/uniform_query.cpp | 208 ++++-
src/mesa/main/uniforms.c | 119 ++-
src/mesa/main/uniforms.h | 16 +
src/mesa/main/varray.c | 23 +
src/mesa/main/varray.h | 3 +
src/mesa/main/vtxfmt.c | 4 +
src/mesa/program/ir_to_mesa.cpp | 36 +-
src/mesa/program/ir_to_mesa.h | 4 +-
src/mesa/program/program.c | 8 +
src/mesa/state_tracker/st_atifs_to_tgsi.c | 2 +-
src/mesa/state_tracker/st_atom_constbuf.c | 6 +
src/mesa/state_tracker/st_atom_image.c | 33 +-
src/mesa/state_tracker/st_atom_sampler.c | 32 +-
src/mesa/state_tracker/st_atom_texture.c | 15 +-
src/mesa/state_tracker/st_cb_texture.c | 84 ++
src/mesa/state_tracker/st_context.c | 2 +
src/mesa/state_tracker/st_context.h | 11 +
src/mesa/state_tracker/st_extensions.c | 1 +
src/mesa/state_tracker/st_glsl_to_nir.cpp | 3 +-
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 138 ++-
src/mesa/state_tracker/st_mesa_to_tgsi.c | 2 +-
src/mesa/state_tracker/st_pbo.c | 2 +-
src/mesa/state_tracker/st_sampler_view.c | 6 +
src/mesa/state_tracker/st_shader_cache.c | 3 +-
src/mesa/state_tracker/st_texture.c | 213 +++++
src/mesa/state_tracker/st_texture.h | 28 +
src/mesa/vbo/vbo_attrib_tmp.h | 28 +
src/mesa/vbo/vbo_context.h | 2 +
src/mesa/vbo/vbo_exec_api.c | 15 +-
src/mesa/vbo/vbo_save_api.c | 3 +
97 files changed, 4250 insertions(+), 260 deletions(-)
create mode 100644 src/mapi/glapi/gen/ARB_bindless_texture.xml
create mode 100644 src/mesa/main/texturebindless.c
create mode 100644 src/mesa/main/texturebindless.h
--
2.13.0
_______________________________________________
mesa-dev mailing list
https://lists.freedesktop.org/mailman/listinfo/mesa-dev
Nicolai Hähnle
2017-05-20 19:01:31 UTC
Permalink
Post by Samuel Pitoiset
Hi,
This series implements ARB_bindless_texture for RadeonSI.
Reminder: the GLSL compiler part is already upstream.
This series has been mainly tested with Feral games, here's the list of
- DXMD
- Hitman
- Dirt Rally
- Mad Max
Today, Feral announced "Warhammer 40,000: Dawn of War III" (called DOW3) which
is going to be released next month. This game *requires* ARB_bindless_texture,
that now explains why I did all this work. :-) So, we have ~3 weeks for merging
this whole series. It would be very nice to have DOW3 support at day one!
=== Tracking bindless problems ===
- Dirt Rally
- Hitman
- Mad Max
- DOW3
- No rendering issues
- No VM faults (ie. amdgpu.vm_debug=1)
However, DXMD is currently broken because the bindless_sampler layout qualifier
is missing, which ends up by reporting a ton of INVALID_OPERATION errors. Note
that Feral implemented bindless support against NV_bindless_texture and not
ARB_bindless_texture. The main difference is that bindless_sampler is implicit
for NV_* while it's required for ARB_*. Feral plan to fix this soon.
All ARB_bindless_texture piglit tests pass with this series.
=== Tracking regressions/changes ===
- No regressions with the Intel CI system
- One piglit regression that needs to be fixed
(arb_texture_multisample-sample-position)
- No shader-db changes
- No CPU overhead (glxgears and Heaven in low)
=== Performance results for DOW3 ===
- mode 1: all bindless (ie. no bound samplers)
- mode 2: bound/bindless (ie. only bindless when the limit is reached)
NVIDIA blob: 381.22
== GTX 1060 ==
- mode 1: 89 FPS
- mode 2: 51 FPS
- mode 1: 49 FPS
- mode 2: 28 FPS
- mode 1: 32 FPS
- mode 2: 19 FPS
The GTX 1060 performs very well with the all bindless mode (default), while
the bound/bindless mode is not good at all.
== RX480 ==
- mode 1: 67 FPS (-32%)
- mode 2: 75 FPS (+32%)
- mode 1: 38 FPS (-28%)
- mode 2: 44 FPS (+57%)
- mode 1: 26 FPS (-23%)
- mode 2: 29 FPS (+52%)
What do the numbers in parenthesis mean? Relative to the GTX 1060?

Out of curiosity, did you do your tests with threaded gallium? I imagine
that it could help a lot already since it pushes the buffer handling
onto the gallium thread. And I guess it could be pushed further into the
CS submit thread.

Anyway, this is all very nice! While I've obviously seen a lot of bits
and pieces, I'll get to reviewing the whole series in earnest soon :-)

Cheers,
Nicolai
Post by Samuel Pitoiset
The RX 480 performs very well with the bound/bindless mode (default), while
the all bindless mode still has to be improved.
The most important bottleneck with the all bindless mode is the number of
buffers that have to be added for every command stream. The overhead in the
winsys and in the kernel (amdgpu_cs_ioctl) becomes important in this situation.
This mode is still clearly CPU bound and should be improved (see the "Future
work" section).
Btw, without any optimisations, it was around 35FPS in low (mode 1).
=== Performance results for other Feral titles ===
I didn't record any numbers because these games have been initially
developed/tested against the NVIDIA blob which it's unaffected by a VERY huge
number of resident handles. While the AMD stack is really slow in this
situation. Though, as I said, all Feral games that use bindless work fine, we
just need to improve perf on both sides.
=== Future work ===
I have some ideas to try in order to improve performance with RadeonSI. I will
work on this once this series is upstream.
Please review,
Thanks!
mapi: add GL_ARB_bindless_texture entry points
mesa: implement ARB_bindless_texture
mesa: add support for unsigned 64-bit vertex attributes
mesa: add support for glUniformHandleui64*ARB()
mesa: refuse to update sampler parameters when a handle is allocated
mesa: refuse to update tex parameters when a handle is allocated
mesa: refuse to change textures when a handle is allocated
mesa: refuse to change tex buffers when a handle is allocated
mesa: keep track of the current variable in add_uniform_to_shader
mesa: store bindless samplers as PROGRAM_UNIFORM
mesa: add infrastructure for bindless samplers/images bound to units
glsl: process uniform samplers declared bindless
glsl: process uniform images declared bindless
glsl: pass the ir_variable object to set_opaque_binding()
glsl: set the explicit binding value for bindless samplers/images
glsl: add ir_variable::is_bindless()
mesa: add update_single_shader_texture_used() helper
mesa: add update_single_program_texture_state() helper
mesa: update textures for bindless samplers bound to texture units
mesa: pass gl_program to _mesa_associate_uniform_storage()
mesa: associate uniform storage to bindless samplers/images
mesa: handle bindless uniforms bound to texture/image units
mesa: get rid of a workaround for bindless in _mesa_get_uniform()
gallium: add PIPE_CAP_BINDLESS_TEXTURE
gallium: add ARB_bindless_texture interface
ddebug: add ARB_bindless_texture support
trace: add ARB_bindless_texture support
tc: add ARB_bindless_texture support
tgsi: add new Bindless flag to tgsi_instruction_texture
tgsi: add new Bindless flag to tgsi_instruction_memory
tgsi/ureg: accept TGSI_FILE_{CONSTANT,INPUT} for dst registers
st/glsl_to_tgsi: add support for bindless samplers
st/glsl_to_tgsi: add support for bindless images
st/glsl_to_tgsi: add support for bindless pack/unpack operations
st/glsl_to_tgsi: teach the DCE pass about bindless samplers/images
st/glsl_to_tgsi: teach rename_temp_registers() about bindless samplers
tgsi/scan: record bindless samplers/images usage
st/mesa: implement ARB_bindless_texture
st/mesa: make update_single_texture() non-static
st/mesa: make convert_sampler_from_unit() non-static
st/mesa: add st_convert_image_from_unit() helper
st/mesa: add st_create_{texture,image}_handle_from_unit() helper
st/mesa: add infrastructure for storing bound texture/image handles
st/mesa: make bindless samplers/images bound to units resident
st/mesa: do not release sampler views for resident textures
st/mesa: disable per-context seamless cubemap when using texture
handles
st/mesa: enable ARB_bindless_texture
radeonsi: add a slab allocator for resident descriptors
radeonsi: add si_init_descriptor_list() helper
radeonsi: add si_set_sampler_view_desc() helper
radeonsi: add si_set_shader_image_desc() helper
radeonsi: implement ARB_bindless_texture
radeonsi: add all resident buffers to the current CS
radeonsi: only add descriptors in presence of resident handles
radeonsi: add si_update_check_render_feedback() helper
radeonsi: decompress DCC for resident textures/images
radeonsi: decompress resident textures/images before graphics/compute
radeonsi: isolate real framebuffer changes from the decompression
passes
radeonsi: track use of bindless samplers/images from tgsi_shader_info
radeonsi: only decompress resident textures/images when used
radeonsi: upload new descriptors when resident buffers are invalidated
radeonsi: invalidate buffers which are made resident if needed
radeonsi: add support for loading bindless samplers
radeonsi: add support for loading bindless images
radeonsi: enable ARB_bindless_texture
docs/features.txt | 2 +-
docs/relnotes/17.2.0.html | 1 +
src/compiler/glsl/ir.h | 11 +
src/compiler/glsl/ir_uniform.h | 12 +
src/compiler/glsl/link_uniform_initializers.cpp | 42 +-
src/compiler/glsl/link_uniforms.cpp | 156 +++-
src/compiler/glsl/shader_cache.cpp | 47 +
src/gallium/auxiliary/tgsi/tgsi_build.c | 8 +
src/gallium/auxiliary/tgsi/tgsi_scan.c | 37 +
src/gallium/auxiliary/tgsi/tgsi_scan.h | 2 +
src/gallium/auxiliary/tgsi/tgsi_ureg.c | 21 +-
src/gallium/auxiliary/tgsi/tgsi_ureg.h | 16 +-
src/gallium/auxiliary/util/u_threaded_context.c | 147 ++++
.../auxiliary/util/u_threaded_context_calls.h | 4 +
src/gallium/docs/source/screen.rst | 2 +
src/gallium/drivers/ddebug/dd_context.c | 61 ++
src/gallium/drivers/etnaviv/etnaviv_screen.c | 1 +
src/gallium/drivers/freedreno/freedreno_screen.c | 1 +
src/gallium/drivers/i915/i915_screen.c | 1 +
src/gallium/drivers/llvmpipe/lp_screen.c | 1 +
src/gallium/drivers/nouveau/nv30/nv30_screen.c | 1 +
src/gallium/drivers/nouveau/nv50/nv50_screen.c | 1 +
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 1 +
src/gallium/drivers/r300/r300_screen.c | 1 +
src/gallium/drivers/r600/r600_pipe.c | 1 +
src/gallium/drivers/radeon/r600_pipe_common.h | 4 +
src/gallium/drivers/radeonsi/si_blit.c | 131 ++-
src/gallium/drivers/radeonsi/si_compute.c | 2 +
src/gallium/drivers/radeonsi/si_compute.h | 14 +
src/gallium/drivers/radeonsi/si_descriptors.c | 943 +++++++++++++++++++--
src/gallium/drivers/radeonsi/si_hw_context.c | 1 +
src/gallium/drivers/radeonsi/si_pipe.c | 25 +
src/gallium/drivers/radeonsi/si_pipe.h | 68 ++
src/gallium/drivers/radeonsi/si_shader.h | 12 +
src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c | 48 +-
src/gallium/drivers/radeonsi/si_state.c | 10 +-
src/gallium/drivers/radeonsi/si_state.h | 9 +
src/gallium/drivers/softpipe/sp_screen.c | 1 +
src/gallium/drivers/svga/svga_screen.c | 1 +
src/gallium/drivers/swr/swr_screen.cpp | 1 +
src/gallium/drivers/trace/tr_context.c | 114 +++
src/gallium/drivers/vc4/vc4_screen.c | 1 +
src/gallium/drivers/virgl/virgl_screen.c | 1 +
src/gallium/include/pipe/p_context.h | 16 +
src/gallium/include/pipe/p_defines.h | 1 +
src/gallium/include/pipe/p_shader_tokens.h | 6 +-
src/mapi/glapi/gen/ARB_bindless_texture.xml | 100 +++
src/mapi/glapi/gen/Makefile.am | 1 +
src/mapi/glapi/gen/apiexec.py | 3 +
src/mapi/glapi/gen/gl_API.xml | 4 +-
src/mapi/glapi/gen/gl_genexec.py | 1 +
src/mesa/Makefile.sources | 2 +
src/mesa/main/api_loopback.c | 18 +
src/mesa/main/api_loopback.h | 6 +
src/mesa/main/bufferobj.c | 4 +-
src/mesa/main/context.c | 3 +
src/mesa/main/dd.h | 19 +
src/mesa/main/mtypes.h | 86 ++
src/mesa/main/samplerobj.c | 48 ++
src/mesa/main/shared.c | 12 +
src/mesa/main/tests/dispatch_sanity.cpp | 18 +
src/mesa/main/teximage.c | 25 +-
src/mesa/main/texobj.c | 12 +
src/mesa/main/texparam.c | 61 ++
src/mesa/main/texstate.c | 52 +-
src/mesa/main/texturebindless.c | 902 ++++++++++++++++++++
src/mesa/main/texturebindless.h | 96 +++
src/mesa/main/uniform_query.cpp | 208 ++++-
src/mesa/main/uniforms.c | 119 ++-
src/mesa/main/uniforms.h | 16 +
src/mesa/main/varray.c | 23 +
src/mesa/main/varray.h | 3 +
src/mesa/main/vtxfmt.c | 4 +
src/mesa/program/ir_to_mesa.cpp | 36 +-
src/mesa/program/ir_to_mesa.h | 4 +-
src/mesa/program/program.c | 8 +
src/mesa/state_tracker/st_atifs_to_tgsi.c | 2 +-
src/mesa/state_tracker/st_atom_constbuf.c | 6 +
src/mesa/state_tracker/st_atom_image.c | 33 +-
src/mesa/state_tracker/st_atom_sampler.c | 32 +-
src/mesa/state_tracker/st_atom_texture.c | 15 +-
src/mesa/state_tracker/st_cb_texture.c | 84 ++
src/mesa/state_tracker/st_context.c | 2 +
src/mesa/state_tracker/st_context.h | 11 +
src/mesa/state_tracker/st_extensions.c | 1 +
src/mesa/state_tracker/st_glsl_to_nir.cpp | 3 +-
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 138 ++-
src/mesa/state_tracker/st_mesa_to_tgsi.c | 2 +-
src/mesa/state_tracker/st_pbo.c | 2 +-
src/mesa/state_tracker/st_sampler_view.c | 6 +
src/mesa/state_tracker/st_shader_cache.c | 3 +-
src/mesa/state_tracker/st_texture.c | 213 +++++
src/mesa/state_tracker/st_texture.h | 28 +
src/mesa/vbo/vbo_attrib_tmp.h | 28 +
src/mesa/vbo/vbo_context.h | 2 +
src/mesa/vbo/vbo_exec_api.c | 15 +-
src/mesa/vbo/vbo_save_api.c | 3 +
97 files changed, 4250 insertions(+), 260 deletions(-)
create mode 100644 src/mapi/glapi/gen/ARB_bindless_texture.xml
create mode 100644 src/mesa/main/texturebindless.c
create mode 100644 src/mesa/main/texturebindless.h
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
Samuel Pitoiset
2017-05-22 08:21:53 UTC
Permalink
Post by Nicolai Hähnle
Post by Samuel Pitoiset
Hi,
This series implements ARB_bindless_texture for RadeonSI.
Reminder: the GLSL compiler part is already upstream.
This series has been mainly tested with Feral games, here's the list of
- DXMD
- Hitman
- Dirt Rally
- Mad Max
Today, Feral announced "Warhammer 40,000: Dawn of War III" (called DOW3) which
is going to be released next month. This game *requires*
ARB_bindless_texture,
that now explains why I did all this work. :-) So, we have ~3 weeks for merging
this whole series. It would be very nice to have DOW3 support at day one!
=== Tracking bindless problems ===
- Dirt Rally
- Hitman
- Mad Max
- DOW3
- No rendering issues
- No VM faults (ie. amdgpu.vm_debug=1)
However, DXMD is currently broken because the bindless_sampler layout qualifier
is missing, which ends up by reporting a ton of INVALID_OPERATION errors. Note
that Feral implemented bindless support against NV_bindless_texture and not
ARB_bindless_texture. The main difference is that bindless_sampler is implicit
for NV_* while it's required for ARB_*. Feral plan to fix this soon.
All ARB_bindless_texture piglit tests pass with this series.
=== Tracking regressions/changes ===
- No regressions with the Intel CI system
- One piglit regression that needs to be fixed
(arb_texture_multisample-sample-position)
- No shader-db changes
- No CPU overhead (glxgears and Heaven in low)
=== Performance results for DOW3 ===
- mode 1: all bindless (ie. no bound samplers)
- mode 2: bound/bindless (ie. only bindless when the limit is reached)
NVIDIA blob: 381.22
== GTX 1060 ==
- mode 1: 89 FPS
- mode 2: 51 FPS
- mode 1: 49 FPS
- mode 2: 28 FPS
- mode 1: 32 FPS
- mode 2: 19 FPS
The GTX 1060 performs very well with the all bindless mode (default), while
the bound/bindless mode is not good at all.
== RX480 ==
- mode 1: 67 FPS (-32%)
- mode 2: 75 FPS (+32%)
- mode 1: 38 FPS (-28%)
- mode 2: 44 FPS (+57%)
- mode 1: 26 FPS (-23%)
- mode 2: 29 FPS (+52%)
What do the numbers in parenthesis mean? Relative to the GTX 1060?
Exactly.
Post by Nicolai Hähnle
Out of curiosity, did you do your tests with threaded gallium? I imagine
that it could help a lot already since it pushes the buffer handling
onto the gallium thread. And I guess it could be pushed further into the
CS submit thread.
Yes, but I don't see any performance differences with threaded gallium.
Post by Nicolai Hähnle
Anyway, this is all very nice! While I've obviously seen a lot of bits
and pieces, I'll get to reviewing the whole series in earnest soon :-)
Cool, thanks! :)
Post by Nicolai Hähnle
Cheers,
Nicolai
Post by Samuel Pitoiset
The RX 480 performs very well with the bound/bindless mode (default), while
the all bindless mode still has to be improved.
The most important bottleneck with the all bindless mode is the number of
buffers that have to be added for every command stream. The overhead in the
winsys and in the kernel (amdgpu_cs_ioctl) becomes important in this situation.
This mode is still clearly CPU bound and should be improved (see the "Future
work" section).
Btw, without any optimisations, it was around 35FPS in low (mode 1).
=== Performance results for other Feral titles ===
I didn't record any numbers because these games have been initially
developed/tested against the NVIDIA blob which it's unaffected by a VERY huge
number of resident handles. While the AMD stack is really slow in this
situation. Though, as I said, all Feral games that use bindless work fine, we
just need to improve perf on both sides.
=== Future work ===
I have some ideas to try in order to improve performance with
RadeonSI. I will
work on this once this series is upstream.
Please review,
Thanks!
mapi: add GL_ARB_bindless_texture entry points
mesa: implement ARB_bindless_texture
mesa: add support for unsigned 64-bit vertex attributes
mesa: add support for glUniformHandleui64*ARB()
mesa: refuse to update sampler parameters when a handle is allocated
mesa: refuse to update tex parameters when a handle is allocated
mesa: refuse to change textures when a handle is allocated
mesa: refuse to change tex buffers when a handle is allocated
mesa: keep track of the current variable in add_uniform_to_shader
mesa: store bindless samplers as PROGRAM_UNIFORM
mesa: add infrastructure for bindless samplers/images bound to units
glsl: process uniform samplers declared bindless
glsl: process uniform images declared bindless
glsl: pass the ir_variable object to set_opaque_binding()
glsl: set the explicit binding value for bindless samplers/images
glsl: add ir_variable::is_bindless()
mesa: add update_single_shader_texture_used() helper
mesa: add update_single_program_texture_state() helper
mesa: update textures for bindless samplers bound to texture units
mesa: pass gl_program to _mesa_associate_uniform_storage()
mesa: associate uniform storage to bindless samplers/images
mesa: handle bindless uniforms bound to texture/image units
mesa: get rid of a workaround for bindless in _mesa_get_uniform()
gallium: add PIPE_CAP_BINDLESS_TEXTURE
gallium: add ARB_bindless_texture interface
ddebug: add ARB_bindless_texture support
trace: add ARB_bindless_texture support
tc: add ARB_bindless_texture support
tgsi: add new Bindless flag to tgsi_instruction_texture
tgsi: add new Bindless flag to tgsi_instruction_memory
tgsi/ureg: accept TGSI_FILE_{CONSTANT,INPUT} for dst registers
st/glsl_to_tgsi: add support for bindless samplers
st/glsl_to_tgsi: add support for bindless images
st/glsl_to_tgsi: add support for bindless pack/unpack operations
st/glsl_to_tgsi: teach the DCE pass about bindless samplers/images
st/glsl_to_tgsi: teach rename_temp_registers() about bindless samplers
tgsi/scan: record bindless samplers/images usage
st/mesa: implement ARB_bindless_texture
st/mesa: make update_single_texture() non-static
st/mesa: make convert_sampler_from_unit() non-static
st/mesa: add st_convert_image_from_unit() helper
st/mesa: add st_create_{texture,image}_handle_from_unit() helper
st/mesa: add infrastructure for storing bound texture/image handles
st/mesa: make bindless samplers/images bound to units resident
st/mesa: do not release sampler views for resident textures
st/mesa: disable per-context seamless cubemap when using texture
handles
st/mesa: enable ARB_bindless_texture
radeonsi: add a slab allocator for resident descriptors
radeonsi: add si_init_descriptor_list() helper
radeonsi: add si_set_sampler_view_desc() helper
radeonsi: add si_set_shader_image_desc() helper
radeonsi: implement ARB_bindless_texture
radeonsi: add all resident buffers to the current CS
radeonsi: only add descriptors in presence of resident handles
radeonsi: add si_update_check_render_feedback() helper
radeonsi: decompress DCC for resident textures/images
radeonsi: decompress resident textures/images before graphics/compute
radeonsi: isolate real framebuffer changes from the decompression
passes
radeonsi: track use of bindless samplers/images from tgsi_shader_info
radeonsi: only decompress resident textures/images when used
radeonsi: upload new descriptors when resident buffers are invalidated
radeonsi: invalidate buffers which are made resident if needed
radeonsi: add support for loading bindless samplers
radeonsi: add support for loading bindless images
radeonsi: enable ARB_bindless_texture
docs/features.txt | 2 +-
docs/relnotes/17.2.0.html | 1 +
src/compiler/glsl/ir.h | 11 +
src/compiler/glsl/ir_uniform.h | 12 +
src/compiler/glsl/link_uniform_initializers.cpp | 42 +-
src/compiler/glsl/link_uniforms.cpp | 156 +++-
src/compiler/glsl/shader_cache.cpp | 47 +
src/gallium/auxiliary/tgsi/tgsi_build.c | 8 +
src/gallium/auxiliary/tgsi/tgsi_scan.c | 37 +
src/gallium/auxiliary/tgsi/tgsi_scan.h | 2 +
src/gallium/auxiliary/tgsi/tgsi_ureg.c | 21 +-
src/gallium/auxiliary/tgsi/tgsi_ureg.h | 16 +-
src/gallium/auxiliary/util/u_threaded_context.c | 147 ++++
.../auxiliary/util/u_threaded_context_calls.h | 4 +
src/gallium/docs/source/screen.rst | 2 +
src/gallium/drivers/ddebug/dd_context.c | 61 ++
src/gallium/drivers/etnaviv/etnaviv_screen.c | 1 +
src/gallium/drivers/freedreno/freedreno_screen.c | 1 +
src/gallium/drivers/i915/i915_screen.c | 1 +
src/gallium/drivers/llvmpipe/lp_screen.c | 1 +
src/gallium/drivers/nouveau/nv30/nv30_screen.c | 1 +
src/gallium/drivers/nouveau/nv50/nv50_screen.c | 1 +
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 1 +
src/gallium/drivers/r300/r300_screen.c | 1 +
src/gallium/drivers/r600/r600_pipe.c | 1 +
src/gallium/drivers/radeon/r600_pipe_common.h | 4 +
src/gallium/drivers/radeonsi/si_blit.c | 131 ++-
src/gallium/drivers/radeonsi/si_compute.c | 2 +
src/gallium/drivers/radeonsi/si_compute.h | 14 +
src/gallium/drivers/radeonsi/si_descriptors.c | 943
+++++++++++++++++++--
src/gallium/drivers/radeonsi/si_hw_context.c | 1 +
src/gallium/drivers/radeonsi/si_pipe.c | 25 +
src/gallium/drivers/radeonsi/si_pipe.h | 68 ++
src/gallium/drivers/radeonsi/si_shader.h | 12 +
src/gallium/drivers/radeonsi/si_shader_tgsi_mem.c | 48 +-
src/gallium/drivers/radeonsi/si_state.c | 10 +-
src/gallium/drivers/radeonsi/si_state.h | 9 +
src/gallium/drivers/softpipe/sp_screen.c | 1 +
src/gallium/drivers/svga/svga_screen.c | 1 +
src/gallium/drivers/swr/swr_screen.cpp | 1 +
src/gallium/drivers/trace/tr_context.c | 114 +++
src/gallium/drivers/vc4/vc4_screen.c | 1 +
src/gallium/drivers/virgl/virgl_screen.c | 1 +
src/gallium/include/pipe/p_context.h | 16 +
src/gallium/include/pipe/p_defines.h | 1 +
src/gallium/include/pipe/p_shader_tokens.h | 6 +-
src/mapi/glapi/gen/ARB_bindless_texture.xml | 100 +++
src/mapi/glapi/gen/Makefile.am | 1 +
src/mapi/glapi/gen/apiexec.py | 3 +
src/mapi/glapi/gen/gl_API.xml | 4 +-
src/mapi/glapi/gen/gl_genexec.py | 1 +
src/mesa/Makefile.sources | 2 +
src/mesa/main/api_loopback.c | 18 +
src/mesa/main/api_loopback.h | 6 +
src/mesa/main/bufferobj.c | 4 +-
src/mesa/main/context.c | 3 +
src/mesa/main/dd.h | 19 +
src/mesa/main/mtypes.h | 86 ++
src/mesa/main/samplerobj.c | 48 ++
src/mesa/main/shared.c | 12 +
src/mesa/main/tests/dispatch_sanity.cpp | 18 +
src/mesa/main/teximage.c | 25 +-
src/mesa/main/texobj.c | 12 +
src/mesa/main/texparam.c | 61 ++
src/mesa/main/texstate.c | 52 +-
src/mesa/main/texturebindless.c | 902
++++++++++++++++++++
src/mesa/main/texturebindless.h | 96 +++
src/mesa/main/uniform_query.cpp | 208 ++++-
src/mesa/main/uniforms.c | 119 ++-
src/mesa/main/uniforms.h | 16 +
src/mesa/main/varray.c | 23 +
src/mesa/main/varray.h | 3 +
src/mesa/main/vtxfmt.c | 4 +
src/mesa/program/ir_to_mesa.cpp | 36 +-
src/mesa/program/ir_to_mesa.h | 4 +-
src/mesa/program/program.c | 8 +
src/mesa/state_tracker/st_atifs_to_tgsi.c | 2 +-
src/mesa/state_tracker/st_atom_constbuf.c | 6 +
src/mesa/state_tracker/st_atom_image.c | 33 +-
src/mesa/state_tracker/st_atom_sampler.c | 32 +-
src/mesa/state_tracker/st_atom_texture.c | 15 +-
src/mesa/state_tracker/st_cb_texture.c | 84 ++
src/mesa/state_tracker/st_context.c | 2 +
src/mesa/state_tracker/st_context.h | 11 +
src/mesa/state_tracker/st_extensions.c | 1 +
src/mesa/state_tracker/st_glsl_to_nir.cpp | 3 +-
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 138 ++-
src/mesa/state_tracker/st_mesa_to_tgsi.c | 2 +-
src/mesa/state_tracker/st_pbo.c | 2 +-
src/mesa/state_tracker/st_sampler_view.c | 6 +
src/mesa/state_tracker/st_shader_cache.c | 3 +-
src/mesa/state_tracker/st_texture.c | 213 +++++
src/mesa/state_tracker/st_texture.h | 28 +
src/mesa/vbo/vbo_attrib_tmp.h | 28 +
src/mesa/vbo/vbo_context.h | 2 +
src/mesa/vbo/vbo_exec_api.c | 15 +-
src/mesa/vbo/vbo_save_api.c | 3 +
97 files changed, 4250 insertions(+), 260 deletions(-)
create mode 100644 src/mapi/glapi/gen/ARB_bindless_texture.xml
create mode 100644 src/mesa/main/texturebindless.c
create mode 100644 src/mesa/main/texturebindless.h
Dieter Nützel
2017-05-22 22:33:58 UTC
Permalink
Hello Samuel,

running this on radeonsi/RX580.
Didn't saw better numbers for Wine/TS2017 (TrainSimulator 2017) ever
before.
But didn't feaguered if it (can) use bindless (with Wine/stagging). Do
we have a knob to toggle bindless on and off?
A key from Feral for DiRT Rally or the like would be very nice (my son
would go crazy). - He (nine years old) love (car) simulators. ~50 € is
much for 'testing'...

So got my

Tested-by: Dieter Nützel <***@nuetzel-hh.de>

Here come some output from 'ogl-samples'

/opt/ogl-samples> ./build/release/gl-420-primitive-bindless-nv
ATTENTION: default value of option mesa_glthread overridden by
environment.
OpenGL Version Needed 4.2 ( 4.5 Found )
Failed to find Extension: "GL_NV_shader_buffer_load"
Running Test
Test Ended
/opt/ogl-samples> ./build/release/gl-420-texture-bindless-nv
ATTENTION: default value of option mesa_glthread overridden by
environment.
OpenGL Version Needed 4.2 ( 4.5 Found )
Failed to find Extension: "GL_NV_bindless_texture"
Running Test
Test Ended

GL_ARB_bindless_texture 'faking' needed?

Dieter
Post by Samuel Pitoiset
Hi,
This series implements ARB_bindless_texture for RadeonSI.
Reminder: the GLSL compiler part is already upstream.
This series has been mainly tested with Feral games, here's the list of
- DXMD
- Hitman
- Dirt Rally
- Mad Max
Today, Feral announced "Warhammer 40,000: Dawn of War III" (called DOW3) which
is going to be released next month. This game *requires*
ARB_bindless_texture,
that now explains why I did all this work. :-) So, we have ~3 weeks for merging
this whole series. It would be very nice to have DOW3 support at day one!
Loading...