summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2015-08-25 17:12:03 -0700
committerJason Ekstrand <[email protected]>2015-08-25 18:41:21 -0700
commit9b387b5d3f4103c51079ea5298d33086af6da433 (patch)
tree4127f2284b6b4a5746bbc01bbfc6a97305057cb4
parent5360edcb304e147341b934567f3bbf40e9d5a3b5 (diff)
parent1d2a844e7d55645ea3d24fb589bec03695b3d2b1 (diff)
Merge remote-tracking branch 'mesa-public/master' into vulkan
-rw-r--r--Makefile.am4
-rw-r--r--VERSION2
-rw-r--r--configure.ac6
-rw-r--r--docs/GL3.txt6
-rw-r--r--docs/index.html6
-rw-r--r--docs/relnotes.html1
-rw-r--r--docs/relnotes/10.6.5.html124
-rw-r--r--docs/relnotes/11.0.0.html7
-rw-r--r--docs/relnotes/11.1.0.html60
-rw-r--r--include/GL/glext.h294
-rwxr-xr-xscons/gallium.py1
-rw-r--r--src/egl/SConscript1
-rw-r--r--src/egl/drivers/dri2/platform_drm.c10
-rw-r--r--src/egl/drivers/dri2/platform_wayland.c4
-rw-r--r--src/gallium/auxiliary/nir/tgsi_to_nir.c58
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_text.c23
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c54
-rw-r--r--src/gallium/auxiliary/util/u_blitter.h3
-rw-r--r--src/gallium/auxiliary/util/u_surface.c3
-rw-r--r--src/gallium/drivers/freedreno/a2xx/a2xx.xml.h4
-rw-r--r--src/gallium/drivers/freedreno/a3xx/a3xx.xml.h23
-rw-r--r--src/gallium/drivers/freedreno/a3xx/fd3_format.c11
-rw-r--r--src/gallium/drivers/freedreno/a3xx/fd3_rasterizer.c2
-rw-r--r--src/gallium/drivers/freedreno/a3xx/fd3_texture.c3
-rw-r--r--src/gallium/drivers/freedreno/a4xx/a4xx.xml.h12
-rw-r--r--src/gallium/drivers/freedreno/a4xx/fd4_emit.h1
-rw-r--r--src/gallium/drivers/freedreno/a4xx/fd4_format.c10
-rw-r--r--src/gallium/drivers/freedreno/a4xx/fd4_gmem.c22
-rw-r--r--src/gallium/drivers/freedreno/a4xx/fd4_program.c7
-rw-r--r--src/gallium/drivers/freedreno/a4xx/fd4_texture.c4
-rw-r--r--src/gallium/drivers/freedreno/adreno_common.xml.h4
-rw-r--r--src/gallium/drivers/freedreno/adreno_pm4.xml.h4
-rw-r--r--src/gallium/drivers/freedreno/freedreno_context.c4
-rw-r--r--src/gallium/drivers/freedreno/freedreno_fence.c25
-rw-r--r--src/gallium/drivers/freedreno/freedreno_fence.h5
-rw-r--r--src/gallium/drivers/freedreno/freedreno_resource.c9
-rw-r--r--src/gallium/drivers/freedreno/freedreno_screen.c10
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c13
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_nir_lower_if_else.c1
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_ra.c2
-rw-r--r--src/gallium/drivers/i915/i915_surface.c3
-rw-r--r--src/gallium/drivers/nouveau/Makefile.sources3
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir.h8
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp1
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp2
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp21
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp12
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_gm107.cpp90
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp4
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h7
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp253
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp5
-rw-r--r--src/gallium/drivers/nouveau/codegen/unordered_set.h48
-rw-r--r--src/gallium/drivers/nouveau/nouveau_compiler.c4
-rw-r--r--src/gallium/drivers/nouveau/nv50/nv50_state.c10
-rw-r--r--src/gallium/drivers/nouveau/nv50/nv50_state_validate.c22
-rw-r--r--src/gallium/drivers/nouveau/nv50/nv50_stateobj.h2
-rw-r--r--src/gallium/drivers/nouveau/nv50/nv50_surface.c20
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_context.c25
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_context.h3
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_program.c17
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c7
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_state.c12
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c21
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_stateobj.h2
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_surface.c15
-rw-r--r--src/gallium/drivers/r300/compiler/radeon_pair_regalloc.c3
-rw-r--r--src/gallium/drivers/r300/r300_blit.c3
-rw-r--r--src/gallium/drivers/r600/r600_blit.c3
-rw-r--r--src/gallium/drivers/r600/r600_isa.h2
-rw-r--r--src/gallium/drivers/r600/r600_pipe.h4
-rw-r--r--src/gallium/drivers/r600/r600_shader.c34
-rw-r--r--src/gallium/drivers/r600/r600_shader.h20
-rw-r--r--src/gallium/drivers/r600/r600_state_common.c42
-rw-r--r--src/gallium/drivers/radeon/radeon_uvd.c5
-rw-r--r--src/gallium/drivers/radeonsi/si_blit.c3
-rw-r--r--src/gallium/drivers/radeonsi/si_shader.c19
-rw-r--r--src/gallium/drivers/vc4/vc4_context.h1
-rw-r--r--src/gallium/drivers/vc4/vc4_opt_algebraic.c33
-rw-r--r--src/gallium/drivers/vc4/vc4_opt_copy_propagation.c22
-rw-r--r--src/gallium/drivers/vc4/vc4_opt_vpm_writes.c18
-rw-r--r--src/gallium/drivers/vc4/vc4_program.c96
-rw-r--r--src/gallium/drivers/vc4/vc4_qir.c38
-rw-r--r--src/gallium/drivers/vc4/vc4_qir.h47
-rw-r--r--src/gallium/drivers/vc4/vc4_qpu.h7
-rw-r--r--src/gallium/drivers/vc4/vc4_qpu_disasm.c16
-rw-r--r--src/gallium/drivers/vc4/vc4_qpu_emit.c63
-rw-r--r--src/gallium/drivers/vc4/vc4_register_allocate.c42
-rw-r--r--src/gallium/include/pipe/p_state.h1
-rw-r--r--src/gallium/state_trackers/clover/llvm/invocation.cpp33
-rw-r--r--src/gallium/state_trackers/nine/adapter9.c38
-rw-r--r--src/gallium/state_trackers/nine/basetexture9.c46
-rw-r--r--src/gallium/state_trackers/nine/basetexture9.h6
-rw-r--r--src/gallium/state_trackers/nine/cubetexture9.c27
-rw-r--r--src/gallium/state_trackers/nine/device9.c436
-rw-r--r--src/gallium/state_trackers/nine/device9.h13
-rw-r--r--src/gallium/state_trackers/nine/nine_ff.c381
-rw-r--r--src/gallium/state_trackers/nine/nine_ff.h81
-rw-r--r--src/gallium/state_trackers/nine/nine_pipe.c42
-rw-r--r--src/gallium/state_trackers/nine/nine_pipe.h67
-rw-r--r--src/gallium/state_trackers/nine/nine_shader.c307
-rw-r--r--src/gallium/state_trackers/nine/nine_shader.h49
-rw-r--r--src/gallium/state_trackers/nine/nine_state.c1096
-rw-r--r--src/gallium/state_trackers/nine/nine_state.h64
-rw-r--r--src/gallium/state_trackers/nine/pixelshader9.c42
-rw-r--r--src/gallium/state_trackers/nine/pixelshader9.h57
-rw-r--r--src/gallium/state_trackers/nine/resource9.c20
-rw-r--r--src/gallium/state_trackers/nine/stateblock9.c2
-rw-r--r--src/gallium/state_trackers/nine/surface9.c213
-rw-r--r--src/gallium/state_trackers/nine/surface9.h14
-rw-r--r--src/gallium/state_trackers/nine/swapchain9.c23
-rw-r--r--src/gallium/state_trackers/nine/texture9.c31
-rw-r--r--src/gallium/state_trackers/nine/vertexshader9.c33
-rw-r--r--src/gallium/state_trackers/nine/vertexshader9.h34
-rw-r--r--src/gallium/state_trackers/nine/volume9.c193
-rw-r--r--src/gallium/state_trackers/nine/volume9.h19
-rw-r--r--src/gallium/state_trackers/nine/volumetexture9.c18
-rw-r--r--src/gallium/targets/d3dadapter9/Makefile.am1
-rw-r--r--src/gallium/targets/d3dadapter9/description.c324
-rw-r--r--src/gallium/targets/d3dadapter9/drm.c76
-rw-r--r--src/gallium/targets/dri/Android.mk4
-rw-r--r--src/gallium/winsys/amdgpu/drm/Android.mk10
-rw-r--r--src/gallium/winsys/amdgpu/drm/Makefile.sources2
-rw-r--r--src/gallium/winsys/amdgpu/drm/amdgpu_cs.h4
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs.c8
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs.h2
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_winsys.c12
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_winsys.h1
-rw-r--r--src/gallium/winsys/sw/kms-dri/Makefile.am2
-rw-r--r--src/gbm/main/backend.c4
-rw-r--r--src/glsl/Makefile.sources3
-rw-r--r--src/glsl/ast_array_index.cpp15
-rw-r--r--src/glsl/ast_to_hir.cpp82
-rw-r--r--src/glsl/builtin_functions.cpp265
-rw-r--r--src/glsl/builtin_types.cpp32
-rw-r--r--src/glsl/builtin_variables.cpp24
-rw-r--r--src/glsl/glcpp/glcpp-parse.y3
-rw-r--r--src/glsl/glsl_lexer.ll41
-rw-r--r--src/glsl/glsl_parser.yy96
-rw-r--r--src/glsl/glsl_parser_extras.cpp3
-rw-r--r--src/glsl/glsl_parser_extras.h9
-rw-r--r--src/glsl/link_uniform_initializers.cpp29
-rw-r--r--src/glsl/linker.cpp2
-rw-r--r--src/glsl/lower_subroutine.cpp2
-rw-r--r--src/glsl/nir/glsl_to_nir.cpp35
-rw-r--r--src/glsl/nir/nir.c687
-rw-r--r--src/glsl/nir/nir.h44
-rw-r--r--src/glsl/nir/nir_control_flow.c769
-rw-r--r--src/glsl/nir/nir_control_flow.h251
-rw-r--r--src/glsl/nir/nir_control_flow_private.h37
-rw-r--r--src/glsl/nir/nir_dominance.c9
-rw-r--r--src/glsl/nir/nir_intrinsics.h32
-rw-r--r--src/glsl/nir/nir_lower_io.c277
-rw-r--r--src/glsl/nir/nir_lower_samplers.cpp6
-rw-r--r--src/glsl/nir/nir_lower_vars_to_ssa.c2
-rw-r--r--src/glsl/nir/nir_opt_algebraic.py2
-rw-r--r--src/glsl/nir/nir_opt_gcm.c2
-rw-r--r--src/glsl/nir/nir_opt_peephole_select.c1
-rw-r--r--src/glsl/nir/nir_spirv.h1
-rw-r--r--src/glsl/nir/nir_to_ssa.c2
-rw-r--r--src/glsl/nir/nir_validate.c95
-rw-r--r--src/glsl/nir/spirv2nir.c2
-rw-r--r--src/glsl/nir/spirv_to_nir.c4
-rw-r--r--src/glsl/opt_constant_propagation.cpp45
-rw-r--r--src/glsl/shader_enums.h310
-rw-r--r--src/glx/dri_common.c3
-rw-r--r--src/glx/dri_common_query_renderer.c2
-rw-r--r--src/glx/glxext.c3
-rw-r--r--src/mapi/glapi/gen/GL4x.xml6
-rw-r--r--src/mapi/glapi/gen/Makefile.am1
-rw-r--r--src/mesa/drivers/dri/common/drirc2
-rw-r--r--src/mesa/drivers/dri/common/utils.c2
-rw-r--r--src/mesa/drivers/dri/i915/intel_pixel_read.c2
-rw-r--r--src/mesa/drivers/dri/i915/intel_tex_image.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_conditional_render.c6
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw.c4
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw_upload.c41
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp58
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.h10
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_nir.cpp87
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp12
-rw-r--r--src/mesa/drivers/dri/i965/brw_misc_state.c3
-rw-r--r--src/mesa/drivers/dri/i965/brw_nir.c23
-rw-r--r--src/mesa/drivers/dri/i965/brw_primitive_restart.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_queryobj.c19
-rw-r--r--src/mesa/drivers/dri/i965/brw_shader.cpp20
-rw-r--r--src/mesa/drivers/dri/i965/brw_shader.h11
-rw-r--r--src/mesa/drivers/dri/i965/brw_state_cache.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_tex_layout.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4.h7
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_gs_nir.cpp4
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_nir.cpp51
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_reg_allocate.cpp7
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp48
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs_surface_state.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_state.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_surface_state.c8
-rw-r--r--src/mesa/drivers/dri/i965/gen6_vs_state.c2
-rw-r--r--src/mesa/drivers/dri/i965/gen7_sol_state.c2
-rw-r--r--src/mesa/drivers/dri/i965/gen8_draw_upload.c73
-rw-r--r--src/mesa/drivers/dri/i965/intel_extensions.c1
-rw-r--r--src/mesa/drivers/dri/i965/intel_fbo.c4
-rw-r--r--src/mesa/drivers/dri/i965/intel_screen.c8
-rw-r--r--src/mesa/main/bufferobj.c4
-rw-r--r--src/mesa/main/context.c4
-rw-r--r--src/mesa/main/extensions.c8
-rw-r--r--src/mesa/main/fbobject.c10
-rw-r--r--src/mesa/main/format_info.py12
-rw-r--r--src/mesa/main/format_utils.c2
-rw-r--r--src/mesa/main/formats.c258
-rw-r--r--src/mesa/main/formats.h10
-rw-r--r--src/mesa/main/get_hash_params.py2
-rw-r--r--src/mesa/main/mipmap.c2
-rw-r--r--src/mesa/main/mtypes.h17
-rw-r--r--src/mesa/main/multisample.c9
-rw-r--r--src/mesa/main/readpix.c2
-rw-r--r--src/mesa/main/shaderapi.c100
-rw-r--r--src/mesa/main/shaderimage.c150
-rw-r--r--src/mesa/main/shaderimage.h9
-rw-r--r--src/mesa/main/tests/Makefile.am1
-rw-r--r--src/mesa/main/tests/dispatch_sanity.cpp9
-rw-r--r--src/mesa/main/tests/mesa_formats.cpp139
-rw-r--r--src/mesa/main/texcompress.c30
-rw-r--r--src/mesa/main/texgetimage.c2
-rw-r--r--src/mesa/main/teximage.c190
-rw-r--r--src/mesa/main/teximage.h2
-rw-r--r--src/mesa/main/texobj.c15
-rw-r--r--src/mesa/main/texobj.h4
-rw-r--r--src/mesa/main/texparam.c38
-rw-r--r--src/mesa/main/texstorage.c37
-rw-r--r--src/mesa/main/texstorage.h21
-rw-r--r--src/mesa/main/texstore.c2
-rw-r--r--src/mesa/main/uniform_query.cpp25
-rw-r--r--src/mesa/main/uniforms.c9
-rw-r--r--src/mesa/program/prog_to_nir.c44
-rw-r--r--src/mesa/state_tracker/st_cb_blit.c1
-rw-r--r--src/mesa/state_tracker/st_cb_readpixels.c2
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c35
-rw-r--r--src/mesa/state_tracker/st_format.c2
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi.cpp14
-rw-r--r--src/mesa/swrast/s_drawpix.c2
-rw-r--r--src/util/bitset.h36
-rw-r--r--src/util/register_allocate.c62
-rw-r--r--src/util/register_allocate.h4
-rw-r--r--src/util/rounding.h3
-rw-r--r--src/vulkan/anv_compiler.cpp2
247 files changed, 7061 insertions, 3849 deletions
diff --git a/Makefile.am b/Makefile.am
index 9f49ce65353..149610c7c69 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,7 +32,9 @@ AM_DISTCHECK_CONFIGURE_FLAGS = \
--enable-vdpau \
--enable-xa \
--enable-xvmc \
- --with-egl-platforms=x11,wayland,drm
+ --with-egl-platforms=x11,wayland,drm \
+ --with-dri-drivers=i915,i965,nouveau,radeon,r200,swrast \
+ --with-gallium-drivers=i915,ilo,nouveau,r300,r600,radeonsi,freedreno,svga,swrast
ACLOCAL_AMFLAGS = -I m4
diff --git a/VERSION b/VERSION
index 2b1181ddc3f..8a1e8e32743 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-11.0.0-devel
+11.1.0-devel
diff --git a/configure.ac b/configure.ac
index 74e13b3fcb7..dd23ecadd08 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,7 +74,7 @@ LIBDRM_AMDGPU_REQUIRED=2.4.63
LIBDRM_INTEL_REQUIRED=2.4.61
LIBDRM_NVVIEUX_REQUIRED=2.4.33
LIBDRM_NOUVEAU_REQUIRED=2.4.62
-LIBDRM_FREEDRENO_REQUIRED=2.4.57
+LIBDRM_FREEDRENO_REQUIRED=2.4.64
DRI2PROTO_REQUIRED=2.6
DRI3PROTO_REQUIRED=1.0
PRESENTPROTO_REQUIRED=1.0
@@ -1639,6 +1639,10 @@ if test "x$enable_nine" = xyes; then
if test "x$with_gallium_drivers" = xswrast; then
AC_MSG_ERROR([nine requires at least one non-swrast gallium driver])
fi
+ if test $GCC_VERSION_MAJOR -lt 4 -o $GCC_VERSION_MAJOR -eq 4 -a $GCC_VERSION_MINOR -lt 6; then
+ AC_MSG_ERROR([gcc >= 4.6 is required to build nine])
+ fi
+
if test "x$enable_dri3" = xno; then
AC_MSG_WARN([using nine together with wine requires DRI3 enabled system])
fi
diff --git a/docs/GL3.txt b/docs/GL3.txt
index 54c0c5aa6a8..331b2daaeb6 100644
--- a/docs/GL3.txt
+++ b/docs/GL3.txt
@@ -163,7 +163,7 @@ GL 4.3, GLSL 4.30:
GL_ARB_multi_draw_indirect DONE (i965, nvc0, r600, radeonsi, llvmpipe, softpipe)
GL_ARB_program_interface_query DONE (all drivers)
GL_ARB_robust_buffer_access_behavior not started
- GL_ARB_shader_image_size in progress (Martin Peres)
+ GL_ARB_shader_image_size DONE (i965)
GL_ARB_shader_storage_buffer_object in progress (Iago Toral, Samuel Iglesias)
GL_ARB_stencil_texturing DONE (i965/gen8+, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe)
GL_ARB_texture_buffer_range DONE (nv50, nvc0, i965, r600, radeonsi, llvmpipe)
@@ -210,8 +210,8 @@ GLES3.1, GLSL ES 3.1
GL_ARB_framebuffer_no_attachments DONE (i965)
GL_ARB_program_interface_query DONE (all drivers)
GL_ARB_shader_atomic_counters DONE (i965)
- GL_ARB_shader_image_load_store in progress (curro)
- GL_ARB_shader_image_size in progress (Martin Peres)
+ GL_ARB_shader_image_load_store DONE (i965)
+ GL_ARB_shader_image_size DONE (i965)
GL_ARB_shader_storage_buffer_object in progress (Iago Toral, Samuel Iglesias)
GL_ARB_shading_language_packing DONE (all drivers)
GL_ARB_separate_shader_objects DONE (all drivers)
diff --git a/docs/index.html b/docs/index.html
index b9e6148914e..b067256d7b2 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -16,6 +16,12 @@
<h1>News</h1>
+<h2>August 22 2015</h2>
+<p>
+<a href="relnotes/10.6.5.html">Mesa 10.6.5</a> is released.
+This is a bug-fix release.
+</p>
+
<h2>August 11 2015</h2>
<p>
<a href="relnotes/10.6.4.html">Mesa 10.6.4</a> is released.
diff --git a/docs/relnotes.html b/docs/relnotes.html
index 39e7f61e792..2cc4701d3ff 100644
--- a/docs/relnotes.html
+++ b/docs/relnotes.html
@@ -21,6 +21,7 @@ The release notes summarize what's new or changed in each Mesa release.
</p>
<ul>
+<li><a href="relnotes/10.6.5.html">10.6.5 release notes</a>
<li><a href="relnotes/10.6.4.html">10.6.4 release notes</a>
<li><a href="relnotes/10.6.3.html">10.6.3 release notes</a>
<li><a href="relnotes/10.6.2.html">10.6.2 release notes</a>
diff --git a/docs/relnotes/10.6.5.html b/docs/relnotes/10.6.5.html
new file mode 100644
index 00000000000..e7326ff1941
--- /dev/null
+++ b/docs/relnotes/10.6.5.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <title>Mesa Release Notes</title>
+ <link rel="stylesheet" type="text/css" href="../mesa.css">
+</head>
+<body>
+
+<div class="header">
+ <h1>The Mesa 3D Graphics Library</h1>
+</div>
+
+<iframe src="../contents.html"></iframe>
+<div class="content">
+
+<h1>Mesa 10.6.5 Release Notes / August 22, 2015</h1>
+
+<p>
+Mesa 10.6.5 is a bug fix release which fixes bugs found since the 10.6.4 release.
+</p>
+<p>
+Mesa 10.6.5 implements the OpenGL 3.3 API, but the version reported by
+glGetString(GL_VERSION) or glGetIntegerv(GL_MAJOR_VERSION) /
+glGetIntegerv(GL_MINOR_VERSION) depends on the particular driver being used.
+Some drivers don't support all the features required in OpenGL 3.3. OpenGL
+3.3 is <strong>only</strong> available if requested at context creation
+because compatibility contexts are not supported.
+</p>
+
+
+<h2>SHA256 checksums</h2>
+<pre>
+afe290fc7af75a25df5ee52396a9f09e5dba85fb3e159304bdda265b8564b0d4 mesa-10.6.5.tar.gz
+fb6fac3c85bcfa9d06b8dd439169f23f0c0924a88e44362e738b99b1feff762f mesa-10.6.5.tar.xz
+</pre>
+
+
+<h2>New features</h2>
+<p>None</p>
+
+<h2>Bug fixes</h2>
+
+<p>This list is likely incomplete.</p>
+
+<ul>
+
+<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=85252">Bug 85252</a> - Segfault in compiler while processing ternary operator with void arguments</li>
+
+<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=91570">Bug 91570</a> - Upgrading mesa to 10.6 causes segfault in OpenGL applications with GeForce4 MX 440 / AGP 8X</li>
+
+<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=91610">Bug 91610</a> - [BSW] GPU hang for spec.shaders.point-vertex-id gl_instanceid divisor</li>
+
+</ul>
+
+
+<h2>Changes</h2>
+
+<p>Adam Jackson (1):</p>
+<ul>
+ <li>glx: Fix __glXWireToEvent for BufferSwapComplete</li>
+</ul>
+
+<p>Alex Deucher (2):</p>
+<ul>
+ <li>radeonsi: add new OLAND pci id</li>
+ <li>radeonsi: properly set the raster_config for KV</li>
+</ul>
+
+<p>Emil Velikov (4):</p>
+<ul>
+ <li>docs: add sha256 checksums for 10.6.4</li>
+ <li>vc4: add missing nir include, to fix the build</li>
+ <li>Revert "radeonsi: properly set the raster_config for KV"</li>
+ <li>Update version to 10.6.5</li>
+</ul>
+
+<p>Frank Binns (1):</p>
+<ul>
+ <li>egl/x11: don't abort when creating a DRI2 drawable fails</li>
+</ul>
+
+<p>Ilia Mirkin (3):</p>
+<ul>
+ <li>nouveau: no need to do tnl wakeup, state updates are always hooked up</li>
+ <li>gm107/ir: indirect handle goes first on maxwell also</li>
+ <li>nv50,nvc0: take level into account when doing eng2d multi-layer blits</li>
+</ul>
+
+<p>Jason Ekstrand (4):</p>
+<ul>
+ <li>meta/copy_image: Stash off the scissor</li>
+ <li>mesa/formats: Only do byteswapping for packed formats</li>
+ <li>mesa/formats: Fix swizzle flipping for big-endian targets</li>
+ <li>mesa/formats: Don't flip channels of null array formats</li>
+</ul>
+
+<p>Marek Olšák (3):</p>
+<ul>
+ <li>radeonsi: fix polygon offset scale</li>
+ <li>r600g: fix polygon offset scale</li>
+ <li>r600g: allow setting geometry shader sampler states</li>
+</ul>
+
+<p>Neil Roberts (1):</p>
+<ul>
+ <li>i965/bdw: Fix setting the instancing state for the SGVS element</li>
+</ul>
+
+<p>Oded Gabbay (2):</p>
+<ul>
+ <li>mesa: clear existing swizzle info before bitwise-OR</li>
+ <li>mesa/formats: don't byteswap when building array formats</li>
+</ul>
+
+<p>Renaud Gaubert (1):</p>
+<ul>
+ <li>glsl: avoid compiler's segfault when processing operators with void arguments</li>
+</ul>
+
+
+</div>
+</body>
+</html>
diff --git a/docs/relnotes/11.0.0.html b/docs/relnotes/11.0.0.html
index 75967ac7eec..537b88341b5 100644
--- a/docs/relnotes/11.0.0.html
+++ b/docs/relnotes/11.0.0.html
@@ -46,9 +46,12 @@ Note: some of the new features are only available with certain drivers.
<ul>
<li>New hardware support for AMD GCN 1.2 GPUs: Tonga, Iceland, Carrizo, Fiji</li>
<li>OpenGL 4.1 on radeonsi, nvc0</li>
+<li>OpenGL ES 3.0 on freedreno (a3xx, a4xx)
<li>GL_AMD_vertex_shader_viewport_index on radeonsi</li>
<li>GL_ARB_conditional_render_inverted on r600, radeonsi</li>
+<li>GL_ARB_depth_buffer_float on a4xx</li>
<li>GL_ARB_derivative_control on radeonsi</li>
+<li>GL_ARB_draw_buffers, GL_ARB_draw_buffers_blend on a4xx</li>
<li>GL_ARB_fragment_layer_viewport on radeonsi</li>
<li>GL_ARB_framebuffer_no_attachments on i965</li>
<li>GL_ARB_get_texture_sub_image for all drivers</li>
@@ -56,12 +59,15 @@ Note: some of the new features are only available with certain drivers.
<li>GL_ARB_gpu_shader_fp64 on llvmpipe, radeonsi</li>
<li>GL_ARB_shader_image_load_store on i965</li>
<li>GL_ARB_shader_precision on radeonsi, nvc0</li>
+<li>GL_ARB_shader_image_size on i965</li>
<li>GL_ARB_shader_stencil_export on llvmpipe</li>
<li>GL_ARB_shader_subroutine on core profile all drivers</li>
<li>GL_ARB_tessellation_shader on nvc0, radeonsi</li>
+<li>GL_ARB_transform_feedback2, GL_ARB_transform_feedback_instanced, GL_EXT_transform_feedback on a3xx, a4xx</li>
<li>GL_ARB_vertex_attrib_64bit on llvmpipe, radeonsi</li>
<li>GL_ARB_viewport_array on radeonsi</li>
<li>GL_EXT_depth_bounds_test on radeonsi, nv30, nv50, nvc0</li>
+<li>GL_EXT_texture_compression_s3tc on freedreno (a3xx)</li>
<li>GL_NV_read_depth (GLES) on all drivers</li>
<li>GL_NV_read_depth_stencil (GLES) on all drivers</li>
<li>GL_NV_read_stencil (GLES) on all drivers</li>
@@ -69,6 +75,7 @@ Note: some of the new features are only available with certain drivers.
<li>GL_OES_texture_half_float on all r300, r600, radeonsi, nv30, nv50, nvc0, softpipe, llvmpipe</li>
<li>GL_OES_texture_float_linear on all r300, r600, radeonsi, nv30, nv50, nvc0, softpipe, llvmpipe</li>
<li>GL_OES_texture_half_float_linear on all r300, r600, radeonsi, nv30, nv50, nvc0, softpipe, llvmpipe</li>
+<li>GL_EXT_draw_buffers2 on a4xx</li>
<li>GLX_ARB_create_context_robustness on r600, radeonsi</li>
<li>EGL_EXT_create_context_robustness on r600, radeonsi</li>
<li>EGL_KHR_gl_colorspace on r600, radeonsi, nv50, nvc0</li>
diff --git a/docs/relnotes/11.1.0.html b/docs/relnotes/11.1.0.html
new file mode 100644
index 00000000000..7f80206a9f2
--- /dev/null
+++ b/docs/relnotes/11.1.0.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <title>Mesa Release Notes</title>
+ <link rel="stylesheet" type="text/css" href="../mesa.css">
+</head>
+<body>
+
+<div class="header">
+ <h1>The Mesa 3D Graphics Library</h1>
+</div>
+
+<iframe src="../contents.html"></iframe>
+<div class="content">
+
+<h1>Mesa 11.1.0 Release Notes / TBD</h1>
+
+<p>
+Mesa 11.1.0 is a new development release.
+People who are concerned with stability and reliability should stick
+with a previous release or wait for Mesa 11.1.1.
+</p>
+<p>
+Mesa 11.1.0 implements the OpenGL 4.1 API, but the version reported by
+glGetString(GL_VERSION) or glGetIntegerv(GL_MAJOR_VERSION) /
+glGetIntegerv(GL_MINOR_VERSION) depends on the particular driver being used.
+Some drivers don't support all the features required in OpenGL 4.1. OpenGL
+4.1 is <strong>only</strong> available if requested at context creation
+because compatibility contexts are not supported.
+</p>
+
+
+<h2>SHA256 checksums</h2>
+<pre>
+TBD.
+</pre>
+
+
+<h2>New features</h2>
+
+<p>
+Note: some of the new features are only available with certain drivers.
+</p>
+
+<ul>
+TBD.
+</ul>
+
+<h2>Bug fixes</h2>
+
+TBD.
+
+<h2>Changes</h2>
+
+TBD.
+
+</div>
+</body>
+</html>
diff --git a/include/GL/glext.h b/include/GL/glext.h
index e5f1d891ec5..907a5826d71 100644
--- a/include/GL/glext.h
+++ b/include/GL/glext.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2014 The Khronos Group Inc.
+** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
@@ -33,7 +33,7 @@ extern "C" {
** used to make the header, and the header can be found at
** http://www.opengl.org/registry/
**
-** Khronos $Revision: 29735 $ on $Date: 2015-02-02 19:00:01 -0800 (Mon, 02 Feb 2015) $
+** Khronos $Revision: 31811 $ on $Date: 2015-08-10 17:01:11 +1000 (Mon, 10 Aug 2015) $
*/
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
@@ -53,7 +53,7 @@ extern "C" {
#define GLAPI extern
#endif
-#define GL_GLEXT_VERSION 20150202
+#define GL_GLEXT_VERSION 20150809
/* Generated C header for:
* API: gl
@@ -1041,6 +1041,22 @@ typedef unsigned short GLhalf;
#define GL_COLOR_ATTACHMENT13 0x8CED
#define GL_COLOR_ATTACHMENT14 0x8CEE
#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT16 0x8CF0
+#define GL_COLOR_ATTACHMENT17 0x8CF1
+#define GL_COLOR_ATTACHMENT18 0x8CF2
+#define GL_COLOR_ATTACHMENT19 0x8CF3
+#define GL_COLOR_ATTACHMENT20 0x8CF4
+#define GL_COLOR_ATTACHMENT21 0x8CF5
+#define GL_COLOR_ATTACHMENT22 0x8CF6
+#define GL_COLOR_ATTACHMENT23 0x8CF7
+#define GL_COLOR_ATTACHMENT24 0x8CF8
+#define GL_COLOR_ATTACHMENT25 0x8CF9
+#define GL_COLOR_ATTACHMENT26 0x8CFA
+#define GL_COLOR_ATTACHMENT27 0x8CFB
+#define GL_COLOR_ATTACHMENT28 0x8CFC
+#define GL_COLOR_ATTACHMENT29 0x8CFD
+#define GL_COLOR_ATTACHMENT30 0x8CFE
+#define GL_COLOR_ATTACHMENT31 0x8CFF
#define GL_DEPTH_ATTACHMENT 0x8D00
#define GL_STENCIL_ATTACHMENT 0x8D20
#define GL_FRAMEBUFFER 0x8D40
@@ -2859,6 +2875,17 @@ GLAPI void APIENTRY glTextureBarrier (void);
#define GL_ARB_ES3_1_compatibility 1
#endif /* GL_ARB_ES3_1_compatibility */
+#ifndef GL_ARB_ES3_2_compatibility
+#define GL_ARB_ES3_2_compatibility 1
+#define GL_PRIMITIVE_BOUNDING_BOX_ARB 0x92BE
+#define GL_MULTISAMPLE_LINE_WIDTH_RANGE_ARB 0x9381
+#define GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY_ARB 0x9382
+typedef void (APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXARBPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPrimitiveBoundingBoxARB (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#endif
+#endif /* GL_ARB_ES3_2_compatibility */
+
#ifndef GL_ARB_ES3_compatibility
#define GL_ARB_ES3_compatibility 1
#endif /* GL_ARB_ES3_compatibility */
@@ -3272,6 +3299,10 @@ GLAPI GLboolean APIENTRY glIsProgramARB (GLuint program);
#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
#endif /* GL_ARB_fragment_shader */
+#ifndef GL_ARB_fragment_shader_interlock
+#define GL_ARB_fragment_shader_interlock 1
+#endif /* GL_ARB_fragment_shader_interlock */
+
#ifndef GL_ARB_framebuffer_no_attachments
#define GL_ARB_framebuffer_no_attachments 1
#endif /* GL_ARB_framebuffer_no_attachments */
@@ -3332,6 +3363,91 @@ GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachmen
#define GL_ARB_gpu_shader_fp64 1
#endif /* GL_ARB_gpu_shader_fp64 */
+#ifndef GL_ARB_gpu_shader_int64
+#define GL_ARB_gpu_shader_int64 1
+#define GL_INT64_ARB 0x140E
+#define GL_INT64_VEC2_ARB 0x8FE9
+#define GL_INT64_VEC3_ARB 0x8FEA
+#define GL_INT64_VEC4_ARB 0x8FEB
+#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7
+typedef void (APIENTRYP PFNGLUNIFORM1I64ARBPROC) (GLint location, GLint64 x);
+typedef void (APIENTRYP PFNGLUNIFORM2I64ARBPROC) (GLint location, GLint64 x, GLint64 y);
+typedef void (APIENTRYP PFNGLUNIFORM3I64ARBPROC) (GLint location, GLint64 x, GLint64 y, GLint64 z);
+typedef void (APIENTRYP PFNGLUNIFORM4I64ARBPROC) (GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
+typedef void (APIENTRYP PFNGLUNIFORM1I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM2I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM3I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM4I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM1UI64ARBPROC) (GLint location, GLuint64 x);
+typedef void (APIENTRYP PFNGLUNIFORM2UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y);
+typedef void (APIENTRYP PFNGLUNIFORM3UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
+typedef void (APIENTRYP PFNGLUNIFORM4UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
+typedef void (APIENTRYP PFNGLUNIFORM1UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLGETUNIFORMI64VARBPROC) (GLuint program, GLint location, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMUI64VARBPROC) (GLuint program, GLint location, GLuint64 *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMI64VARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMUI64VARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint64 *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64ARBPROC) (GLuint program, GLint location, GLint64 x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64ARBPROC) (GLuint program, GLint location, GLuint64 x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniform1i64ARB (GLint location, GLint64 x);
+GLAPI void APIENTRY glUniform2i64ARB (GLint location, GLint64 x, GLint64 y);
+GLAPI void APIENTRY glUniform3i64ARB (GLint location, GLint64 x, GLint64 y, GLint64 z);
+GLAPI void APIENTRY glUniform4i64ARB (GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
+GLAPI void APIENTRY glUniform1i64vARB (GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glUniform2i64vARB (GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glUniform3i64vARB (GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glUniform4i64vARB (GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glUniform1ui64ARB (GLint location, GLuint64 x);
+GLAPI void APIENTRY glUniform2ui64ARB (GLint location, GLuint64 x, GLuint64 y);
+GLAPI void APIENTRY glUniform3ui64ARB (GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
+GLAPI void APIENTRY glUniform4ui64ARB (GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
+GLAPI void APIENTRY glUniform1ui64vARB (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glUniform2ui64vARB (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glUniform3ui64vARB (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glUniform4ui64vARB (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glGetUniformi64vARB (GLuint program, GLint location, GLint64 *params);
+GLAPI void APIENTRY glGetUniformui64vARB (GLuint program, GLint location, GLuint64 *params);
+GLAPI void APIENTRY glGetnUniformi64vARB (GLuint program, GLint location, GLsizei bufSize, GLint64 *params);
+GLAPI void APIENTRY glGetnUniformui64vARB (GLuint program, GLint location, GLsizei bufSize, GLuint64 *params);
+GLAPI void APIENTRY glProgramUniform1i64ARB (GLuint program, GLint location, GLint64 x);
+GLAPI void APIENTRY glProgramUniform2i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y);
+GLAPI void APIENTRY glProgramUniform3i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z);
+GLAPI void APIENTRY glProgramUniform4i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
+GLAPI void APIENTRY glProgramUniform1i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glProgramUniform2i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glProgramUniform3i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glProgramUniform4i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value);
+GLAPI void APIENTRY glProgramUniform1ui64ARB (GLuint program, GLint location, GLuint64 x);
+GLAPI void APIENTRY glProgramUniform2ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y);
+GLAPI void APIENTRY glProgramUniform3ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
+GLAPI void APIENTRY glProgramUniform4ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
+GLAPI void APIENTRY glProgramUniform1ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniform2ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniform3ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniform4ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value);
+#endif
+#endif /* GL_ARB_gpu_shader_int64 */
+
#ifndef GL_ARB_half_float_pixel
#define GL_ARB_half_float_pixel 1
typedef unsigned short GLhalfARB;
@@ -3711,6 +3827,16 @@ GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *par
#define GL_ARB_occlusion_query2 1
#endif /* GL_ARB_occlusion_query2 */
+#ifndef GL_ARB_parallel_shader_compile
+#define GL_ARB_parallel_shader_compile 1
+#define GL_MAX_SHADER_COMPILER_THREADS_ARB 0x91B0
+#define GL_COMPLETION_STATUS_ARB 0x91B1
+typedef void (APIENTRYP PFNGLMAXSHADERCOMPILERTHREADSARBPROC) (GLuint count);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMaxShaderCompilerThreadsARB (GLuint count);
+#endif
+#endif /* GL_ARB_parallel_shader_compile */
+
#ifndef GL_ARB_pipeline_statistics_query
#define GL_ARB_pipeline_statistics_query 1
#define GL_VERTICES_SUBMITTED_ARB 0x82EE
@@ -3753,6 +3879,10 @@ GLAPI void APIENTRY glPointParameterfvARB (GLenum pname, const GLfloat *params);
#define GL_COORD_REPLACE_ARB 0x8862
#endif /* GL_ARB_point_sprite */
+#ifndef GL_ARB_post_depth_coverage
+#define GL_ARB_post_depth_coverage 1
+#endif /* GL_ARB_post_depth_coverage */
+
#ifndef GL_ARB_program_interface_query
#define GL_ARB_program_interface_query 1
#endif /* GL_ARB_program_interface_query */
@@ -3826,6 +3956,26 @@ GLAPI void APIENTRY glGetnMinmaxARB (GLenum target, GLboolean reset, GLenum form
#define GL_ARB_robustness_isolation 1
#endif /* GL_ARB_robustness_isolation */
+#ifndef GL_ARB_sample_locations
+#define GL_ARB_sample_locations 1
+#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB 0x933D
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB 0x933E
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB 0x933F
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB 0x9340
+#define GL_SAMPLE_LOCATION_ARB 0x8E50
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB 0x9341
+#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB 0x9342
+#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB 0x9343
+typedef void (APIENTRYP PFNGLFRAMEBUFFERSAMPLELOCATIONSFVARBPROC) (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVARBPROC) (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLEVALUATEDEPTHVALUESARBPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFramebufferSampleLocationsfvARB (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glNamedFramebufferSampleLocationsfvARB (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glEvaluateDepthValuesARB (void);
+#endif
+#endif /* GL_ARB_sample_locations */
+
#ifndef GL_ARB_sample_shading
#define GL_ARB_sample_shading 1
#define GL_SAMPLE_SHADING_ARB 0x8C36
@@ -3852,14 +4002,26 @@ GLAPI void APIENTRY glMinSampleShadingARB (GLfloat value);
#define GL_ARB_separate_shader_objects 1
#endif /* GL_ARB_separate_shader_objects */
+#ifndef GL_ARB_shader_atomic_counter_ops
+#define GL_ARB_shader_atomic_counter_ops 1
+#endif /* GL_ARB_shader_atomic_counter_ops */
+
#ifndef GL_ARB_shader_atomic_counters
#define GL_ARB_shader_atomic_counters 1
#endif /* GL_ARB_shader_atomic_counters */
+#ifndef GL_ARB_shader_ballot
+#define GL_ARB_shader_ballot 1
+#endif /* GL_ARB_shader_ballot */
+
#ifndef GL_ARB_shader_bit_encoding
#define GL_ARB_shader_bit_encoding 1
#endif /* GL_ARB_shader_bit_encoding */
+#ifndef GL_ARB_shader_clock
+#define GL_ARB_shader_clock 1
+#endif /* GL_ARB_shader_clock */
+
#ifndef GL_ARB_shader_draw_parameters
#define GL_ARB_shader_draw_parameters 1
#endif /* GL_ARB_shader_draw_parameters */
@@ -4029,6 +4191,10 @@ GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GL
#define GL_ARB_shader_texture_lod 1
#endif /* GL_ARB_shader_texture_lod */
+#ifndef GL_ARB_shader_viewport_layer_array
+#define GL_ARB_shader_viewport_layer_array 1
+#endif /* GL_ARB_shader_viewport_layer_array */
+
#ifndef GL_ARB_shading_language_100
#define GL_ARB_shading_language_100 1
#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
@@ -4102,12 +4268,20 @@ GLAPI void APIENTRY glNamedBufferPageCommitmentARB (GLuint buffer, GLintptr offs
#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB 0x9199
#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB 0x919A
#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB 0x91A9
-typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
#ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
#endif
#endif /* GL_ARB_sparse_texture */
+#ifndef GL_ARB_sparse_texture2
+#define GL_ARB_sparse_texture2 1
+#endif /* GL_ARB_sparse_texture2 */
+
+#ifndef GL_ARB_sparse_texture_clamp
+#define GL_ARB_sparse_texture_clamp 1
+#endif /* GL_ARB_sparse_texture_clamp */
+
#ifndef GL_ARB_stencil_texturing
#define GL_ARB_stencil_texturing 1
#endif /* GL_ARB_stencil_texturing */
@@ -4260,6 +4434,12 @@ GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, void
#define GL_DOT3_RGBA_ARB 0x86AF
#endif /* GL_ARB_texture_env_dot3 */
+#ifndef GL_ARB_texture_filter_minmax
+#define GL_ARB_texture_filter_minmax 1
+#define GL_TEXTURE_REDUCTION_MODE_ARB 0x9366
+#define GL_WEIGHTED_AVERAGE_ARB 0x9367
+#endif /* GL_ARB_texture_filter_minmax */
+
#ifndef GL_ARB_texture_float
#define GL_ARB_texture_float 1
#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
@@ -4754,6 +4934,11 @@ GLAPI void APIENTRY glBlendBarrierKHR (void);
#define GL_KHR_debug 1
#endif /* GL_KHR_debug */
+#ifndef GL_KHR_no_error
+#define GL_KHR_no_error 1
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
+#endif /* GL_KHR_no_error */
+
#ifndef GL_KHR_robust_buffer_access_behavior
#define GL_KHR_robust_buffer_access_behavior 1
#endif /* GL_KHR_robust_buffer_access_behavior */
@@ -4896,7 +5081,6 @@ typedef void (APIENTRYP PFNGLPOINTPARAMETERXVOESPROC) (GLenum pname, const GLfix
typedef void (APIENTRYP PFNGLPOINTSIZEXOESPROC) (GLfixed size);
typedef void (APIENTRYP PFNGLPOLYGONOFFSETXOESPROC) (GLfixed factor, GLfixed units);
typedef void (APIENTRYP PFNGLROTATEXOESPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
-typedef void (APIENTRYP PFNGLSAMPLECOVERAGEOESPROC) (GLfixed value, GLboolean invert);
typedef void (APIENTRYP PFNGLSCALEXOESPROC) (GLfixed x, GLfixed y, GLfixed z);
typedef void (APIENTRYP PFNGLTEXENVXOESPROC) (GLenum target, GLenum pname, GLfixed param);
typedef void (APIENTRYP PFNGLTEXENVXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
@@ -5001,7 +5185,6 @@ GLAPI void APIENTRY glPointParameterxvOES (GLenum pname, const GLfixed *params);
GLAPI void APIENTRY glPointSizexOES (GLfixed size);
GLAPI void APIENTRY glPolygonOffsetxOES (GLfixed factor, GLfixed units);
GLAPI void APIENTRY glRotatexOES (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
-GLAPI void APIENTRY glSampleCoverageOES (GLfixed value, GLboolean invert);
GLAPI void APIENTRY glScalexOES (GLfixed x, GLfixed y, GLfixed z);
GLAPI void APIENTRY glTexEnvxOES (GLenum target, GLenum pname, GLfixed param);
GLAPI void APIENTRY glTexEnvxvOES (GLenum target, GLenum pname, const GLfixed *params);
@@ -6715,7 +6898,7 @@ typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) (GLuint vaob
typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor);
typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
-typedef void (APIENTRYP PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+typedef void (APIENTRYP PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC) (GLuint vaobj, GLuint index, GLuint divisor);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glMatrixLoadfEXT (GLenum mode, const GLfloat *m);
@@ -6971,7 +7154,7 @@ GLAPI void APIENTRY glVertexArrayVertexAttribLFormatEXT (GLuint vaobj, GLuint at
GLAPI void APIENTRY glVertexArrayVertexAttribBindingEXT (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
GLAPI void APIENTRY glVertexArrayVertexBindingDivisorEXT (GLuint vaobj, GLuint bindingindex, GLuint divisor);
GLAPI void APIENTRY glVertexArrayVertexAttribLOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
-GLAPI void APIENTRY glTexturePageCommitmentEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+GLAPI void APIENTRY glTexturePageCommitmentEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
GLAPI void APIENTRY glVertexArrayVertexAttribDivisorEXT (GLuint vaobj, GLuint index, GLuint divisor);
#endif
#endif /* GL_EXT_direct_state_access */
@@ -8635,6 +8818,14 @@ GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRG
#define GL_INTEL_fragment_shader_ordering 1
#endif /* GL_INTEL_fragment_shader_ordering */
+#ifndef GL_INTEL_framebuffer_CMAA
+#define GL_INTEL_framebuffer_CMAA 1
+typedef void (APIENTRYP PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glApplyFramebufferAttachmentCMAAINTEL (void);
+#endif
+#endif /* GL_INTEL_framebuffer_CMAA */
+
#ifndef GL_INTEL_map_texture
#define GL_INTEL_map_texture 1
#define GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF
@@ -8939,6 +9130,65 @@ GLAPI void APIENTRY glBlendBarrierNV (void);
#define GL_NV_blend_square 1
#endif /* GL_NV_blend_square */
+#ifndef GL_NV_command_list
+#define GL_NV_command_list 1
+#define GL_TERMINATE_SEQUENCE_COMMAND_NV 0x0000
+#define GL_NOP_COMMAND_NV 0x0001
+#define GL_DRAW_ELEMENTS_COMMAND_NV 0x0002
+#define GL_DRAW_ARRAYS_COMMAND_NV 0x0003
+#define GL_DRAW_ELEMENTS_STRIP_COMMAND_NV 0x0004
+#define GL_DRAW_ARRAYS_STRIP_COMMAND_NV 0x0005
+#define GL_DRAW_ELEMENTS_INSTANCED_COMMAND_NV 0x0006
+#define GL_DRAW_ARRAYS_INSTANCED_COMMAND_NV 0x0007
+#define GL_ELEMENT_ADDRESS_COMMAND_NV 0x0008
+#define GL_ATTRIBUTE_ADDRESS_COMMAND_NV 0x0009
+#define GL_UNIFORM_ADDRESS_COMMAND_NV 0x000A
+#define GL_BLEND_COLOR_COMMAND_NV 0x000B
+#define GL_STENCIL_REF_COMMAND_NV 0x000C
+#define GL_LINE_WIDTH_COMMAND_NV 0x000D
+#define GL_POLYGON_OFFSET_COMMAND_NV 0x000E
+#define GL_ALPHA_REF_COMMAND_NV 0x000F
+#define GL_VIEWPORT_COMMAND_NV 0x0010
+#define GL_SCISSOR_COMMAND_NV 0x0011
+#define GL_FRONT_FACE_COMMAND_NV 0x0012
+typedef void (APIENTRYP PFNGLCREATESTATESNVPROC) (GLsizei n, GLuint *states);
+typedef void (APIENTRYP PFNGLDELETESTATESNVPROC) (GLsizei n, const GLuint *states);
+typedef GLboolean (APIENTRYP PFNGLISSTATENVPROC) (GLuint state);
+typedef void (APIENTRYP PFNGLSTATECAPTURENVPROC) (GLuint state, GLenum mode);
+typedef GLuint (APIENTRYP PFNGLGETCOMMANDHEADERNVPROC) (GLenum tokenID, GLuint size);
+typedef GLushort (APIENTRYP PFNGLGETSTAGEINDEXNVPROC) (GLenum shadertype);
+typedef void (APIENTRYP PFNGLDRAWCOMMANDSNVPROC) (GLenum primitiveMode, GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, GLuint count);
+typedef void (APIENTRYP PFNGLDRAWCOMMANDSADDRESSNVPROC) (GLenum primitiveMode, const GLuint64 *indirects, const GLsizei *sizes, GLuint count);
+typedef void (APIENTRYP PFNGLDRAWCOMMANDSSTATESNVPROC) (GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count);
+typedef void (APIENTRYP PFNGLDRAWCOMMANDSSTATESADDRESSNVPROC) (const GLuint64 *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count);
+typedef void (APIENTRYP PFNGLCREATECOMMANDLISTSNVPROC) (GLsizei n, GLuint *lists);
+typedef void (APIENTRYP PFNGLDELETECOMMANDLISTSNVPROC) (GLsizei n, const GLuint *lists);
+typedef GLboolean (APIENTRYP PFNGLISCOMMANDLISTNVPROC) (GLuint list);
+typedef void (APIENTRYP PFNGLLISTDRAWCOMMANDSSTATESCLIENTNVPROC) (GLuint list, GLuint segment, const void **indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count);
+typedef void (APIENTRYP PFNGLCOMMANDLISTSEGMENTSNVPROC) (GLuint list, GLuint segments);
+typedef void (APIENTRYP PFNGLCOMPILECOMMANDLISTNVPROC) (GLuint list);
+typedef void (APIENTRYP PFNGLCALLCOMMANDLISTNVPROC) (GLuint list);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCreateStatesNV (GLsizei n, GLuint *states);
+GLAPI void APIENTRY glDeleteStatesNV (GLsizei n, const GLuint *states);
+GLAPI GLboolean APIENTRY glIsStateNV (GLuint state);
+GLAPI void APIENTRY glStateCaptureNV (GLuint state, GLenum mode);
+GLAPI GLuint APIENTRY glGetCommandHeaderNV (GLenum tokenID, GLuint size);
+GLAPI GLushort APIENTRY glGetStageIndexNV (GLenum shadertype);
+GLAPI void APIENTRY glDrawCommandsNV (GLenum primitiveMode, GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, GLuint count);
+GLAPI void APIENTRY glDrawCommandsAddressNV (GLenum primitiveMode, const GLuint64 *indirects, const GLsizei *sizes, GLuint count);
+GLAPI void APIENTRY glDrawCommandsStatesNV (GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count);
+GLAPI void APIENTRY glDrawCommandsStatesAddressNV (const GLuint64 *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count);
+GLAPI void APIENTRY glCreateCommandListsNV (GLsizei n, GLuint *lists);
+GLAPI void APIENTRY glDeleteCommandListsNV (GLsizei n, const GLuint *lists);
+GLAPI GLboolean APIENTRY glIsCommandListNV (GLuint list);
+GLAPI void APIENTRY glListDrawCommandsStatesClientNV (GLuint list, GLuint segment, const void **indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count);
+GLAPI void APIENTRY glCommandListSegmentsNV (GLuint list, GLuint segments);
+GLAPI void APIENTRY glCompileCommandListNV (GLuint list);
+GLAPI void APIENTRY glCallCommandListNV (GLuint list);
+#endif
+#endif /* GL_NV_command_list */
+
#ifndef GL_NV_compute_program5
#define GL_NV_compute_program5 1
#define GL_COMPUTE_PROGRAM_NV 0x90FB
@@ -8971,6 +9221,17 @@ GLAPI void APIENTRY glSubpixelPrecisionBiasNV (GLuint xbits, GLuint ybits);
#endif
#endif /* GL_NV_conservative_raster */
+#ifndef GL_NV_conservative_raster_dilate
+#define GL_NV_conservative_raster_dilate 1
+#define GL_CONSERVATIVE_RASTER_DILATE_NV 0x9379
+#define GL_CONSERVATIVE_RASTER_DILATE_RANGE_NV 0x937A
+#define GL_CONSERVATIVE_RASTER_DILATE_GRANULARITY_NV 0x937B
+typedef void (APIENTRYP PFNGLCONSERVATIVERASTERPARAMETERFNVPROC) (GLenum pname, GLfloat value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glConservativeRasterParameterfNV (GLenum pname, GLfloat value);
+#endif
+#endif /* GL_NV_conservative_raster_dilate */
+
#ifndef GL_NV_copy_depth_to_color
#define GL_NV_copy_depth_to_color 1
#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
@@ -10850,6 +11111,21 @@ GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot
#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983
#endif /* GL_OML_subsample */
+#ifndef GL_OVR_multiview
+#define GL_OVR_multiview 1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
+#define GL_MAX_VIEWS_OVR 0x9631
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+#endif
+#endif /* GL_OVR_multiview */
+
+#ifndef GL_OVR_multiview2
+#define GL_OVR_multiview2 1
+#endif /* GL_OVR_multiview2 */
+
#ifndef GL_PGI_misc_hints
#define GL_PGI_misc_hints 1
#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8
diff --git a/scons/gallium.py b/scons/gallium.py
index 51b84d7652b..46dbf0ebd0e 100755
--- a/scons/gallium.py
+++ b/scons/gallium.py
@@ -300,6 +300,7 @@ def generate(env):
# C preprocessor options
cppdefines = []
+ cppdefines += ['__STDC_LIMIT_MACROS']
if env['build'] in ('debug', 'checked'):
cppdefines += ['DEBUG']
else:
diff --git a/src/egl/SConscript b/src/egl/SConscript
index 1b2a4271ef7..f8102db6f3a 100644
--- a/src/egl/SConscript
+++ b/src/egl/SConscript
@@ -15,7 +15,6 @@ env.Append(CPPPATH = [
# parse Makefile.sources
egl_sources = env.ParseSourceList('Makefile.sources', 'LIBEGL_C_FILES')
-egl_sources.append(env.ParseSourceList('Makefile.sources', 'dri2_backend_core_FILES'))
env.Append(CPPDEFINES = [
'_EGL_NATIVE_PLATFORM=_EGL_PLATFORM_HAIKU',
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index a439a3be6b6..eda50875e02 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -68,7 +68,7 @@ release_buffer(struct gbm_surface *_surf, struct gbm_bo *bo)
{
struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
struct dri2_egl_surface *dri2_surf = surf->dri_private;
- int i;
+ unsigned i;
for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
if (dri2_surf->color_buffers[i].bo == bo) {
@@ -82,7 +82,7 @@ has_free_buffers(struct gbm_surface *_surf)
{
struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
struct dri2_egl_surface *dri2_surf = surf->dri_private;
- int i;
+ unsigned i;
for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
if (!dri2_surf->color_buffers[i].locked)
@@ -189,7 +189,7 @@ dri2_drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
- int i;
+ unsigned i;
if (!_eglPutSurface(surf))
return EGL_TRUE;
@@ -218,7 +218,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
struct dri2_egl_display *dri2_dpy =
dri2_egl_display(dri2_surf->base.Resource.Display);
struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
- int i;
+ unsigned i;
if (dri2_surf->back == NULL) {
for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
@@ -414,7 +414,7 @@ dri2_drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
- int i;
+ unsigned i;
if (dri2_dpy->swrast) {
(*dri2_dpy->core->swapBuffers)(dri2_surf->dri_drawable);
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index dabaf1ebbd1..dbc64ba2d8a 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -1227,6 +1227,8 @@ dri2_wl_swrast_get_stride_for_format(int format, int w)
* Taken from weston shared/os-compatibility.c
*/
+#ifndef HAVE_MKOSTEMP
+
static int
set_cloexec_or_close(int fd)
{
@@ -1249,6 +1251,8 @@ err:
return -1;
}
+#endif
+
/*
* Taken from weston shared/os-compatibility.c
*/
diff --git a/src/gallium/auxiliary/nir/tgsi_to_nir.c b/src/gallium/auxiliary/nir/tgsi_to_nir.c
index 93dfb803389..278d5e9bf5b 100644
--- a/src/gallium/auxiliary/nir/tgsi_to_nir.c
+++ b/src/gallium/auxiliary/nir/tgsi_to_nir.c
@@ -24,6 +24,7 @@
#include "util/ralloc.h"
#include "glsl/nir/nir.h"
+#include "glsl/nir/nir_control_flow.h"
#include "glsl/nir/nir_builder.h"
#include "glsl/list.h"
#include "glsl/shader_enums.h"
@@ -307,7 +308,7 @@ ttn_emit_immediate(struct ttn_compile *c)
for (i = 0; i < 4; i++)
load_const->value.u[i] = tgsi_imm->u[i].Uint;
- nir_instr_insert_after_cf_list(b->cf_node_list, &load_const->instr);
+ nir_builder_instr_insert(b, &load_const->instr);
}
static nir_src
@@ -363,7 +364,7 @@ ttn_src_for_file_and_index(struct ttn_compile *c, unsigned file, unsigned index,
load->variables[0] = ttn_array_deref(c, load, var, offset, indirect);
nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
- nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+ nir_builder_instr_insert(b, &load->instr);
src = nir_src_for_ssa(&load->dest.ssa);
@@ -414,7 +415,7 @@ ttn_src_for_file_and_index(struct ttn_compile *c, unsigned file, unsigned index,
load->num_components = ncomp;
nir_ssa_dest_init(&load->instr, &load->dest, ncomp, NULL);
- nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+ nir_builder_instr_insert(b, &load->instr);
src = nir_src_for_ssa(&load->dest.ssa);
break;
@@ -476,7 +477,7 @@ ttn_src_for_file_and_index(struct ttn_compile *c, unsigned file, unsigned index,
srcn++;
}
nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
- nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+ nir_builder_instr_insert(b, &load->instr);
src = nir_src_for_ssa(&load->dest.ssa);
break;
@@ -552,7 +553,7 @@ ttn_get_dest(struct ttn_compile *c, struct tgsi_full_dst_register *tgsi_fdst)
load->dest = nir_dest_for_reg(reg);
- nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+ nir_builder_instr_insert(b, &load->instr);
} else {
assert(!tgsi_dst->Indirect);
dest.dest.reg.reg = c->temp_regs[index].reg;
@@ -667,7 +668,7 @@ ttn_alu(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
instr->src[i].src = nir_src_for_ssa(src[i]);
instr->dest = dest;
- nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+ nir_builder_instr_insert(b, &instr->instr);
}
static void
@@ -683,7 +684,7 @@ ttn_move_dest_masked(nir_builder *b, nir_alu_dest dest,
mov->src[0].src = nir_src_for_ssa(def);
for (unsigned i = def->num_components; i < 4; i++)
mov->src[0].swizzle[i] = def->num_components - 1;
- nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr);
+ nir_builder_instr_insert(b, &mov->instr);
}
static void
@@ -902,7 +903,7 @@ ttn_kill(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
{
nir_intrinsic_instr *discard =
nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard);
- nir_instr_insert_after_cf_list(b->cf_node_list, &discard->instr);
+ nir_builder_instr_insert(b, &discard->instr);
}
static void
@@ -912,7 +913,7 @@ ttn_kill_if(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
nir_intrinsic_instr *discard =
nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard_if);
discard->src[0] = nir_src_for_ssa(cmp);
- nir_instr_insert_after_cf_list(b->cf_node_list, &discard->instr);
+ nir_builder_instr_insert(b, &discard->instr);
}
static void
@@ -976,14 +977,14 @@ static void
ttn_cont(nir_builder *b)
{
nir_jump_instr *instr = nir_jump_instr_create(b->shader, nir_jump_continue);
- nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+ nir_builder_instr_insert(b, &instr->instr);
}
static void
ttn_brk(nir_builder *b)
{
nir_jump_instr *instr = nir_jump_instr_create(b->shader, nir_jump_break);
- nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+ nir_builder_instr_insert(b, &instr->instr);
}
static void
@@ -1279,7 +1280,7 @@ ttn_tex(struct ttn_compile *c, nir_alu_dest dest, nir_ssa_def **src)
assert(src_number == num_srcs);
nir_ssa_dest_init(&instr->instr, &instr->dest, 4, NULL);
- nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+ nir_builder_instr_insert(b, &instr->instr);
/* Resolve the writemask on the texture op. */
ttn_move_dest(b, dest, &instr->dest.ssa);
@@ -1318,10 +1319,10 @@ ttn_txq(struct ttn_compile *c, nir_alu_dest dest, nir_ssa_def **src)
txs->src[0].src_type = nir_tex_src_lod;
nir_ssa_dest_init(&txs->instr, &txs->dest, 3, NULL);
- nir_instr_insert_after_cf_list(b->cf_node_list, &txs->instr);
+ nir_builder_instr_insert(b, &txs->instr);
nir_ssa_dest_init(&qlv->instr, &qlv->dest, 1, NULL);
- nir_instr_insert_after_cf_list(b->cf_node_list, &qlv->instr);
+ nir_builder_instr_insert(b, &qlv->instr);
ttn_move_dest_masked(b, dest, &txs->dest.ssa, TGSI_WRITEMASK_XYZ);
ttn_move_dest_masked(b, dest, &qlv->dest.ssa, TGSI_WRITEMASK_W);
@@ -1730,7 +1731,7 @@ ttn_emit_instruction(struct ttn_compile *c)
store->variables[0] = ttn_array_deref(c, store, var, offset, indirect);
store->src[0] = nir_src_for_reg(dest.dest.reg.reg);
- nir_instr_insert_after_cf_list(b->cf_node_list, &store->instr);
+ nir_builder_instr_insert(b, &store->instr);
}
}
@@ -1759,11 +1760,26 @@ ttn_add_output_stores(struct ttn_compile *c)
store->const_index[0] = loc;
store->src[0].reg.reg = c->output_regs[loc].reg;
store->src[0].reg.base_offset = c->output_regs[loc].offset;
- nir_instr_insert_after_cf_list(b->cf_node_list, &store->instr);
+ nir_builder_instr_insert(b, &store->instr);
}
}
}
+static gl_shader_stage
+tgsi_processor_to_shader_stage(unsigned processor)
+{
+ switch (processor) {
+ case TGSI_PROCESSOR_FRAGMENT: return MESA_SHADER_FRAGMENT;
+ case TGSI_PROCESSOR_VERTEX: return MESA_SHADER_VERTEX;
+ case TGSI_PROCESSOR_GEOMETRY: return MESA_SHADER_GEOMETRY;
+ case TGSI_PROCESSOR_TESS_CTRL: return MESA_SHADER_TESS_CTRL;
+ case TGSI_PROCESSOR_TESS_EVAL: return MESA_SHADER_TESS_EVAL;
+ case TGSI_PROCESSOR_COMPUTE: return MESA_SHADER_COMPUTE;
+ default:
+ unreachable("invalid TGSI processor");
+ };
+}
+
struct nir_shader *
tgsi_to_nir(const void *tgsi_tokens,
const nir_shader_compiler_options *options)
@@ -1775,7 +1791,12 @@ tgsi_to_nir(const void *tgsi_tokens,
int ret;
c = rzalloc(NULL, struct ttn_compile);
- s = nir_shader_create(NULL, options);
+
+ tgsi_scan_shader(tgsi_tokens, &scan);
+ c->scan = &scan;
+
+ s = nir_shader_create(NULL, tgsi_processor_to_shader_stage(scan.processor),
+ options);
nir_function *func = nir_function_create(s, "main");
nir_function_overload *overload = nir_function_overload_create(func);
@@ -1784,9 +1805,6 @@ tgsi_to_nir(const void *tgsi_tokens,
nir_builder_init(&c->build, impl);
nir_builder_insert_after_cf_list(&c->build, &impl->body);
- tgsi_scan_shader(tgsi_tokens, &scan);
- c->scan = &scan;
-
s->num_inputs = scan.file_max[TGSI_FILE_INPUT] + 1;
s->num_uniforms = scan.const_file_max[0] + 1;
s->num_outputs = scan.file_max[TGSI_FILE_OUTPUT] + 1;
diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c
index a6675c5168d..3e3ed5b19d1 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_text.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_text.c
@@ -259,7 +259,7 @@ struct translate_ctx
struct tgsi_token *tokens_end;
struct tgsi_header *header;
unsigned processor : 4;
- int implied_array_size : 5;
+ unsigned implied_array_size : 6;
unsigned num_immediates;
};
@@ -675,6 +675,9 @@ parse_register_dcl(
eat_opt_white( &cur );
if (cur[0] == '[') {
+ bool is_in = *file == TGSI_FILE_INPUT;
+ bool is_out = *file == TGSI_FILE_OUTPUT;
+
++cur;
ctx->cur = cur;
if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
@@ -684,7 +687,11 @@ parse_register_dcl(
* input primitive. so we want to declare just
* the index relevant to the semantics which is in
* the second bracket */
- if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
+
+ /* tessellation has similar constraints to geometry shader */
+ if ((ctx->processor == TGSI_PROCESSOR_GEOMETRY && is_in) ||
+ (ctx->processor == TGSI_PROCESSOR_TESS_EVAL && is_in) ||
+ (ctx->processor == TGSI_PROCESSOR_TESS_CTRL && (is_in || is_out))) {
brackets[0] = brackets[1];
*num_brackets = 1;
} else {
@@ -740,6 +747,14 @@ parse_dst_operand(
dst->Dimension.Indirect = 0;
dst->Dimension.Dimension = 0;
dst->Dimension.Index = bracket[0].index;
+
+ if (bracket[0].ind_file != TGSI_FILE_NULL) {
+ dst->Dimension.Indirect = 1;
+ dst->DimIndirect.File = bracket[0].ind_file;
+ dst->DimIndirect.Index = bracket[0].ind_index;
+ dst->DimIndirect.Swizzle = bracket[0].ind_comp;
+ dst->DimIndirect.ArrayID = bracket[0].ind_array;
+ }
bracket[0] = bracket[1];
}
dst->Register.Index = bracket[0].index;
@@ -1623,6 +1638,10 @@ static boolean translate( struct translate_ctx *ctx )
if (!parse_header( ctx ))
return FALSE;
+ if (ctx->processor == TGSI_PROCESSOR_TESS_CTRL ||
+ ctx->processor == TGSI_PROCESSOR_TESS_EVAL)
+ ctx->implied_array_size = 32;
+
while (*ctx->cur != '\0') {
uint label_val = 0;
if (!eat_white( &ctx->cur )) {
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 85206eab1a7..9bba07aa18e 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -104,7 +104,7 @@ struct blitter_context_priv
void *fs_resolve_uint[PIPE_MAX_TEXTURE_TYPES][NUM_RESOLVE_FRAG_SHADERS][2];
/* Blend state. */
- void *blend[PIPE_MASK_RGBA+1]; /**< blend state with writemask */
+ void *blend[PIPE_MASK_RGBA+1][2]; /**< blend state with writemask */
void *blend_clear[GET_CLEAR_BLEND_STATE_IDX(PIPE_CLEAR_COLOR)+1];
/* Depth stencil alpha state. */
@@ -159,7 +159,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
struct pipe_rasterizer_state rs_state;
struct pipe_sampler_state sampler_state;
struct pipe_vertex_element velem[2];
- unsigned i;
+ unsigned i, j;
ctx = CALLOC_STRUCT(blitter_context_priv);
if (!ctx)
@@ -208,8 +208,20 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
memset(&blend, 0, sizeof(blend));
for (i = 0; i <= PIPE_MASK_RGBA; i++) {
- blend.rt[0].colormask = i;
- ctx->blend[i] = pipe->create_blend_state(pipe, &blend);
+ for (j = 0; j < 2; j++) {
+ memset(&blend.rt[0], 0, sizeof(blend.rt[0]));
+ blend.rt[0].colormask = i;
+ if (j) {
+ blend.rt[0].blend_enable = 1;
+ blend.rt[0].rgb_func = PIPE_BLEND_ADD;
+ blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
+ blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ blend.rt[0].alpha_func = PIPE_BLEND_ADD;
+ blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
+ blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ }
+ ctx->blend[i][j] = pipe->create_blend_state(pipe, &blend);
+ }
}
/* depth stencil alpha state objects */
@@ -409,9 +421,10 @@ void util_blitter_destroy(struct blitter_context *blitter)
struct pipe_context *pipe = blitter->pipe;
int i, j, f;
- for (i = 0; i <= PIPE_MASK_RGBA; i++) {
- pipe->delete_blend_state(pipe, ctx->blend[i]);
- }
+ for (i = 0; i <= PIPE_MASK_RGBA; i++)
+ for (j = 0; j < 2; j++)
+ pipe->delete_blend_state(pipe, ctx->blend[i][j]);
+
for (i = 0; i < Elements(ctx->blend_clear); i++) {
if (ctx->blend_clear[i])
pipe->delete_blend_state(pipe, ctx->blend_clear[i]);
@@ -1217,7 +1230,7 @@ static void *get_clear_blend_state(struct blitter_context_priv *ctx,
/* Return an existing blend state. */
if (!clear_buffers)
- return ctx->blend[0];
+ return ctx->blend[0][0];
index = GET_CLEAR_BLEND_STATE_IDX(clear_buffers);
@@ -1483,7 +1496,8 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
/* Copy. */
util_blitter_blit_generic(blitter, dst_view, &dstbox,
src_view, srcbox, src->width0, src->height0,
- PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL);
+ PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL,
+ FALSE);
pipe_surface_reference(&dst_view, NULL);
pipe_sampler_view_reference(&src_view, NULL);
@@ -1496,7 +1510,8 @@ void util_blitter_blit_generic(struct blitter_context *blitter,
const struct pipe_box *srcbox,
unsigned src_width0, unsigned src_height0,
unsigned mask, unsigned filter,
- const struct pipe_scissor_state *scissor)
+ const struct pipe_scissor_state *scissor,
+ boolean alpha_blend)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
@@ -1550,7 +1565,7 @@ void util_blitter_blit_generic(struct blitter_context *blitter,
fb_state.zsbuf = NULL;
if (blit_depth || blit_stencil) {
- pipe->bind_blend_state(pipe, ctx->blend[0]);
+ pipe->bind_blend_state(pipe, ctx->blend[0][0]);
if (blit_depth && blit_stencil) {
pipe->bind_depth_stencil_alpha_state(pipe,
@@ -1573,7 +1588,9 @@ void util_blitter_blit_generic(struct blitter_context *blitter,
}
} else {
- pipe->bind_blend_state(pipe, ctx->blend[mask & PIPE_MASK_RGBA]);
+ unsigned colormask = mask & PIPE_MASK_RGBA;
+
+ pipe->bind_blend_state(pipe, ctx->blend[colormask][alpha_blend]);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
ctx->bind_fs_state(pipe,
blitter_get_fs_texfetch_col(ctx, src->format, src_target,
@@ -1786,7 +1803,8 @@ util_blitter_blit(struct blitter_context *blitter,
util_blitter_blit_generic(blitter, dst_view, &info->dst.box,
src_view, &info->src.box, src->width0, src->height0,
info->mask, info->filter,
- info->scissor_enable ? &info->scissor : NULL);
+ info->scissor_enable ? &info->scissor : NULL,
+ info->alpha_blend);
pipe_surface_reference(&dst_view, NULL);
pipe_sampler_view_reference(&src_view, NULL);
@@ -1815,7 +1833,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
blitter_disable_render_cond(ctx);
/* bind states */
- pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]);
+ pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
bind_fs_write_one_cbuf(ctx);
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
@@ -1867,7 +1885,7 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
blitter_disable_render_cond(ctx);
/* bind states */
- pipe->bind_blend_state(pipe, ctx->blend[0]);
+ pipe->bind_blend_state(pipe, ctx->blend[0][0]);
if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
sr.ref_value[0] = stencil & 0xff;
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
@@ -1933,8 +1951,8 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
blitter_disable_render_cond(ctx);
/* bind states */
- pipe->bind_blend_state(pipe, cbsurf ? ctx->blend[PIPE_MASK_RGBA] :
- ctx->blend[0]);
+ pipe->bind_blend_state(pipe, cbsurf ? ctx->blend[PIPE_MASK_RGBA][0] :
+ ctx->blend[0][0]);
pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
if (cbsurf)
bind_fs_write_one_cbuf(ctx);
@@ -2187,7 +2205,7 @@ void util_blitter_custom_color(struct blitter_context *blitter,
/* bind states */
pipe->bind_blend_state(pipe, custom_blend ? custom_blend
- : ctx->blend[PIPE_MASK_RGBA]);
+ : ctx->blend[PIPE_MASK_RGBA][0]);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
bind_fs_write_one_cbuf(ctx);
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h
index 0cd173d6284..becdb029f13 100644
--- a/src/gallium/auxiliary/util/u_blitter.h
+++ b/src/gallium/auxiliary/util/u_blitter.h
@@ -246,7 +246,8 @@ void util_blitter_blit_generic(struct blitter_context *blitter,
const struct pipe_box *srcbox,
unsigned src_width0, unsigned src_height0,
unsigned mask, unsigned filter,
- const struct pipe_scissor_state *scissor);
+ const struct pipe_scissor_state *scissor,
+ boolean alpha_blend);
void util_blitter_blit(struct blitter_context *blitter,
const struct pipe_blit_info *info);
diff --git a/src/gallium/auxiliary/util/u_surface.c b/src/gallium/auxiliary/util/u_surface.c
index 654b5bbc552..70ed911b7f1 100644
--- a/src/gallium/auxiliary/util/u_surface.c
+++ b/src/gallium/auxiliary/util/u_surface.c
@@ -676,6 +676,9 @@ util_try_blit_via_copy_region(struct pipe_context *ctx,
return FALSE;
}
+ if (blit->alpha_blend)
+ return FALSE;
+
ctx->resource_copy_region(ctx, blit->dst.resource, blit->dst.level,
blit->dst.box.x, blit->dst.box.y, blit->dst.box.z,
blit->src.resource, blit->src.level,
diff --git a/src/gallium/drivers/freedreno/a2xx/a2xx.xml.h b/src/gallium/drivers/freedreno/a2xx/a2xx.xml.h
index c4516baf2ec..dd489568a77 100644
--- a/src/gallium/drivers/freedreno/a2xx/a2xx.xml.h
+++ b/src/gallium/drivers/freedreno/a2xx/a2xx.xml.h
@@ -13,8 +13,8 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63728 bytes, from 2015-08-05 18:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63915 bytes, from 2015-08-24 16:56:28)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <[email protected]> (robclark)
diff --git a/src/gallium/drivers/freedreno/a3xx/a3xx.xml.h b/src/gallium/drivers/freedreno/a3xx/a3xx.xml.h
index 8e8cf6a03f2..441bfec5756 100644
--- a/src/gallium/drivers/freedreno/a3xx/a3xx.xml.h
+++ b/src/gallium/drivers/freedreno/a3xx/a3xx.xml.h
@@ -13,8 +13,8 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63728 bytes, from 2015-08-05 18:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63915 bytes, from 2015-08-24 16:56:28)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <[email protected]> (robclark)
@@ -326,6 +326,13 @@ enum a3xx_tex_type {
A3XX_TEX_3D = 3,
};
+enum a3xx_tex_msaa {
+ A3XX_TPL1_MSAA1X = 0,
+ A3XX_TPL1_MSAA2X = 1,
+ A3XX_TPL1_MSAA4X = 2,
+ A3XX_TPL1_MSAA8X = 3,
+};
+
#define A3XX_INT0_RBBM_GPU_IDLE 0x00000001
#define A3XX_INT0_RBBM_AHB_ERROR 0x00000002
#define A3XX_INT0_RBBM_REG_TIMEOUT 0x00000004
@@ -2652,6 +2659,7 @@ static inline uint32_t A3XX_VGT_DRAW_INITIATOR_NUM_INSTANCES(uint32_t val)
#define REG_A3XX_VGT_IMMED_DATA 0x000021fd
#define REG_A3XX_TEX_SAMP_0 0x00000000
+#define A3XX_TEX_SAMP_0_CLAMPENABLE 0x00000001
#define A3XX_TEX_SAMP_0_MIPFILTER_LINEAR 0x00000002
#define A3XX_TEX_SAMP_0_XY_MAG__MASK 0x0000000c
#define A3XX_TEX_SAMP_0_XY_MAG__SHIFT 2
@@ -2695,6 +2703,7 @@ static inline uint32_t A3XX_TEX_SAMP_0_COMPARE_FUNC(enum adreno_compare_func val
{
return ((val) << A3XX_TEX_SAMP_0_COMPARE_FUNC__SHIFT) & A3XX_TEX_SAMP_0_COMPARE_FUNC__MASK;
}
+#define A3XX_TEX_SAMP_0_CUBEMAPSEAMLESSFILTOFF 0x01000000
#define A3XX_TEX_SAMP_0_UNNORM_COORDS 0x80000000
#define REG_A3XX_TEX_SAMP_1 0x00000001
@@ -2750,6 +2759,12 @@ static inline uint32_t A3XX_TEX_CONST_0_MIPLVLS(uint32_t val)
{
return ((val) << A3XX_TEX_CONST_0_MIPLVLS__SHIFT) & A3XX_TEX_CONST_0_MIPLVLS__MASK;
}
+#define A3XX_TEX_CONST_0_MSAATEX__MASK 0x00300000
+#define A3XX_TEX_CONST_0_MSAATEX__SHIFT 20
+static inline uint32_t A3XX_TEX_CONST_0_MSAATEX(enum a3xx_tex_msaa val)
+{
+ return ((val) << A3XX_TEX_CONST_0_MSAATEX__SHIFT) & A3XX_TEX_CONST_0_MSAATEX__MASK;
+}
#define A3XX_TEX_CONST_0_FMT__MASK 0x1fc00000
#define A3XX_TEX_CONST_0_FMT__SHIFT 22
static inline uint32_t A3XX_TEX_CONST_0_FMT(enum a3xx_tex_fmt val)
@@ -2785,7 +2800,7 @@ static inline uint32_t A3XX_TEX_CONST_1_FETCHSIZE(enum a3xx_tex_fetchsize val)
}
#define REG_A3XX_TEX_CONST_2 0x00000002
-#define A3XX_TEX_CONST_2_INDX__MASK 0x000000ff
+#define A3XX_TEX_CONST_2_INDX__MASK 0x000001ff
#define A3XX_TEX_CONST_2_INDX__SHIFT 0
static inline uint32_t A3XX_TEX_CONST_2_INDX(uint32_t val)
{
@@ -2805,7 +2820,7 @@ static inline uint32_t A3XX_TEX_CONST_2_SWAP(enum a3xx_color_swap val)
}
#define REG_A3XX_TEX_CONST_3 0x00000003
-#define A3XX_TEX_CONST_3_LAYERSZ1__MASK 0x00007fff
+#define A3XX_TEX_CONST_3_LAYERSZ1__MASK 0x0001ffff
#define A3XX_TEX_CONST_3_LAYERSZ1__SHIFT 0
static inline uint32_t A3XX_TEX_CONST_3_LAYERSZ1(uint32_t val)
{
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_format.c b/src/gallium/drivers/freedreno/a3xx/fd3_format.c
index ec87aa979e3..04cb9b98fb7 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_format.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_format.c
@@ -262,6 +262,15 @@ static struct fd3_format formats[PIPE_FORMAT_COUNT] = {
_T(ETC2_R11_SNORM, ETC2_R11_SNORM, NONE, WZYX),
_T(ETC2_RG11_UNORM, ETC2_RG11_UNORM, NONE, WZYX),
_T(ETC2_RG11_SNORM, ETC2_RG11_SNORM, NONE, WZYX),
+
+ _T(DXT1_RGB, DXT1, NONE, WZYX),
+ _T(DXT1_SRGB, DXT1, NONE, WZYX),
+ _T(DXT1_RGBA, DXT1, NONE, WZYX),
+ _T(DXT1_SRGBA, DXT1, NONE, WZYX),
+ _T(DXT3_RGBA, DXT3, NONE, WZYX),
+ _T(DXT3_SRGBA, DXT3, NONE, WZYX),
+ _T(DXT5_RGBA, DXT5, NONE, WZYX),
+ _T(DXT5_SRGBA, DXT5, NONE, WZYX),
};
enum a3xx_vtx_fmt
@@ -301,7 +310,7 @@ fd3_pipe2fetchsize(enum pipe_format format)
{
if (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
format = PIPE_FORMAT_Z32_FLOAT;
- switch (util_format_get_blocksizebits(format)) {
+ switch (util_format_get_blocksizebits(format) / util_format_get_blockwidth(format)) {
case 8: return TFETCH_1_BYTE;
case 16: return TFETCH_2_BYTE;
case 32: return TFETCH_4_BYTE;
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_rasterizer.c b/src/gallium/drivers/freedreno/a3xx/fd3_rasterizer.c
index 9c16804fff5..583caaa806f 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_rasterizer.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_rasterizer.c
@@ -73,7 +73,7 @@ fd3_rasterizer_state_create(struct pipe_context *pctx,
so->gras_su_poly_offset_scale =
A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL(cso->offset_scale);
so->gras_su_poly_offset_offset =
- A3XX_GRAS_SU_POLY_OFFSET_OFFSET(cso->offset_units);
+ A3XX_GRAS_SU_POLY_OFFSET_OFFSET(cso->offset_units * 2.0f);
so->gras_su_mode_control =
A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(cso->line_width/2.0);
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_texture.c b/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
index c30658d0e7b..2d6ecb2c050 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_texture.c
@@ -115,6 +115,7 @@ fd3_sampler_state_create(struct pipe_context *pctx,
so->texsamp0 =
COND(!cso->normalized_coords, A3XX_TEX_SAMP_0_UNNORM_COORDS) |
+ COND(!cso->seamless_cube_map, A3XX_TEX_SAMP_0_CUBEMAPSEAMLESSFILTOFF) |
COND(miplinear, A3XX_TEX_SAMP_0_MIPFILTER_LINEAR) |
A3XX_TEX_SAMP_0_XY_MAG(tex_filter(cso->mag_img_filter, aniso)) |
A3XX_TEX_SAMP_0_XY_MIN(tex_filter(cso->min_img_filter, aniso)) |
@@ -239,7 +240,7 @@ fd3_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
A3XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl));
/* when emitted, A3XX_TEX_CONST_2_INDX() must be OR'd in: */
so->texconst2 =
- A3XX_TEX_CONST_2_PITCH(rsc->slices[lvl].pitch * rsc->cpp);
+ A3XX_TEX_CONST_2_PITCH(util_format_get_nblocksx(cso->format, rsc->slices[lvl].pitch) * rsc->cpp);
switch (prsc->target) {
case PIPE_TEXTURE_1D_ARRAY:
case PIPE_TEXTURE_2D_ARRAY:
diff --git a/src/gallium/drivers/freedreno/a4xx/a4xx.xml.h b/src/gallium/drivers/freedreno/a4xx/a4xx.xml.h
index 563f70ac5eb..2e1d712a28c 100644
--- a/src/gallium/drivers/freedreno/a4xx/a4xx.xml.h
+++ b/src/gallium/drivers/freedreno/a4xx/a4xx.xml.h
@@ -13,8 +13,8 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63728 bytes, from 2015-08-05 18:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63915 bytes, from 2015-08-24 16:56:28)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <[email protected]> (robclark)
@@ -162,10 +162,13 @@ enum a4xx_tex_fmt {
TFMT4_8_UNORM = 4,
TFMT4_8_8_UNORM = 14,
TFMT4_8_8_8_8_UNORM = 28,
+ TFMT4_8_SNORM = 5,
TFMT4_8_8_SNORM = 15,
TFMT4_8_8_8_8_SNORM = 29,
+ TFMT4_8_UINT = 6,
TFMT4_8_8_UINT = 16,
TFMT4_8_8_8_8_UINT = 30,
+ TFMT4_8_SINT = 7,
TFMT4_8_8_SINT = 17,
TFMT4_8_8_8_8_SINT = 31,
TFMT4_16_UINT = 21,
@@ -430,7 +433,7 @@ static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_SWAP(enum a3xx_color_swap val)
return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK;
}
#define A4XX_RB_MRT_BUF_INFO_COLOR_SRGB 0x00002000
-#define A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__MASK 0x007fc000
+#define A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__MASK 0xffffc000
#define A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__SHIFT 14
static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(uint32_t val)
{
@@ -440,7 +443,7 @@ static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(uint32_t val)
static inline uint32_t REG_A4XX_RB_MRT_BASE(uint32_t i0) { return 0x000020a6 + 0x5*i0; }
static inline uint32_t REG_A4XX_RB_MRT_CONTROL3(uint32_t i0) { return 0x000020a7 + 0x5*i0; }
-#define A4XX_RB_MRT_CONTROL3_STRIDE__MASK 0x0001fff8
+#define A4XX_RB_MRT_CONTROL3_STRIDE__MASK 0x03fffff8
#define A4XX_RB_MRT_CONTROL3_STRIDE__SHIFT 3
static inline uint32_t A4XX_RB_MRT_CONTROL3_STRIDE(uint32_t val)
{
@@ -1460,6 +1463,7 @@ static inline uint32_t A4XX_SP_FS_MRT_REG_MRTFORMAT(enum a4xx_color_fmt val)
{
return ((val) << A4XX_SP_FS_MRT_REG_MRTFORMAT__SHIFT) & A4XX_SP_FS_MRT_REG_MRTFORMAT__MASK;
}
+#define A4XX_SP_FS_MRT_REG_COLOR_SRGB 0x00040000
#define REG_A4XX_SP_CS_CTRL_REG0 0x00002300
diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_emit.h b/src/gallium/drivers/freedreno/a4xx/fd4_emit.h
index ab7850e50b0..3a1d4b617d3 100644
--- a/src/gallium/drivers/freedreno/a4xx/fd4_emit.h
+++ b/src/gallium/drivers/freedreno/a4xx/fd4_emit.h
@@ -56,6 +56,7 @@ struct fd4_emit {
uint32_t sprite_coord_enable; /* bitmask */
bool sprite_coord_mode;
bool rasterflat;
+ bool no_decode_srgb;
/* cached to avoid repeated lookups of same variants: */
struct ir3_shader_variant *vp, *fp;
diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_format.c b/src/gallium/drivers/freedreno/a4xx/fd4_format.c
index 3e0045449eb..6c9e217d5ad 100644
--- a/src/gallium/drivers/freedreno/a4xx/fd4_format.c
+++ b/src/gallium/drivers/freedreno/a4xx/fd4_format.c
@@ -79,9 +79,9 @@ struct fd4_format {
static struct fd4_format formats[PIPE_FORMAT_COUNT] = {
/* 8-bit */
VT(R8_UNORM, 8_UNORM, R8_UNORM, WZYX),
- V_(R8_SNORM, 8_SNORM, NONE, WZYX),
- V_(R8_UINT, 8_UINT, NONE, WZYX),
- V_(R8_SINT, 8_SINT, NONE, WZYX),
+ VT(R8_SNORM, 8_SNORM, NONE, WZYX),
+ VT(R8_UINT, 8_UINT, NONE, WZYX),
+ VT(R8_SINT, 8_SINT, NONE, WZYX),
V_(R8_USCALED, 8_UINT, NONE, WZYX),
V_(R8_SSCALED, 8_UINT, NONE, WZYX),
@@ -115,8 +115,8 @@ static struct fd4_format formats[PIPE_FORMAT_COUNT] = {
VT(R8G8_UNORM, 8_8_UNORM, R8G8_UNORM, WZYX),
VT(R8G8_SNORM, 8_8_SNORM, R8G8_SNORM, WZYX),
- VT(R8G8_UINT, 8_8_UINT, NONE, WZYX),
- VT(R8G8_SINT, 8_8_SINT, NONE, WZYX),
+ VT(R8G8_UINT, 8_8_UINT, R8G8_UINT, WZYX),
+ VT(R8G8_SINT, 8_8_SINT, R8G8_SINT, WZYX),
V_(R8G8_USCALED, 8_8_UINT, NONE, WZYX),
V_(R8G8_SSCALED, 8_8_SINT, NONE, WZYX),
diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_gmem.c b/src/gallium/drivers/freedreno/a4xx/fd4_gmem.c
index 81c37f72565..3f8bbf3a124 100644
--- a/src/gallium/drivers/freedreno/a4xx/fd4_gmem.c
+++ b/src/gallium/drivers/freedreno/a4xx/fd4_gmem.c
@@ -46,7 +46,8 @@
static void
emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
- struct pipe_surface **bufs, uint32_t *bases, uint32_t bin_w)
+ struct pipe_surface **bufs, uint32_t *bases,
+ uint32_t bin_w, bool decode_srgb)
{
enum a4xx_tile_mode tile_mode;
unsigned i;
@@ -60,6 +61,7 @@ emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
for (i = 0; i < A4XX_MAX_RENDER_TARGETS; i++) {
enum a4xx_color_fmt format = 0;
enum a3xx_color_swap swap = WZYX;
+ bool srgb = false;
struct fd_resource *rsc = NULL;
struct fd_resource_slice *slice = NULL;
uint32_t stride = 0;
@@ -68,10 +70,9 @@ emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
if ((i < nr_bufs) && bufs[i]) {
struct pipe_surface *psurf = bufs[i];
- enum pipe_format pformat = 0;
+ enum pipe_format pformat = psurf->format;
rsc = fd_resource(psurf->texture);
- pformat = psurf->format;
/* In case we're drawing to Z32F_S8, the "color" actually goes to
* the stencil
@@ -86,6 +87,11 @@ emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
format = fd4_pipe2color(pformat);
swap = fd4_pipe2swap(pformat);
+ if (decode_srgb)
+ srgb = util_format_is_srgb(pformat);
+ else
+ pformat = util_format_linear(pformat);
+
debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
offset = fd_resource_offset(rsc, psurf->u.tex.level,
@@ -108,7 +114,8 @@ emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs,
OUT_RING(ring, A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT(format) |
A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(tile_mode) |
A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(stride) |
- A4XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap));
+ A4XX_RB_MRT_BUF_INFO_COLOR_SWAP(swap) |
+ COND(srgb, A4XX_RB_MRT_BUF_INFO_COLOR_SRGB));
if (bin_w || (i >= nr_bufs) || !bufs[i]) {
OUT_RING(ring, base);
OUT_RING(ring, A4XX_RB_MRT_CONTROL3_STRIDE(stride));
@@ -282,7 +289,7 @@ emit_mem2gmem_surf(struct fd_context *ctx, uint32_t *bases,
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_surface *zsbufs[2];
- emit_mrt(ring, nr_bufs, bufs, bases, bin_w);
+ emit_mrt(ring, nr_bufs, bufs, bases, bin_w, false);
if (bufs[0] && (bufs[0]->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)) {
/* The gmem_restore_tex logic will put the first buffer's stencil
@@ -315,6 +322,7 @@ fd4_emit_tile_mem2gmem(struct fd_context *ctx, struct fd_tile *tile)
.key = {
.half_precision = fd_half_precision(pfb),
},
+ .no_decode_srgb = true,
};
unsigned char mrt_comp[A4XX_MAX_RENDER_TARGETS] = {0};
float x0, y0, x1, y1;
@@ -520,7 +528,7 @@ fd4_emit_sysmem_prep(struct fd_context *ctx)
OUT_RING(ring, A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(pfb->width) |
A4XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(pfb->height));
- emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL, 0);
+ emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL, 0, true);
/* setup scissor/offset for current tile: */
OUT_PKT0(ring, REG_A4XX_RB_BIN_OFFSET, 1);
@@ -677,7 +685,7 @@ fd4_emit_tile_renderprep(struct fd_context *ctx, struct fd_tile *tile)
OUT_RING(ring, CP_SET_BIN_1_X1(x1) | CP_SET_BIN_1_Y1(y1));
OUT_RING(ring, CP_SET_BIN_2_X2(x2) | CP_SET_BIN_2_Y2(y2));
- emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, gmem->cbuf_base, gmem->bin_w);
+ emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, gmem->cbuf_base, gmem->bin_w, true);
/* setup scissor/offset for current tile: */
OUT_PKT0(ring, REG_A4XX_RB_BIN_OFFSET, 1);
diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_program.c b/src/gallium/drivers/freedreno/a4xx/fd4_program.c
index 1a6d0142132..a3d7123ccee 100644
--- a/src/gallium/drivers/freedreno/a4xx/fd4_program.c
+++ b/src/gallium/drivers/freedreno/a4xx/fd4_program.c
@@ -450,10 +450,15 @@ fd4_program_emit(struct fd_ringbuffer *ring, struct fd4_emit *emit,
OUT_PKT0(ring, REG_A4XX_SP_FS_MRT_REG(0), 8);
for (i = 0; i < 8; i++) {
enum a4xx_color_fmt format = 0;
- if (i < nr)
+ bool srgb = false;
+ if (i < nr) {
format = fd4_emit_format(bufs[i]);
+ if (bufs[i] && !emit->no_decode_srgb)
+ srgb = util_format_is_srgb(bufs[i]->format);
+ }
OUT_RING(ring, A4XX_SP_FS_MRT_REG_REGID(color_regid[i]) |
A4XX_SP_FS_MRT_REG_MRTFORMAT(format) |
+ COND(srgb, A4XX_SP_FS_MRT_REG_COLOR_SRGB) |
COND(emit->key.half_precision,
A4XX_SP_FS_MRT_REG_HALF_PRECISION));
}
diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_texture.c b/src/gallium/drivers/freedreno/a4xx/fd4_texture.c
index d2bc5fee6c0..213b29c9181 100644
--- a/src/gallium/drivers/freedreno/a4xx/fd4_texture.c
+++ b/src/gallium/drivers/freedreno/a4xx/fd4_texture.c
@@ -187,9 +187,9 @@ fd4_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
A4XX_TEX_CONST_3_LAYERSZ(rsc->layer_size);
break;
case PIPE_TEXTURE_CUBE:
- case PIPE_TEXTURE_CUBE_ARRAY: /* ?? not sure about _CUBE_ARRAY */
+ case PIPE_TEXTURE_CUBE_ARRAY:
so->texconst3 =
- A4XX_TEX_CONST_3_DEPTH(1) |
+ A4XX_TEX_CONST_3_DEPTH(prsc->array_size / 6) |
A4XX_TEX_CONST_3_LAYERSZ(rsc->layer_size);
break;
case PIPE_TEXTURE_3D:
diff --git a/src/gallium/drivers/freedreno/adreno_common.xml.h b/src/gallium/drivers/freedreno/adreno_common.xml.h
index 00b6acba065..29944b7ac08 100644
--- a/src/gallium/drivers/freedreno/adreno_common.xml.h
+++ b/src/gallium/drivers/freedreno/adreno_common.xml.h
@@ -13,8 +13,8 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63728 bytes, from 2015-08-05 18:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63915 bytes, from 2015-08-24 16:56:28)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <[email protected]> (robclark)
diff --git a/src/gallium/drivers/freedreno/adreno_pm4.xml.h b/src/gallium/drivers/freedreno/adreno_pm4.xml.h
index 98a90e26679..432dce3dfb3 100644
--- a/src/gallium/drivers/freedreno/adreno_pm4.xml.h
+++ b/src/gallium/drivers/freedreno/adreno_pm4.xml.h
@@ -13,8 +13,8 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2015-05-20 20:03:14)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14968 bytes, from 2015-05-20 20:12:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63728 bytes, from 2015-08-05 18:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 67120 bytes, from 2015-08-14 23:22:03)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 63915 bytes, from 2015-08-24 16:56:28)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <[email protected]> (robclark)
diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c
index 8e6d43150ce..0b6b9fbbe7a 100644
--- a/src/gallium/drivers/freedreno/freedreno_context.c
+++ b/src/gallium/drivers/freedreno/freedreno_context.c
@@ -131,11 +131,13 @@ static void
fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,
unsigned flags)
{
+ struct fd_ringbuffer *ring = fd_context(pctx)->ring;
+
fd_context_render(pctx);
if (fence) {
fd_screen_fence_ref(pctx->screen, fence, NULL);
- *fence = fd_fence_create(pctx);
+ *fence = fd_fence_create(pctx, fd_ringbuffer_timestamp(ring));
}
}
diff --git a/src/gallium/drivers/freedreno/freedreno_fence.c b/src/gallium/drivers/freedreno/freedreno_fence.c
index 04a9feacd58..5125f091860 100644
--- a/src/gallium/drivers/freedreno/freedreno_fence.c
+++ b/src/gallium/drivers/freedreno/freedreno_fence.c
@@ -50,35 +50,18 @@ fd_screen_fence_ref(struct pipe_screen *pscreen,
*ptr = pfence;
}
-/* TODO we need to spiff out libdrm_freedreno a bit to allow passing
- * the timeout.. and maybe a better way to check if fence has been
- * signaled. The current implementation is a bit lame for now to
- * avoid bumping libdrm version requirement.
- */
-
-boolean fd_screen_fence_signalled(struct pipe_screen *screen,
- struct pipe_fence_handle *fence)
-{
- uint32_t timestamp = fd_ringbuffer_timestamp(fence->ctx->ring);
-
- /* TODO util helper for compare w/ rollover? */
- return timestamp >= fence->timestamp;
-}
-
boolean fd_screen_fence_finish(struct pipe_screen *screen,
struct pipe_fence_handle *fence,
uint64_t timeout)
{
- if (!timeout)
- return fd_screen_fence_signalled(screen, fence);
-
- if (fd_pipe_wait(fence->screen->pipe, fence->timestamp))
+ if (fd_pipe_wait_timeout(fence->screen->pipe, fence->timestamp, timeout))
return false;
return true;
}
-struct pipe_fence_handle * fd_fence_create(struct pipe_context *pctx)
+struct pipe_fence_handle * fd_fence_create(struct pipe_context *pctx,
+ uint32_t timestamp)
{
struct pipe_fence_handle *fence;
struct fd_context *ctx = fd_context(pctx);
@@ -91,7 +74,7 @@ struct pipe_fence_handle * fd_fence_create(struct pipe_context *pctx)
fence->ctx = ctx;
fence->screen = ctx->screen;
- fence->timestamp = fd_ringbuffer_timestamp(ctx->ring);
+ fence->timestamp = timestamp;
return fence;
}
diff --git a/src/gallium/drivers/freedreno/freedreno_fence.h b/src/gallium/drivers/freedreno/freedreno_fence.h
index e36bcc4d1f2..06c314a6116 100644
--- a/src/gallium/drivers/freedreno/freedreno_fence.h
+++ b/src/gallium/drivers/freedreno/freedreno_fence.h
@@ -34,11 +34,10 @@
void fd_screen_fence_ref(struct pipe_screen *pscreen,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *pfence);
-boolean fd_screen_fence_signalled(struct pipe_screen *screen,
- struct pipe_fence_handle *pfence);
boolean fd_screen_fence_finish(struct pipe_screen *screen,
struct pipe_fence_handle *pfence,
uint64_t timeout);
-struct pipe_fence_handle * fd_fence_create(struct pipe_context *pctx);
+struct pipe_fence_handle * fd_fence_create(struct pipe_context *pctx,
+ uint32_t timestamp);
#endif /* FREEDRENO_FENCE_H_ */
diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c
index 709ad4eb55b..98de0969cab 100644
--- a/src/gallium/drivers/freedreno/freedreno_resource.c
+++ b/src/gallium/drivers/freedreno/freedreno_resource.c
@@ -222,7 +222,7 @@ fd_resource_transfer_map(struct pipe_context *pctx,
ptrans->level = level;
ptrans->usage = usage;
ptrans->box = *box;
- ptrans->stride = slice->pitch * rsc->cpp;
+ ptrans->stride = util_format_get_nblocksx(format, slice->pitch) * rsc->cpp;
ptrans->layer_stride = slice->size0;
if (usage & PIPE_TRANSFER_READ)
@@ -375,9 +375,11 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment)
for (level = 0; level <= prsc->last_level; level++) {
struct fd_resource_slice *slice = fd_resource_slice(rsc, level);
+ uint32_t blocks;
slice->pitch = width = align(width, 32);
slice->offset = size;
+ blocks = util_format_get_nblocks(prsc->format, width, height);
/* 1d array and 2d array textures must all have the same layer size
* for each miplevel on a3xx. 3d textures can have different layer
* sizes for high levels, but the hw auto-sizer is buggy (or at least
@@ -387,9 +389,9 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment)
if (prsc->target == PIPE_TEXTURE_3D && (
level == 1 ||
(level > 1 && rsc->slices[level - 1].size0 > 0xf000)))
- slice->size0 = align(slice->pitch * height * rsc->cpp, alignment);
+ slice->size0 = align(blocks * rsc->cpp, alignment);
else if (level == 0 || rsc->layer_first || alignment == 1)
- slice->size0 = align(slice->pitch * height * rsc->cpp, alignment);
+ slice->size0 = align(blocks * rsc->cpp, alignment);
else
slice->size0 = rsc->slices[level - 1].size0;
@@ -459,7 +461,6 @@ fd_resource_create(struct pipe_screen *pscreen,
if (is_a4xx(fd_screen(pscreen))) {
switch (tmpl->target) {
case PIPE_TEXTURE_3D:
- /* TODO 3D_ARRAY? */
rsc->layer_first = false;
break;
default:
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c
index b55f5b36ca9..86e9a21da2f 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.c
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c
@@ -163,7 +163,6 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_TEXTURE_MULTISAMPLE:
case PIPE_CAP_TEXTURE_BARRIER:
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
- case PIPE_CAP_CUBE_MAP_ARRAY:
case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
case PIPE_CAP_START_INSTANCE:
case PIPE_CAP_COMPUTE:
@@ -176,6 +175,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_INDEP_BLEND_ENABLE:
case PIPE_CAP_INDEP_BLEND_FUNC:
case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
+ case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
return is_a3xx(screen) || is_a4xx(screen);
case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
@@ -191,8 +191,13 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
return 16383;
case PIPE_CAP_DEPTH_CLIP_DISABLE:
+ case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
return is_a3xx(screen);
+ case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
+ case PIPE_CAP_CUBE_MAP_ARRAY:
+ return is_a4xx(screen);
+
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
return 256;
@@ -202,7 +207,6 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
return is_ir3(screen) ? 130 : 120;
/* Unsupported features. */
- case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
@@ -230,8 +234,6 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_RESOURCE_FROM_USER_MEMORY:
case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:
case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
- case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
- case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
case PIPE_CAP_DEPTH_BOUNDS_TEST:
return 0;
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
index 0ab33455ed1..071901a3cc7 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
@@ -1636,6 +1636,11 @@ emit_tex(struct ir3_compile *ctx, nir_tex_instr *tex)
coord[i] = ir3_SHL_B(b, coord[i], 0, lod, 0);
}
+ /* the array coord for cube arrays needs 0.5 added to it */
+ if (tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE && tex->is_array &&
+ opc != OPC_ISAML)
+ coord[3] = ir3_ADD_F(b, coord[3], 0, create_immed(b, fui(0.5)), 0);
+
/*
* lay out the first argument in the proper order:
* - actual coordinates first
@@ -1759,6 +1764,12 @@ emit_tex_txs(struct ir3_compile *ctx, nir_tex_instr *tex)
tex_info(tex, &flags, &coords);
+ /* Actually we want the number of dimensions, not coordinates. This
+ * distinction only matters for cubes.
+ */
+ if (tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE)
+ coords = 2;
+
dst = get_dst(ctx, &tex->dest, 4);
compile_assert(ctx, tex->num_srcs == 1);
@@ -2301,7 +2312,7 @@ emit_instructions(struct ir3_compile *ctx)
ctx->ir = ir3_create(ctx->compiler, ninputs, noutputs);
/* Create inputs in first block: */
- ctx->block = get_block(ctx, fxn->start_block);
+ ctx->block = get_block(ctx, nir_start_block(fxn));
ctx->in_block = ctx->block;
list_addtail(&ctx->block->node, &ctx->ir->block_list);
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_nir_lower_if_else.c b/src/gallium/drivers/freedreno/ir3/ir3_nir_lower_if_else.c
index dc9e4626f27..bed7b7b826a 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_nir_lower_if_else.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_nir_lower_if_else.c
@@ -29,6 +29,7 @@
#include "ir3_nir.h"
#include "glsl/nir/nir_builder.h"
+#include "glsl/nir/nir_control_flow.h"
/* Based on nir_opt_peephole_select, and hacked up to more aggressively
* flatten anything that can be flattened
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_ra.c b/src/gallium/drivers/freedreno/ir3/ir3_ra.c
index eaf3b3c35e8..88018398e96 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_ra.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_ra.c
@@ -189,7 +189,7 @@ ir3_ra_alloc_reg_set(void *memctx)
}
/* allocate the reg-set.. */
- set->regs = ra_alloc_reg_set(set, ra_reg_count);
+ set->regs = ra_alloc_reg_set(set, ra_reg_count, true);
set->ra_reg_to_gpr = ralloc_array(set, uint16_t, ra_reg_count);
set->gpr_to_ra_reg = ralloc_array(set, uint16_t *, total_class_count);
diff --git a/src/gallium/drivers/i915/i915_surface.c b/src/gallium/drivers/i915/i915_surface.c
index 24e01560110..b2a639cb0f1 100644
--- a/src/gallium/drivers/i915/i915_surface.c
+++ b/src/gallium/drivers/i915/i915_surface.c
@@ -120,7 +120,8 @@ i915_surface_copy_render(struct pipe_context *pipe,
util_blitter_blit_generic(i915->blitter, dst_view, &dstbox,
src_view, src_box, src_width0, src_height0,
- PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL);
+ PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL,
+ FALSE);
return;
fallback:
diff --git a/src/gallium/drivers/nouveau/Makefile.sources b/src/gallium/drivers/nouveau/Makefile.sources
index 3fae3bc9cba..9346ea3204d 100644
--- a/src/gallium/drivers/nouveau/Makefile.sources
+++ b/src/gallium/drivers/nouveau/Makefile.sources
@@ -121,7 +121,8 @@ NV50_CODEGEN_SOURCES := \
codegen/nv50_ir_target_nv50.cpp \
codegen/nv50_ir_target_nv50.h \
codegen/nv50_ir_util.cpp \
- codegen/nv50_ir_util.h
+ codegen/nv50_ir_util.h \
+ codegen/unordered_set.h
NVC0_CODEGEN_SOURCES := \
codegen/nv50_ir_emit_gk110.cpp \
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir.h b/src/gallium/drivers/nouveau/codegen/nv50_ir.h
index 3ddaeafebbd..ba1b0851927 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir.h
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir.h
@@ -29,8 +29,8 @@
#include <deque>
#include <list>
#include <vector>
-#include <tr1/unordered_set>
+#include "codegen/unordered_set.h"
#include "codegen/nv50_ir_util.h"
#include "codegen/nv50_ir_graph.h"
@@ -585,10 +585,10 @@ public:
static inline Value *get(Iterator&);
- std::tr1::unordered_set<ValueRef *> uses;
+ unordered_set<ValueRef *> uses;
std::list<ValueDef *> defs;
- typedef std::tr1::unordered_set<ValueRef *>::iterator UseIterator;
- typedef std::tr1::unordered_set<ValueRef *>::const_iterator UseCIterator;
+ typedef unordered_set<ValueRef *>::iterator UseIterator;
+ typedef unordered_set<ValueRef *>::const_iterator UseCIterator;
typedef std::list<ValueDef *>::iterator DefIterator;
typedef std::list<ValueDef *>::const_iterator DefCIterator;
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
index f06056f8f17..8f1542959c9 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
@@ -933,6 +933,7 @@ CodeEmitterGK110::emitCVT(const Instruction *i)
code[0] |= typeSizeofLog2(dType) << 10;
code[0] |= typeSizeofLog2(i->sType) << 12;
+ code[1] |= i->subOp << 12;
if (isSignedIntType(dType))
code[0] |= 0x4000;
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
index ef5c87d0437..6e22788341f 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
@@ -818,6 +818,7 @@ CodeEmitterGM107::emitI2F()
emitField(0x31, 1, (insn->op == OP_ABS) || insn->src(0).mod.abs());
emitCC (0x2f);
emitField(0x2d, 1, (insn->op == OP_NEG) || insn->src(0).mod.neg());
+ emitField(0x29, 2, insn->subOp);
emitRND (0x27, rnd, -1);
emitField(0x0d, 1, isSignedType(insn->sType));
emitField(0x0a, 2, util_logbase2(typeSizeof(insn->sType)));
@@ -850,6 +851,7 @@ CodeEmitterGM107::emitI2I()
emitField(0x31, 1, (insn->op == OP_ABS) || insn->src(0).mod.abs());
emitCC (0x2f);
emitField(0x2d, 1, (insn->op == OP_NEG) || insn->src(0).mod.neg());
+ emitField(0x29, 2, insn->subOp);
emitField(0x0d, 1, isSignedType(insn->sType));
emitField(0x0c, 1, isSignedType(insn->dType));
emitField(0x0a, 2, util_logbase2(typeSizeof(insn->sType)));
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp
index f607f3ba3ec..6bf5219d346 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp
@@ -1020,6 +1020,10 @@ CodeEmitterNVC0::emitCVT(Instruction *i)
code[0] |= util_logbase2(typeSizeof(dType)) << 20;
code[0] |= util_logbase2(typeSizeof(i->sType)) << 23;
+ // for 8/16 source types, the byte/word is in subOp. word 1 is
+ // represented as 2.
+ code[1] |= i->subOp << 0x17;
+
if (sat)
code[0] |= 0x20;
if (abs)
@@ -2614,11 +2618,12 @@ private:
int imul; // integer MUL to MUL delay 3
} res;
struct ScoreData {
- int r[64];
+ int r[256];
int p[8];
int c;
} rd, wr;
int base;
+ int regs;
void rebase(const int base)
{
@@ -2627,7 +2632,7 @@ private:
return;
this->base = 0;
- for (int i = 0; i < 64; ++i) {
+ for (int i = 0; i < regs; ++i) {
rd.r[i] += delta;
wr.r[i] += delta;
}
@@ -2646,16 +2651,17 @@ private:
res.imul += delta;
res.tex += delta;
}
- void wipe()
+ void wipe(int regs)
{
memset(&rd, 0, sizeof(rd));
memset(&wr, 0, sizeof(wr));
memset(&res, 0, sizeof(res));
+ this->regs = regs;
}
int getLatest(const ScoreData& d) const
{
int max = 0;
- for (int i = 0; i < 64; ++i)
+ for (int i = 0; i < regs; ++i)
if (d.r[i] > max)
max = d.r[i];
for (int i = 0; i < 8; ++i)
@@ -2690,7 +2696,7 @@ private:
}
void setMax(const RegScores *that)
{
- for (int i = 0; i < 64; ++i) {
+ for (int i = 0; i < regs; ++i) {
rd.r[i] = MAX2(rd.r[i], that->rd.r[i]);
wr.r[i] = MAX2(wr.r[i], that->wr.r[i]);
}
@@ -2711,7 +2717,7 @@ private:
}
void print(int cycle)
{
- for (int i = 0; i < 64; ++i) {
+ for (int i = 0; i < regs; ++i) {
if (rd.r[i] > cycle)
INFO("rd $r%i @ %i\n", i, rd.r[i]);
if (wr.r[i] > cycle)
@@ -2806,9 +2812,10 @@ SchedDataCalculator::getCycles(const Instruction *insn, int origDelay) const
bool
SchedDataCalculator::visit(Function *func)
{
+ int regs = targ->getFileSize(FILE_GPR) + 1;
scoreBoards.resize(func->cfg.getSize());
for (size_t i = 0; i < scoreBoards.size(); ++i)
- scoreBoards[i].wipe();
+ scoreBoards[i].wipe(regs);
return true;
}
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
index 4847a0f3355..f153674e9ce 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
@@ -2990,9 +2990,15 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn)
case TGSI_OPCODE_UBFE:
FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
src0 = fetchSrc(0, c);
- src1 = fetchSrc(1, c);
- src2 = fetchSrc(2, c);
- mkOp3(OP_INSBF, TYPE_U32, src1, src2, mkImm(0x808), src1);
+ if (tgsi.getSrc(1).getFile() == TGSI_FILE_IMMEDIATE &&
+ tgsi.getSrc(2).getFile() == TGSI_FILE_IMMEDIATE) {
+ src1 = loadImm(NULL, tgsi.getSrc(2).getValueU32(c, info) << 8 |
+ tgsi.getSrc(1).getValueU32(c, info));
+ } else {
+ src1 = fetchSrc(1, c);
+ src2 = fetchSrc(2, c);
+ mkOp3(OP_INSBF, TYPE_U32, src1, src2, mkImm(0x808), src1);
+ }
mkOp2(OP_EXTBF, dstTy, dst0[c], src0, src1);
}
break;
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_gm107.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_gm107.cpp
index 1f3fce2bb9a..420cc4ef7c0 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_gm107.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_gm107.cpp
@@ -193,100 +193,16 @@ GM107LoweringPass::visit(Instruction *i)
checkPredicate(i);
switch (i->op) {
- case OP_TEX:
- case OP_TXB:
- case OP_TXL:
- case OP_TXF:
- case OP_TXG:
- return handleTEX(i->asTex());
- case OP_TXD:
- return handleTXD(i->asTex());
- case OP_TXLQ:
- return handleTXLQ(i->asTex());
- case OP_TXQ:
- return handleTXQ(i->asTex());
- case OP_EX2:
- bld.mkOp1(OP_PREEX2, TYPE_F32, i->getDef(0), i->getSrc(0));
- i->setSrc(0, i->getDef(0));
- break;
- case OP_POW:
- return handlePOW(i);
- case OP_DIV:
- return handleDIV(i);
- case OP_MOD:
- return handleMOD(i);
- case OP_SQRT:
- return handleSQRT(i);
- case OP_EXPORT:
- return handleEXPORT(i);
case OP_PFETCH:
return handlePFETCH(i);
- case OP_EMIT:
- case OP_RESTART:
- return handleOUT(i);
- case OP_RDSV:
- return handleRDSV(i);
- case OP_WRSV:
- return handleWRSV(i);
- case OP_LOAD:
- if (i->src(0).getFile() == FILE_SHADER_INPUT) {
- if (prog->getType() == Program::TYPE_COMPUTE) {
- i->getSrc(0)->reg.file = FILE_MEMORY_CONST;
- i->getSrc(0)->reg.fileIndex = 0;
- } else
- if (prog->getType() == Program::TYPE_GEOMETRY &&
- i->src(0).isIndirect(0)) {
- // XXX: this assumes vec4 units
- Value *ptr = bld.mkOp2v(OP_SHL, TYPE_U32, bld.getSSA(),
- i->getIndirect(0, 0), bld.mkImm(4));
- i->setIndirect(0, 0, ptr);
- i->op = OP_VFETCH;
- } else {
- i->op = OP_VFETCH;
- assert(prog->getType() != Program::TYPE_FRAGMENT); // INTERP
- }
- } else if (i->src(0).getFile() == FILE_MEMORY_CONST) {
- if (i->src(0).isIndirect(1)) {
- Value *ptr;
- if (i->src(0).isIndirect(0))
- ptr = bld.mkOp3v(OP_INSBF, TYPE_U32, bld.getSSA(),
- i->getIndirect(0, 1), bld.mkImm(0x1010),
- i->getIndirect(0, 0));
- else
- ptr = bld.mkOp2v(OP_SHL, TYPE_U32, bld.getSSA(),
- i->getIndirect(0, 1), bld.mkImm(16));
- i->setIndirect(0, 1, NULL);
- i->setIndirect(0, 0, ptr);
- i->subOp = NV50_IR_SUBOP_LDC_IS;
- }
- }
- break;
- case OP_ATOM:
- {
- const bool cctl = i->src(0).getFile() == FILE_MEMORY_GLOBAL;
- handleATOM(i);
- handleCasExch(i, cctl);
- }
- break;
- case OP_SULDB:
- case OP_SULDP:
- case OP_SUSTB:
- case OP_SUSTP:
- case OP_SUREDB:
- case OP_SUREDP:
- handleSurfaceOpNVE4(i->asTex());
- break;
case OP_DFDX:
case OP_DFDY:
- handleDFDX(i);
- break;
+ return handleDFDX(i);
case OP_POPCNT:
- handlePOPCNT(i);
- break;
+ return handlePOPCNT(i);
default:
- break;
+ return NVC0LoweringPass::visit(i);
}
- return true;
}
} // namespace nv50_ir
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
index c3c302da5c8..b1f406585a9 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
@@ -224,7 +224,7 @@ NVC0LegalizePostRA::findFirstUses(
const Instruction *texi,
const Instruction *insn,
std::list<TexUse> &uses,
- std::tr1::unordered_set<const Instruction *>& visited)
+ unordered_set<const Instruction *>& visited)
{
for (int d = 0; insn->defExists(d); ++d) {
Value *v = insn->getDef(d);
@@ -323,7 +323,7 @@ NVC0LegalizePostRA::insertTextureBarriers(Function *fn)
if (!uses)
return false;
for (size_t i = 0; i < texes.size(); ++i) {
- std::tr1::unordered_set<const Instruction *> visited;
+ unordered_set<const Instruction *> visited;
findFirstUses(texes[i], texes[i], uses[i], visited);
}
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h
index 260e101a1fb..2ce52e5c4f7 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.h
@@ -20,8 +20,6 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <tr1/unordered_set>
-
#include "codegen/nv50_ir.h"
#include "codegen/nv50_ir_build_util.h"
@@ -73,7 +71,7 @@ private:
inline bool insnDominatedBy(const Instruction *, const Instruction *) const;
void findFirstUses(const Instruction *tex, const Instruction *def,
std::list<TexUse>&,
- std::tr1::unordered_set<const Instruction *>&);
+ unordered_set<const Instruction *>&);
void findOverwritingDefs(const Instruction *tex, Instruction *insn,
const BasicBlock *term,
std::list<TexUse>&);
@@ -111,10 +109,11 @@ protected:
void checkPredicate(Instruction *);
+ virtual bool visit(Instruction *);
+
private:
virtual bool visit(Function *);
virtual bool visit(BasicBlock *);
- virtual bool visit(Instruction *);
void readTessCoord(LValue *dst, int c);
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp
index cea96dcdfc5..b01ef4128cd 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_peephole.cpp
@@ -1023,27 +1023,53 @@ ConstantFolding::opnd(Instruction *i, ImmediateValue &imm0, int s)
case OP_AND:
{
- CmpInstruction *cmp = i->getSrc(t)->getInsn()->asCmp();
- if (!cmp || cmp->op == OP_SLCT || cmp->getDef(0)->refCount() > 1)
- return;
- if (!prog->getTarget()->isOpSupported(cmp->op, TYPE_F32))
- return;
- if (imm0.reg.data.f32 != 1.0)
- return;
- if (i->getSrc(t)->getInsn()->dType != TYPE_U32)
- return;
+ Instruction *src = i->getSrc(t)->getInsn();
+ ImmediateValue imm1;
+ if (imm0.reg.data.u32 == 0) {
+ i->op = OP_MOV;
+ i->setSrc(0, new_ImmediateValue(prog, 0u));
+ i->src(0).mod = Modifier(0);
+ i->setSrc(1, NULL);
+ } else if (imm0.reg.data.u32 == ~0U) {
+ i->op = i->src(t).mod.getOp();
+ if (t) {
+ i->setSrc(0, i->getSrc(t));
+ i->src(0).mod = i->src(t).mod;
+ }
+ i->setSrc(1, NULL);
+ } else if (src->asCmp()) {
+ CmpInstruction *cmp = src->asCmp();
+ if (!cmp || cmp->op == OP_SLCT || cmp->getDef(0)->refCount() > 1)
+ return;
+ if (!prog->getTarget()->isOpSupported(cmp->op, TYPE_F32))
+ return;
+ if (imm0.reg.data.f32 != 1.0)
+ return;
+ if (cmp->dType != TYPE_U32)
+ return;
- i->getSrc(t)->getInsn()->dType = TYPE_F32;
- if (i->src(t).mod != Modifier(0)) {
- assert(i->src(t).mod == Modifier(NV50_IR_MOD_NOT));
- i->src(t).mod = Modifier(0);
- cmp->setCond = inverseCondCode(cmp->setCond);
- }
- i->op = OP_MOV;
- i->setSrc(s, NULL);
- if (t) {
- i->setSrc(0, i->getSrc(t));
- i->setSrc(t, NULL);
+ cmp->dType = TYPE_F32;
+ if (i->src(t).mod != Modifier(0)) {
+ assert(i->src(t).mod == Modifier(NV50_IR_MOD_NOT));
+ i->src(t).mod = Modifier(0);
+ cmp->setCond = inverseCondCode(cmp->setCond);
+ }
+ i->op = OP_MOV;
+ i->setSrc(s, NULL);
+ if (t) {
+ i->setSrc(0, i->getSrc(t));
+ i->setSrc(t, NULL);
+ }
+ } else if (prog->getTarget()->isOpSupported(OP_EXTBF, TYPE_U32) &&
+ src->op == OP_SHR &&
+ src->src(1).getImmediate(imm1) &&
+ i->src(t).mod == Modifier(0) &&
+ util_is_power_of_two(imm0.reg.data.u32 + 1)) {
+ // low byte = offset, high byte = width
+ uint32_t ext = (util_last_bit(imm0.reg.data.u32) << 8) | imm1.reg.data.u32;
+ i->op = OP_EXTBF;
+ i->setSrc(0, src->getSrc(0));
+ i->setSrc(1, new_ImmediateValue(prog, ext));
}
}
break;
@@ -1106,6 +1132,84 @@ ConstantFolding::opnd(Instruction *i, ImmediateValue &imm0, int s)
i->op = OP_MOV;
break;
}
+ case OP_CVT: {
+ Storage res;
+
+ // TODO: handle 64-bit values properly
+ if (typeSizeof(i->dType) == 8 || typeSizeof(i->sType) == 8)
+ return;
+
+ // TODO: handle single byte/word extractions
+ if (i->subOp)
+ return;
+
+ bld.setPosition(i, true); /* make sure bld is init'ed */
+
+#define CASE(type, dst, fmin, fmax, imin, imax, umin, umax) \
+ case type: \
+ switch (i->sType) { \
+ case TYPE_F32: \
+ res.data.dst = util_iround(i->saturate ? \
+ CLAMP(imm0.reg.data.f32, fmin, fmax) : \
+ imm0.reg.data.f32); \
+ break; \
+ case TYPE_S32: \
+ res.data.dst = i->saturate ? \
+ CLAMP(imm0.reg.data.s32, imin, imax) : \
+ imm0.reg.data.s32; \
+ break; \
+ case TYPE_U32: \
+ res.data.dst = i->saturate ? \
+ CLAMP(imm0.reg.data.u32, umin, umax) : \
+ imm0.reg.data.u32; \
+ break; \
+ case TYPE_S16: \
+ res.data.dst = i->saturate ? \
+ CLAMP(imm0.reg.data.s16, imin, imax) : \
+ imm0.reg.data.s16; \
+ break; \
+ case TYPE_U16: \
+ res.data.dst = i->saturate ? \
+ CLAMP(imm0.reg.data.u16, umin, umax) : \
+ imm0.reg.data.u16; \
+ break; \
+ default: return; \
+ } \
+ i->setSrc(0, bld.mkImm(res.data.dst)); \
+ break
+
+ switch(i->dType) {
+ CASE(TYPE_U16, u16, 0, UINT16_MAX, 0, UINT16_MAX, 0, UINT16_MAX);
+ CASE(TYPE_S16, s16, INT16_MIN, INT16_MAX, INT16_MIN, INT16_MAX, 0, INT16_MAX);
+ CASE(TYPE_U32, u32, 0, UINT32_MAX, 0, INT32_MAX, 0, UINT32_MAX);
+ CASE(TYPE_S32, s32, INT32_MIN, INT32_MAX, INT32_MIN, INT32_MAX, 0, INT32_MAX);
+ case TYPE_F32:
+ switch (i->sType) {
+ case TYPE_F32:
+ res.data.f32 = i->saturate ?
+ CLAMP(imm0.reg.data.f32, 0.0f, 1.0f) :
+ imm0.reg.data.f32;
+ break;
+ case TYPE_U16: res.data.f32 = (float) imm0.reg.data.u16; break;
+ case TYPE_U32: res.data.f32 = (float) imm0.reg.data.u32; break;
+ case TYPE_S16: res.data.f32 = (float) imm0.reg.data.s16; break;
+ case TYPE_S32: res.data.f32 = (float) imm0.reg.data.s32; break;
+ default:
+ return;
+ }
+ i->setSrc(0, bld.mkImm(res.data.f32));
+ break;
+ default:
+ return;
+ }
+#undef CASE
+
+ i->setType(i->dType); /* Remove i->sType, which we don't need anymore */
+ i->op = OP_MOV;
+ i->saturate = 0;
+ i->src(0).mod = Modifier(0); /* Clear the already applied modifier */
+ break;
+ }
default:
return;
}
@@ -1212,7 +1316,8 @@ private:
void handleRCP(Instruction *);
void handleSLCT(Instruction *);
void handleLOGOP(Instruction *);
- void handleCVT(Instruction *);
+ void handleCVT_NEG(Instruction *);
+ void handleCVT_EXTBF(Instruction *);
void handleSUCLAMP(Instruction *);
BuildUtil bld;
@@ -1463,12 +1568,12 @@ AlgebraicOpt::handleLOGOP(Instruction *logop)
// nv50:
// F2I(NEG(I2F(ABS(SET))))
void
-AlgebraicOpt::handleCVT(Instruction *cvt)
+AlgebraicOpt::handleCVT_NEG(Instruction *cvt)
{
+ Instruction *insn = cvt->getSrc(0)->getInsn();
if (cvt->sType != TYPE_F32 ||
cvt->dType != TYPE_S32 || cvt->src(0).mod != Modifier(0))
return;
- Instruction *insn = cvt->getSrc(0)->getInsn();
if (!insn || insn->op != OP_NEG || insn->dType != TYPE_F32)
return;
if (insn->src(0).mod != Modifier(0))
@@ -1498,6 +1603,104 @@ AlgebraicOpt::handleCVT(Instruction *cvt)
delete_Instruction(prog, cvt);
}
+// Some shaders extract packed bytes out of words and convert them to
+// e.g. float. The Fermi+ CVT instruction can extract those directly, as can
+// nv50 for word sizes.
+//
+// CVT(EXTBF(x, byte/word))
+// CVT(AND(bytemask, x))
+// CVT(AND(bytemask, SHR(x, 8/16/24)))
+// CVT(SHR(x, 16/24))
+void
+AlgebraicOpt::handleCVT_EXTBF(Instruction *cvt)
+{
+ Instruction *insn = cvt->getSrc(0)->getInsn();
+ ImmediateValue imm;
+ Value *arg = NULL;
+ unsigned width, offset;
+ if ((cvt->sType != TYPE_U32 && cvt->sType != TYPE_S32) || !insn)
+ return;
+ if (insn->op == OP_EXTBF && insn->src(1).getImmediate(imm)) {
+ width = (imm.reg.data.u32 >> 8) & 0xff;
+ offset = imm.reg.data.u32 & 0xff;
+ arg = insn->getSrc(0);
+
+ if (width != 8 && width != 16)
+ return;
+ if (width == 8 && offset & 0x7)
+ return;
+ if (width == 16 && offset & 0xf)
+ return;
+ } else if (insn->op == OP_AND) {
+ int s;
+ if (insn->src(0).getImmediate(imm))
+ s = 0;
+ else if (insn->src(1).getImmediate(imm))
+ s = 1;
+ else
+ return;
+
+ if (imm.reg.data.u32 == 0xff)
+ width = 8;
+ else if (imm.reg.data.u32 == 0xffff)
+ width = 16;
+ else
+ return;
+
+ arg = insn->getSrc(!s);
+ Instruction *shift = arg->getInsn();
+ offset = 0;
+ if (shift && shift->op == OP_SHR &&
+ shift->sType == cvt->sType &&
+ shift->src(1).getImmediate(imm) &&
+ ((width == 8 && (imm.reg.data.u32 & 0x7) == 0) ||
+ (width == 16 && (imm.reg.data.u32 & 0xf) == 0))) {
+ arg = shift->getSrc(0);
+ offset = imm.reg.data.u32;
+ }
+ } else if (insn->op == OP_SHR &&
+ insn->sType == cvt->sType &&
+ insn->src(1).getImmediate(imm)) {
+ arg = insn->getSrc(0);
+ if (imm.reg.data.u32 == 24) {
+ width = 8;
+ offset = 24;
+ } else if (imm.reg.data.u32 == 16) {
+ width = 16;
+ offset = 16;
+ } else {
+ return;
+ }
+ }
+
+ if (!arg)
+ return;
+
+ // Irrespective of what came earlier, we can undo a shift on the argument
+ // by adjusting the offset.
+ Instruction *shift = arg->getInsn();
+ if (shift && shift->op == OP_SHL &&
+ shift->src(1).getImmediate(imm) &&
+ ((width == 8 && (imm.reg.data.u32 & 0x7) == 0) ||
+ (width == 16 && (imm.reg.data.u32 & 0xf) == 0)) &&
+ imm.reg.data.u32 <= offset) {
+ arg = shift->getSrc(0);
+ offset -= imm.reg.data.u32;
+ }
+
+ // The unpackSnorm lowering still leaves a few shifts behind, but it's too
+ // annoying to detect them.
+
+ if (width == 8) {
+ cvt->sType = cvt->sType == TYPE_U32 ? TYPE_U8 : TYPE_S8;
+ } else {
+ assert(width == 16);
+ cvt->sType = cvt->sType == TYPE_U32 ? TYPE_U16 : TYPE_S16;
+ }
+ cvt->setSrc(0, arg);
+ cvt->subOp = offset >> 3;
+}
+
// SUCLAMP dst, (ADD b imm), k, 0 -> SUCLAMP dst, b, k, imm (if imm fits s6)
void
AlgebraicOpt::handleSUCLAMP(Instruction *insn)
@@ -1568,7 +1771,9 @@ AlgebraicOpt::visit(BasicBlock *bb)
handleLOGOP(i);
break;
case OP_CVT:
- handleCVT(i);
+ handleCVT_NEG(i);
+ if (prog->getTarget()->isOpSupported(OP_EXTBF, TYPE_U32))
+ handleCVT_EXTBF(i);
break;
case OP_SUCLAMP:
handleSUCLAMP(i);
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp
index 78bc97f4397..0cd21cf47f5 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp
@@ -25,7 +25,6 @@
#include <stack>
#include <limits>
-#include <tr1/unordered_set>
namespace nv50_ir {
@@ -1551,7 +1550,7 @@ SpillCodeInserter::run(const std::list<ValuePair>& lst)
// Keep track of which instructions to delete later. Deleting them
// inside the loop is unsafe since a single instruction may have
// multiple destinations that all need to be spilled (like OP_SPLIT).
- std::tr1::unordered_set<Instruction *> to_del;
+ unordered_set<Instruction *> to_del;
for (Value::DefIterator d = lval->defs.begin(); d != lval->defs.end();
++d) {
@@ -1593,7 +1592,7 @@ SpillCodeInserter::run(const std::list<ValuePair>& lst)
}
}
- for (std::tr1::unordered_set<Instruction *>::const_iterator it = to_del.begin();
+ for (unordered_set<Instruction *>::const_iterator it = to_del.begin();
it != to_del.end(); ++it)
delete_Instruction(func->getProgram(), *it);
}
diff --git a/src/gallium/drivers/nouveau/codegen/unordered_set.h b/src/gallium/drivers/nouveau/codegen/unordered_set.h
new file mode 100644
index 00000000000..8ef6d462ffd
--- /dev/null
+++ b/src/gallium/drivers/nouveau/codegen/unordered_set.h
@@ -0,0 +1,48 @@
+#ifndef __NV50_UNORDERED_SET_H__
+#define __NV50_UNORDERED_SET_H__
+
+#if (__cplusplus >= 201103L) || defined(ANDROID)
+#include <unordered_set>
+#else
+#include <tr1/unordered_set>
+#endif
+
+namespace nv50_ir {
+
+#if __cplusplus >= 201103L
+using std::unordered_set;
+#elif !defined(ANDROID)
+using std::tr1::unordered_set;
+#else // Android release before lollipop
+using std::isfinite;
+typedef std::tr1::unordered_set<void *> voidptr_unordered_set;
+
+template <typename V>
+class unordered_set : public voidptr_unordered_set {
+ public:
+ typedef voidptr_unordered_set _base;
+ typedef _base::iterator _biterator;
+ typedef _base::const_iterator const_biterator;
+
+ class iterator : public _biterator {
+ public:
+ iterator(const _biterator & i) : _biterator(i) {}
+ V operator*() const { return reinterpret_cast<V>(*_biterator(*this)); }
+ };
+ class const_iterator : public const_biterator {
+ public:
+ const_iterator(const iterator & i) : const_biterator(i) {}
+ const_iterator(const const_biterator & i) : const_biterator(i) {}
+ const V operator*() const { return reinterpret_cast<const V>(*const_biterator(*this)); }
+ };
+
+ iterator begin() { return _base::begin(); }
+ iterator end() { return _base::end(); }
+ const_iterator begin() const { return _base::begin(); }
+ const_iterator end() const { return _base::end(); }
+};
+#endif
+
+} // namespace nv50_ir
+
+#endif // __NV50_UNORDERED_SET_H__
diff --git a/src/gallium/drivers/nouveau/nouveau_compiler.c b/src/gallium/drivers/nouveau/nouveau_compiler.c
index 86604984220..495450b317a 100644
--- a/src/gallium/drivers/nouveau/nouveau_compiler.c
+++ b/src/gallium/drivers/nouveau/nouveau_compiler.c
@@ -190,6 +190,10 @@ main(int argc, char *argv[])
type = PIPE_SHADER_GEOMETRY;
else if (!strncmp(text, "COMP", 4))
type = PIPE_SHADER_COMPUTE;
+ else if (!strncmp(text, "TESS_CTRL", 9))
+ type = PIPE_SHADER_TESS_CTRL;
+ else if (!strncmp(text, "TESS_EVAL", 9))
+ type = PIPE_SHADER_TESS_EVAL;
else {
_debug_printf("Unrecognized TGSI header\n");
return 1;
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state.c b/src/gallium/drivers/nouveau/nv50/nv50_state.c
index 9505a0b4085..410e6311e60 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_state.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_state.c
@@ -117,7 +117,6 @@ nv50_blend_state_create(struct pipe_context *pipe,
struct nv50_blend_stateobj *so = CALLOC_STRUCT(nv50_blend_stateobj);
int i;
bool emit_common_func = cso->rt[0].blend_enable;
- uint32_t ms;
if (nv50_context(pipe)->screen->tesla->oclass >= NVA3_3D_CLASS) {
SB_BEGIN_3D(so, BLEND_INDEPENDENT, 1);
@@ -189,15 +188,6 @@ nv50_blend_state_create(struct pipe_context *pipe,
SB_DATA (so, nv50_colormask(cso->rt[0].colormask));
}
- ms = 0;
- if (cso->alpha_to_coverage)
- ms |= NV50_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE;
- if (cso->alpha_to_one)
- ms |= NV50_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE;
-
- SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1);
- SB_DATA (so, ms);
-
assert(so->size <= (sizeof(so->state) / sizeof(so->state[0])));
return so;
}
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c
index 985603df5fa..b304a177b50 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c
@@ -1,4 +1,6 @@
+#include "util/u_format.h"
+
#include "nv50/nv50_context.h"
#include "nv50/nv50_defs.xml.h"
@@ -314,6 +316,25 @@ nv50_validate_derived_2(struct nv50_context *nv50)
}
static void
+nv50_validate_derived_3(struct nv50_context *nv50)
+{
+ struct nouveau_pushbuf *push = nv50->base.pushbuf;
+ struct pipe_framebuffer_state *fb = &nv50->framebuffer;
+ uint32_t ms = 0;
+
+ if ((!fb->nr_cbufs || !fb->cbufs[0] ||
+ !util_format_is_pure_integer(fb->cbufs[0]->format)) && nv50->blend) {
+ if (nv50->blend->pipe.alpha_to_coverage)
+ ms |= NV50_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE;
+ if (nv50->blend->pipe.alpha_to_one)
+ ms |= NV50_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE;
+ }
+
+ BEGIN_NV04(push, NV50_3D(MULTISAMPLE_CTRL), 1);
+ PUSH_DATA (push, ms);
+}
+
+static void
nv50_validate_clip(struct nv50_context *nv50)
{
struct nouveau_pushbuf *push = nv50->base.pushbuf;
@@ -474,6 +495,7 @@ static struct state_validate {
{ nv50_validate_derived_rs, NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER |
NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
{ nv50_validate_derived_2, NV50_NEW_ZSA | NV50_NEW_FRAMEBUFFER },
+ { nv50_validate_derived_3, NV50_NEW_BLEND | NV50_NEW_FRAMEBUFFER },
{ nv50_validate_clip, NV50_NEW_CLIP | NV50_NEW_RASTERIZER |
NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
{ nv50_constbufs_validate, NV50_NEW_CONSTBUF },
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_stateobj.h b/src/gallium/drivers/nouveau/nv50/nv50_stateobj.h
index cf75d1eb11b..4b1d00c7155 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_stateobj.h
+++ b/src/gallium/drivers/nouveau/nv50/nv50_stateobj.h
@@ -19,7 +19,7 @@
struct nv50_blend_stateobj {
struct pipe_blend_state pipe;
int size;
- uint32_t state[84]; // TODO: allocate less if !independent_blend_enable
+ uint32_t state[82]; // TODO: allocate less if !independent_blend_enable
};
struct nv50_rasterizer_stateobj {
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_surface.c b/src/gallium/drivers/nouveau/nv50/nv50_surface.c
index b1ae01692cb..64348b3c378 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_surface.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_surface.c
@@ -68,6 +68,10 @@ nv50_2d_format(enum pipe_format format, bool dst, bool dst_src_equal)
return NV50_SURFACE_FORMAT_R16_UNORM;
case 4:
return NV50_SURFACE_FORMAT_BGRA8_UNORM;
+ case 8:
+ return NV50_SURFACE_FORMAT_RGBA16_FLOAT;
+ case 16:
+ return NV50_SURFACE_FORMAT_RGBA32_FLOAT;
default:
return 0;
}
@@ -1003,6 +1007,8 @@ nv50_blitctx_prepare_state(struct nv50_blitctx *blit)
/* zsa state */
BEGIN_NV04(push, NV50_3D(DEPTH_TEST_ENABLE), 1);
PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV50_3D(DEPTH_BOUNDS_EN), 1);
+ PUSH_DATA (push, 0);
BEGIN_NV04(push, NV50_3D(STENCIL_ENABLE), 1);
PUSH_DATA (push, 0);
BEGIN_NV04(push, NV50_3D(ALPHA_TEST_ENABLE), 1);
@@ -1387,18 +1393,24 @@ nv50_blit_eng2d(struct nv50_context *nv50, const struct pipe_blit_info *info)
PUSH_DATA (push, info->dst.box.z + i);
} else {
const unsigned z = info->dst.box.z + i;
+ const uint64_t address = dst->base.address +
+ dst->level[info->dst.level].offset +
+ z * dst->layer_stride;
BEGIN_NV04(push, NV50_2D(DST_ADDRESS_HIGH), 2);
- PUSH_DATAh(push, dst->base.address + z * dst->layer_stride);
- PUSH_DATA (push, dst->base.address + z * dst->layer_stride);
+ PUSH_DATAh(push, address);
+ PUSH_DATA (push, address);
}
if (src->layout_3d) {
/* not possible because of depth tiling */
assert(0);
} else {
const unsigned z = info->src.box.z + i;
+ const uint64_t address = src->base.address +
+ src->level[info->src.level].offset +
+ z * src->layer_stride;
BEGIN_NV04(push, NV50_2D(SRC_ADDRESS_HIGH), 2);
- PUSH_DATAh(push, src->base.address + z * src->layer_stride);
- PUSH_DATA (push, src->base.address + z * src->layer_stride);
+ PUSH_DATAh(push, address);
+ PUSH_DATA (push, address);
}
BEGIN_NV04(push, NV50_2D(BLIT_SRC_Y_INT), 1); /* trigger */
PUSH_DATA (push, srcy >> 32);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
index 84f8db6a8ac..7a15a11f560 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
@@ -132,6 +132,9 @@ nvc0_context_unreference_resources(struct nvc0_context *nvc0)
pipe_resource_reference(res, NULL);
}
util_dynarray_fini(&nvc0->global_residents);
+
+ if (nvc0->tcp_empty)
+ nvc0->base.pipe.delete_tcs_state(&nvc0->base.pipe, nvc0->tcp_empty);
}
static void
@@ -306,13 +309,6 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
pipe->memory_barrier = nvc0_memory_barrier;
pipe->get_sample_position = nvc0_context_get_sample_position;
- if (!screen->cur_ctx) {
- nvc0->state = screen->save_state;
- screen->cur_ctx = nvc0;
- nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx);
- }
- screen->base.pushbuf->kick_notify = nvc0_default_kick_notify;
-
nvc0_init_query_functions(nvc0);
nvc0_init_surface_functions(nvc0);
nvc0_init_state_functions(nvc0);
@@ -326,6 +322,21 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
/* shader builtin library is per-screen, but we need a context for m2mf */
nvc0_program_library_upload(nvc0);
+ nvc0_program_init_tcp_empty(nvc0);
+ if (!nvc0->tcp_empty)
+ goto out_err;
+ /* set the empty tctl prog on next draw in case one is never set */
+ nvc0->dirty |= NVC0_NEW_TCTLPROG;
+
+ /* now that there are no more opportunities for errors, set the current
+ * context if there isn't already one.
+ */
+ if (!screen->cur_ctx) {
+ nvc0->state = screen->save_state;
+ screen->cur_ctx = nvc0;
+ nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx);
+ }
+ screen->base.pushbuf->kick_notify = nvc0_default_kick_notify;
/* add permanently resident buffers to bufctxts */
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
index f4499423a10..df1a891a43e 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
@@ -128,6 +128,8 @@ struct nvc0_context {
struct nvc0_program *fragprog;
struct nvc0_program *compprog;
+ struct nvc0_program *tcp_empty;
+
struct nvc0_constbuf constbuf[6][NVC0_MAX_PIPE_CONSTBUFS];
uint16_t constbuf_dirty[6];
uint16_t constbuf_valid[6];
@@ -227,6 +229,7 @@ void nvc0_program_destroy(struct nvc0_context *, struct nvc0_program *);
void nvc0_program_library_upload(struct nvc0_context *);
uint32_t nvc0_program_symbol_offset(const struct nvc0_program *,
uint32_t label);
+void nvc0_program_init_tcp_empty(struct nvc0_context *);
/* nvc0_query.c */
void nvc0_init_query_functions(struct nvc0_context *);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
index 507a2507fe3..12f1bb728d7 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
@@ -22,6 +22,8 @@
#include "pipe/p_defines.h"
+#include "tgsi/tgsi_ureg.h"
+
#include "nvc0/nvc0_context.h"
#include "codegen/nv50_ir_driver.h"
@@ -799,3 +801,18 @@ nvc0_program_symbol_offset(const struct nvc0_program *prog, uint32_t label)
return prog->code_base + base + syms[i].offset;
return prog->code_base; /* no symbols or symbol not found */
}
+
+void
+nvc0_program_init_tcp_empty(struct nvc0_context *nvc0)
+{
+ struct ureg_program *ureg;
+
+ ureg = ureg_create(TGSI_PROCESSOR_TESS_CTRL);
+ if (!ureg)
+ return;
+
+ ureg_property(ureg, TGSI_PROPERTY_TCS_VERTICES_OUT, 1);
+ ureg_END(ureg);
+
+ nvc0->tcp_empty = ureg_create_shader_and_destroy(ureg, &nvc0->base.pipe);
+}
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c
index 8aa127adc0a..8f8ac2d34b9 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c
@@ -148,8 +148,13 @@ nvc0_tctlprog_validate(struct nvc0_context *nvc0)
BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(2)), 1);
PUSH_DATA (push, tp->num_gprs);
} else {
- BEGIN_NVC0(push, NVC0_3D(SP_SELECT(2)), 1);
+ tp = nvc0->tcp_empty;
+ /* not a whole lot we can do to handle this failure */
+ if (!nvc0_program_validate(nvc0, tp))
+ assert(!"unable to validate empty tcp");
+ BEGIN_NVC0(push, NVC0_3D(SP_SELECT(2)), 2);
PUSH_DATA (push, 0x20);
+ PUSH_DATA (push, tp->code_base);
}
nvc0_program_update_context_state(nvc0, tp, 1);
}
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
index 2a33857d9df..ee29912eb40 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
@@ -90,7 +90,6 @@ nvc0_blend_state_create(struct pipe_context *pipe,
struct nvc0_blend_stateobj *so = CALLOC_STRUCT(nvc0_blend_stateobj);
int i;
int r; /* reference */
- uint32_t ms;
uint8_t blend_en = 0;
bool indep_masks = false;
bool indep_funcs = false;
@@ -176,15 +175,6 @@ nvc0_blend_state_create(struct pipe_context *pipe,
}
}
- ms = 0;
- if (cso->alpha_to_coverage)
- ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE;
- if (cso->alpha_to_one)
- ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE;
-
- SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1);
- SB_DATA (so, ms);
-
assert(so->size <= (sizeof(so->state) / sizeof(so->state[0])));
return so;
}
@@ -234,7 +224,7 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe,
SB_IMMED_3D(so, MULTISAMPLE_ENABLE, cso->multisample);
SB_IMMED_3D(so, LINE_SMOOTH_ENABLE, cso->line_smooth);
- if (cso->line_smooth)
+ if (cso->line_smooth || cso->multisample)
SB_BEGIN_3D(so, LINE_WIDTH_SMOOTH, 1);
else
SB_BEGIN_3D(so, LINE_WIDTH_ALIASED, 1);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
index ce1119c284d..47bd66d1e35 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
@@ -1,4 +1,5 @@
+#include "util/u_format.h"
#include "util/u_math.h"
#include "nvc0/nvc0_context.h"
@@ -555,6 +556,25 @@ nvc0_validate_derived_2(struct nvc0_context *nvc0)
}
static void
+nvc0_validate_derived_3(struct nvc0_context *nvc0)
+{
+ struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+ struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
+ uint32_t ms = 0;
+
+ if ((!fb->nr_cbufs || !fb->cbufs[0] ||
+ !util_format_is_pure_integer(fb->cbufs[0]->format)) && nvc0->blend) {
+ if (nvc0->blend->pipe.alpha_to_coverage)
+ ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE;
+ if (nvc0->blend->pipe.alpha_to_one)
+ ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE;
+ }
+
+ BEGIN_NVC0(push, NVC0_3D(MULTISAMPLE_CTRL), 1);
+ PUSH_DATA (push, ms);
+}
+
+static void
nvc0_validate_tess_state(struct nvc0_context *nvc0)
{
struct nouveau_pushbuf *push = nvc0->base.pushbuf;
@@ -628,6 +648,7 @@ static struct state_validate {
{ nvc0_validate_derived_1, NVC0_NEW_FRAGPROG | NVC0_NEW_ZSA |
NVC0_NEW_RASTERIZER },
{ nvc0_validate_derived_2, NVC0_NEW_ZSA | NVC0_NEW_FRAMEBUFFER },
+ { nvc0_validate_derived_3, NVC0_NEW_BLEND | NVC0_NEW_FRAMEBUFFER },
{ nvc0_validate_clip, NVC0_NEW_CLIP | NVC0_NEW_RASTERIZER |
NVC0_NEW_VERTPROG |
NVC0_NEW_TEVLPROG |
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_stateobj.h b/src/gallium/drivers/nouveau/nvc0/nvc0_stateobj.h
index 18fcc12dea3..8bc33c6a0e0 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_stateobj.h
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_stateobj.h
@@ -17,7 +17,7 @@
struct nvc0_blend_stateobj {
struct pipe_blend_state pipe;
int size;
- uint32_t state[72];
+ uint32_t state[70];
};
struct nvc0_rasterizer_stateobj {
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
index 51a6f93f891..dbdf292c862 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
@@ -887,6 +887,7 @@ nvc0_blitctx_prepare_state(struct nvc0_blitctx *blit)
/* zsa state */
IMMED_NVC0(push, NVC0_3D(DEPTH_TEST_ENABLE), 0);
+ IMMED_NVC0(push, NVC0_3D(DEPTH_BOUNDS_EN), 0);
IMMED_NVC0(push, NVC0_3D(STENCIL_ENABLE), 0);
IMMED_NVC0(push, NVC0_3D(ALPHA_TEST_ENABLE), 0);
@@ -1336,18 +1337,24 @@ nvc0_blit_eng2d(struct nvc0_context *nvc0, const struct pipe_blit_info *info)
PUSH_DATA (push, info->dst.box.z + i);
} else {
const unsigned z = info->dst.box.z + i;
+ const uint64_t address = dst->base.address +
+ dst->level[info->dst.level].offset +
+ z * dst->layer_stride;
BEGIN_NVC0(push, NVC0_2D(DST_ADDRESS_HIGH), 2);
- PUSH_DATAh(push, dst->base.address + z * dst->layer_stride);
- PUSH_DATA (push, dst->base.address + z * dst->layer_stride);
+ PUSH_DATAh(push, address);
+ PUSH_DATA (push, address);
}
if (src->layout_3d) {
/* not possible because of depth tiling */
assert(0);
} else {
const unsigned z = info->src.box.z + i;
+ const uint64_t address = src->base.address +
+ src->level[info->src.level].offset +
+ z * src->layer_stride;
BEGIN_NVC0(push, NVC0_2D(SRC_ADDRESS_HIGH), 2);
- PUSH_DATAh(push, src->base.address + z * src->layer_stride);
- PUSH_DATA (push, src->base.address + z * src->layer_stride);
+ PUSH_DATAh(push, address);
+ PUSH_DATA (push, address);
}
BEGIN_NVC0(push, NVC0_2D(BLIT_SRC_Y_INT), 1); /* trigger */
PUSH_DATA (push, srcy >> 32);
diff --git a/src/gallium/drivers/r300/compiler/radeon_pair_regalloc.c b/src/gallium/drivers/r300/compiler/radeon_pair_regalloc.c
index 14f93fba986..e8f4087cbc4 100644
--- a/src/gallium/drivers/r300/compiler/radeon_pair_regalloc.c
+++ b/src/gallium/drivers/r300/compiler/radeon_pair_regalloc.c
@@ -693,7 +693,8 @@ void rc_init_regalloc_state(struct rc_regalloc_state *s)
};
/* Allocate the main ra data structure */
- s->regs = ra_alloc_reg_set(NULL, R500_PFS_NUM_TEMP_REGS * RC_MASK_XYZW);
+ s->regs = ra_alloc_reg_set(NULL, R500_PFS_NUM_TEMP_REGS * RC_MASK_XYZW,
+ true);
/* Create the register classes */
for (i = 0; i < RC_REG_CLASS_COUNT; i++) {
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index 6ea8f24cc14..b8cc316c2ac 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -667,7 +667,8 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
r300_blitter_begin(r300, R300_COPY);
util_blitter_blit_generic(r300->blitter, dst_view, &dstbox,
src_view, src_box, src_width0, src_height0,
- PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL);
+ PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL,
+ FALSE);
r300_blitter_end(r300);
pipe_surface_reference(&dst_view, NULL);
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index b0002c3b50f..22a0950a491 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -732,7 +732,8 @@ void r600_resource_copy_region(struct pipe_context *ctx,
r600_blitter_begin(ctx, R600_COPY_TEXTURE);
util_blitter_blit_generic(rctx->blitter, dst_view, &dstbox,
src_view, src_box, src_width0, src_height0,
- PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL);
+ PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL,
+ FALSE);
r600_blitter_end(ctx);
pipe_surface_reference(&dst_view, NULL);
diff --git a/src/gallium/drivers/r600/r600_isa.h b/src/gallium/drivers/r600/r600_isa.h
index 381f06d5924..fdbe1c00d20 100644
--- a/src/gallium/drivers/r600/r600_isa.h
+++ b/src/gallium/drivers/r600/r600_isa.h
@@ -262,7 +262,7 @@ static const struct alu_op_info alu_op_table[] = {
{"PRED_SETNE_PUSH_INT", 2, { 0x4D, 0x4D },{ AF_VS, AF_VS, AF_VS, AF_VS}, AF_PRED_PUSH | AF_CC_NE | AF_INT_CMP },
{"PRED_SETLT_PUSH_INT", 2, { 0x4E, 0x4E },{ AF_VS, AF_VS, AF_VS, AF_VS}, AF_PRED_PUSH | AF_CC_LT | AF_INT_CMP },
{"PRED_SETLE_PUSH_INT", 2, { 0x4F, 0x4F },{ AF_VS, AF_VS, AF_VS, AF_VS}, AF_PRED_PUSH | AF_CC_LE | AF_INT_CMP },
- {"FLT_TO_INT", 1, { 0x6B, 0x50 },{ AF_S, AF_S, AF_VS, AF_VS}, AF_INT_DST | AF_CVT },
+ {"FLT_TO_INT", 1, { 0x6B, 0x50 },{ AF_S, AF_S, AF_V, AF_V}, AF_INT_DST | AF_CVT },
{"BFREV_INT", 1, { -1, 0x51 },{ 0, 0, AF_VS, AF_VS}, AF_INT_DST },
{"ADDC_UINT", 2, { -1, 0x52 },{ 0, 0, AF_VS, AF_VS}, AF_UINT_DST },
{"SUBB_UINT", 2, { -1, 0x53 },{ 0, 0, AF_VS, AF_VS}, AF_UINT_DST },
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 9b66105641a..384ba800a79 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -90,7 +90,7 @@
struct r600_context;
struct r600_bytecode;
-struct r600_shader_key;
+union r600_shader_key;
/* This is an atom containing GPU commands that never change.
* This is supposed to be copied directly into the CS. */
@@ -643,7 +643,7 @@ void r600_resource_copy_region(struct pipe_context *ctx,
/* r600_shader.c */
int r600_pipe_shader_create(struct pipe_context *ctx,
struct r600_pipe_shader *shader,
- struct r600_shader_key key);
+ union r600_shader_key key);
void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *shader);
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index 8d1f95abddc..4c4b6005981 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -62,7 +62,7 @@ The compiler must issue the source argument to slots z, y, and x
static int r600_shader_from_tgsi(struct r600_context *rctx,
struct r600_pipe_shader *pipeshader,
- struct r600_shader_key key);
+ union r600_shader_key key);
static void r600_add_gpr_array(struct r600_shader *ps, int start_gpr,
@@ -133,7 +133,7 @@ static int store_shader(struct pipe_context *ctx,
int r600_pipe_shader_create(struct pipe_context *ctx,
struct r600_pipe_shader *shader,
- struct r600_shader_key key)
+ union r600_shader_key key)
{
struct r600_context *rctx = (struct r600_context *)ctx;
struct r600_pipe_shader_selector *sel = shader->selector;
@@ -141,7 +141,7 @@ int r600_pipe_shader_create(struct pipe_context *ctx,
bool dump = r600_can_dump_shader(&rctx->screen->b, sel->tokens);
unsigned use_sb = !(rctx->screen->b.debug_flags & DBG_NO_SB);
unsigned sb_disasm = use_sb || (rctx->screen->b.debug_flags & DBG_SB_DISASM);
- unsigned export_shader = key.vs_as_es;
+ unsigned export_shader = key.vs.as_es;
shader->shader.bc.isa = rctx->isa;
@@ -1802,7 +1802,7 @@ static int emit_gs_ring_writes(struct r600_shader_ctx *ctx, bool ind)
static int r600_shader_from_tgsi(struct r600_context *rctx,
struct r600_pipe_shader *pipeshader,
- struct r600_shader_key key)
+ union r600_shader_key key)
{
struct r600_screen *rscreen = rctx->screen;
struct r600_shader *shader = &pipeshader->shader;
@@ -1816,7 +1816,7 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
unsigned opcode;
int i, j, k, r = 0;
int next_param_base = 0, next_clip_base;
- int max_color_exports = MAX2(key.nr_cbufs, 1);
+ int max_color_exports = MAX2(key.ps.nr_cbufs, 1);
/* Declarations used by llvm code */
bool use_llvm = false;
bool indirect_gprs;
@@ -1830,8 +1830,8 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
ctx.shader = shader;
ctx.native_integers = true;
- shader->vs_as_gs_a = key.vs_as_gs_a;
- shader->vs_as_es = key.vs_as_es;
+ shader->vs_as_gs_a = key.vs.as_gs_a;
+ shader->vs_as_es = key.vs.as_es;
r600_bytecode_init(ctx.bc, rscreen->b.chip_class, rscreen->b.family,
rscreen->has_compressed_msaa_texturing);
@@ -1844,9 +1844,9 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
shader->processor_type = ctx.type;
ctx.bc->type = shader->processor_type;
- ring_outputs = key.vs_as_es || (ctx.type == TGSI_PROCESSOR_GEOMETRY);
+ ring_outputs = key.vs.as_es || (ctx.type == TGSI_PROCESSOR_GEOMETRY);
- if (key.vs_as_es) {
+ if (key.vs.as_es) {
ctx.gs_for_vs = &rctx->gs_shader->current->shader;
} else {
ctx.gs_for_vs = NULL;
@@ -1866,7 +1866,7 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
shader->nr_ps_color_exports = 0;
shader->nr_ps_max_color_exports = 0;
- shader->two_side = key.color_two_side;
+ shader->two_side = key.ps.color_two_side;
/* register allocations */
/* Values [0,127] correspond to GPR[0..127].
@@ -1970,7 +1970,7 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
shader->fs_write_all = FALSE;
if (shader->vs_as_gs_a)
- vs_add_primid_output(&ctx, key.vs_prim_id_out);
+ vs_add_primid_output(&ctx, key.vs.prim_id_out);
while (!tgsi_parse_end_of_tokens(&ctx.parse)) {
tgsi_parse_token(&ctx.parse);
@@ -2091,7 +2091,7 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
radeon_llvm_ctx.chip_class = ctx.bc->chip_class;
radeon_llvm_ctx.fs_color_all = shader->fs_write_all && (rscreen->b.chip_class >= EVERGREEN);
radeon_llvm_ctx.stream_outputs = &so;
- radeon_llvm_ctx.alpha_to_one = key.alpha_to_one;
+ radeon_llvm_ctx.alpha_to_one = key.ps.alpha_to_one;
radeon_llvm_ctx.has_compressed_msaa_texturing =
ctx.bc->has_compressed_msaa_texturing;
mod = r600_tgsi_llvm(&radeon_llvm_ctx, tokens);
@@ -2270,7 +2270,7 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
convert_edgeflag_to_int(&ctx);
if (ring_outputs) {
- if (key.vs_as_es)
+ if (key.vs.as_es)
emit_gs_ring_writes(&ctx, FALSE);
} else {
/* Export output */
@@ -2386,7 +2386,7 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
j--;
continue;
}
- output[j].swizzle_w = key.alpha_to_one ? 5 : 3;
+ output[j].swizzle_w = key.ps.alpha_to_one ? 5 : 3;
output[j].array_base = shader->output[i].sid;
output[j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
shader->nr_ps_color_exports++;
@@ -2399,7 +2399,7 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
output[j].swizzle_x = 0;
output[j].swizzle_y = 1;
output[j].swizzle_z = 2;
- output[j].swizzle_w = key.alpha_to_one ? 5 : 3;
+ output[j].swizzle_w = key.ps.alpha_to_one ? 5 : 3;
output[j].burst_count = 1;
output[j].array_base = k;
output[j].op = CF_OP_EXPORT;
@@ -6151,10 +6151,10 @@ static int tgsi_cmp(struct r600_shader_ctx *ctx)
r = tgsi_make_src_for_op3(ctx, temp_regs[0], i, &alu.src[0], &ctx->src[0]);
if (r)
return r;
- r = tgsi_make_src_for_op3(ctx, temp_regs[1], i, &alu.src[1], &ctx->src[2]);
+ r = tgsi_make_src_for_op3(ctx, temp_regs[2], i, &alu.src[1], &ctx->src[2]);
if (r)
return r;
- r = tgsi_make_src_for_op3(ctx, temp_regs[2], i, &alu.src[2], &ctx->src[1]);
+ r = tgsi_make_src_for_op3(ctx, temp_regs[1], i, &alu.src[2], &ctx->src[1]);
if (r)
return r;
tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst);
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
index 5d05c8153d7..927bac57673 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -95,13 +95,17 @@ struct r600_shader {
struct r600_shader_array * arrays;
};
-struct r600_shader_key {
- unsigned color_two_side:1;
- unsigned alpha_to_one:1;
- unsigned nr_cbufs:4;
- unsigned vs_as_es:1;
- unsigned vs_as_gs_a:1;
- unsigned vs_prim_id_out:8;
+union r600_shader_key {
+ struct {
+ unsigned nr_cbufs:4;
+ unsigned color_two_side:1;
+ unsigned alpha_to_one:1;
+ } ps;
+ struct {
+ unsigned prim_id_out:8;
+ unsigned as_es:1; /* export shader */
+ unsigned as_gs_a:1;
+ } vs;
};
struct r600_shader_array {
@@ -122,7 +126,7 @@ struct r600_pipe_shader {
unsigned flatshade;
unsigned pa_cl_vs_out_cntl;
unsigned nr_ps_color_outputs;
- struct r600_shader_key key;
+ union r600_shader_key key;
unsigned db_shader_control;
unsigned ps_depth_export;
unsigned enabled_stream_buffers_mask;
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index aa4a8d0240f..a05dd8352c7 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -702,29 +702,39 @@ void r600_emit_viewport_state(struct r600_context *rctx, struct r600_atom *atom)
}
/* Compute the key for the hw shader variant */
-static inline struct r600_shader_key r600_shader_selector_key(struct pipe_context * ctx,
+static inline union r600_shader_key r600_shader_selector_key(struct pipe_context * ctx,
struct r600_pipe_shader_selector * sel)
{
struct r600_context *rctx = (struct r600_context *)ctx;
- struct r600_shader_key key;
+ union r600_shader_key key;
memset(&key, 0, sizeof(key));
- if (sel->type == PIPE_SHADER_FRAGMENT) {
- key.color_two_side = rctx->rasterizer && rctx->rasterizer->two_side;
- key.alpha_to_one = rctx->alpha_to_one &&
- rctx->rasterizer && rctx->rasterizer->multisample_enable &&
- !rctx->framebuffer.cb0_is_integer;
- key.nr_cbufs = rctx->framebuffer.state.nr_cbufs;
- /* Dual-source blending only makes sense with nr_cbufs == 1. */
- if (key.nr_cbufs == 1 && rctx->dual_src_blend)
- key.nr_cbufs = 2;
- } else if (sel->type == PIPE_SHADER_VERTEX) {
- key.vs_as_es = (rctx->gs_shader != NULL);
+ switch (sel->type) {
+ case PIPE_SHADER_VERTEX: {
+ key.vs.as_es = (rctx->gs_shader != NULL);
if (rctx->ps_shader->current->shader.gs_prim_id_input && !rctx->gs_shader) {
- key.vs_as_gs_a = true;
- key.vs_prim_id_out = rctx->ps_shader->current->shader.input[rctx->ps_shader->current->shader.ps_prim_id_input].spi_sid;
+ key.vs.as_gs_a = true;
+ key.vs.prim_id_out = rctx->ps_shader->current->shader.input[rctx->ps_shader->current->shader.ps_prim_id_input].spi_sid;
}
+ break;
+ }
+ case PIPE_SHADER_GEOMETRY:
+ break;
+ case PIPE_SHADER_FRAGMENT: {
+ key.ps.color_two_side = rctx->rasterizer && rctx->rasterizer->two_side;
+ key.ps.alpha_to_one = rctx->alpha_to_one &&
+ rctx->rasterizer && rctx->rasterizer->multisample_enable &&
+ !rctx->framebuffer.cb0_is_integer;
+ key.ps.nr_cbufs = rctx->framebuffer.state.nr_cbufs;
+ /* Dual-source blending only makes sense with nr_cbufs == 1. */
+ if (key.ps.nr_cbufs == 1 && rctx->dual_src_blend)
+ key.ps.nr_cbufs = 2;
+ break;
}
+ default:
+ assert(0);
+ }
+
return key;
}
@@ -734,7 +744,7 @@ static int r600_shader_select(struct pipe_context *ctx,
struct r600_pipe_shader_selector* sel,
bool *dirty)
{
- struct r600_shader_key key;
+ union r600_shader_key key;
struct r600_pipe_shader * shader = NULL;
int r;
diff --git a/src/gallium/drivers/radeon/radeon_uvd.c b/src/gallium/drivers/radeon/radeon_uvd.c
index 16ee5410273..81f3f45db9f 100644
--- a/src/gallium/drivers/radeon/radeon_uvd.c
+++ b/src/gallium/drivers/radeon/radeon_uvd.c
@@ -209,8 +209,6 @@ static uint32_t profile2stream_type(struct ruvd_decoder *dec, unsigned family)
static unsigned calc_ctx_size(struct ruvd_decoder *dec)
{
- unsigned width_in_mb, height_in_mb, ctx_size;
-
unsigned width = align(dec->base.width, VL_MACROBLOCK_WIDTH);
unsigned height = align(dec->base.height, VL_MACROBLOCK_HEIGHT);
@@ -223,8 +221,7 @@ static unsigned calc_ctx_size(struct ruvd_decoder *dec)
width = align (width, 16);
height = align (height, 16);
- ctx_size = ((width + 255) / 16)*((height + 255) / 16) * 16 * max_references + 52 * 1024;
- return ctx_size;
+ return ((width + 255) / 16) * ((height + 255) / 16) * 16 * max_references + 52 * 1024;
}
/* calculate size of reference picture buffer */
diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c
index 48972bd170c..b7450b6fcec 100644
--- a/src/gallium/drivers/radeonsi/si_blit.c
+++ b/src/gallium/drivers/radeonsi/si_blit.c
@@ -586,7 +586,8 @@ void si_resource_copy_region(struct pipe_context *ctx,
si_blitter_begin(ctx, SI_COPY);
util_blitter_blit_generic(sctx->blitter, dst_view, &dstbox,
src_view, src_box, src_width0, src_height0,
- PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL);
+ PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL,
+ FALSE);
si_blitter_end(ctx);
pipe_surface_reference(&dst_view, NULL);
diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index 4288e9b2ab1..fa6c15a6591 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -2277,7 +2277,7 @@ static void tex_fetch_args(
unsigned sampler_index;
unsigned num_deriv_channels = 0;
bool has_offset = HAVE_LLVM >= 0x0305 ? inst->Texture.NumOffsets > 0 : false;
- LLVMValueRef res_ptr, samp_ptr;
+ LLVMValueRef res_ptr, samp_ptr, fmask_ptr = NULL;
sampler_src = emit_data->inst->Instruction.NumSrcRegs - 1;
sampler_index = emit_data->inst->Src[sampler_src].Register.Index;
@@ -2293,9 +2293,19 @@ static void tex_fetch_args(
samp_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_SAMPLER);
samp_ptr = build_indexed_load_const(si_shader_ctx, samp_ptr, ind_index);
+
+ if (target == TGSI_TEXTURE_2D_MSAA ||
+ target == TGSI_TEXTURE_2D_ARRAY_MSAA) {
+ ind_index = LLVMBuildAdd(gallivm->builder, ind_index,
+ lp_build_const_int32(gallivm,
+ SI_FMASK_TEX_OFFSET), "");
+ fmask_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_RESOURCE);
+ fmask_ptr = build_indexed_load_const(si_shader_ctx, res_ptr, ind_index);
+ }
} else {
res_ptr = si_shader_ctx->resources[sampler_index];
samp_ptr = si_shader_ctx->samplers[sampler_index];
+ fmask_ptr = si_shader_ctx->resources[SI_FMASK_TEX_OFFSET + sampler_index];
}
if (target == TGSI_TEXTURE_BUFFER) {
@@ -2493,7 +2503,7 @@ static void tex_fetch_args(
txf_emit_data.dst_type = LLVMVectorType(
LLVMInt32TypeInContext(gallivm->context), 4);
txf_emit_data.args[0] = lp_build_gather_values(gallivm, txf_address, txf_count);
- txf_emit_data.args[1] = si_shader_ctx->resources[SI_FMASK_TEX_OFFSET + sampler_index];
+ txf_emit_data.args[1] = fmask_ptr;
txf_emit_data.args[2] = lp_build_const_int32(gallivm, inst.Texture.Texture);
txf_emit_data.arg_count = 3;
@@ -2524,8 +2534,7 @@ static void tex_fetch_args(
* resource descriptor is 0 (invalid),
*/
LLVMValueRef fmask_desc =
- LLVMBuildBitCast(gallivm->builder,
- si_shader_ctx->resources[SI_FMASK_TEX_OFFSET + sampler_index],
+ LLVMBuildBitCast(gallivm->builder, fmask_ptr,
LLVMVectorType(uint_bld->elem_type, 8), "");
LLVMValueRef fmask_word1 =
@@ -3973,7 +3982,7 @@ static void si_dump_key(unsigned shader, union si_shader_key *key)
fprintf(stderr, " es_enabled_outputs = 0x%"PRIx64"\n",
key->vs.es_enabled_outputs);
fprintf(stderr, " as_es = %u\n", key->vs.as_es);
- fprintf(stderr, " as_es = %u\n", key->vs.as_ls);
+ fprintf(stderr, " as_ls = %u\n", key->vs.as_ls);
break;
case PIPE_SHADER_TESS_CTRL:
diff --git a/src/gallium/drivers/vc4/vc4_context.h b/src/gallium/drivers/vc4/vc4_context.h
index 654c46f3c0d..3a63af8f2b0 100644
--- a/src/gallium/drivers/vc4/vc4_context.h
+++ b/src/gallium/drivers/vc4/vc4_context.h
@@ -270,6 +270,7 @@ struct vc4_context {
struct ra_regs *regs;
unsigned int reg_class_any;
+ unsigned int reg_class_a_or_b_or_acc;
unsigned int reg_class_r4_or_a;
unsigned int reg_class_a;
diff --git a/src/gallium/drivers/vc4/vc4_opt_algebraic.c b/src/gallium/drivers/vc4/vc4_opt_algebraic.c
index 7978ea1829f..5b435832b92 100644
--- a/src/gallium/drivers/vc4/vc4_opt_algebraic.c
+++ b/src/gallium/drivers/vc4/vc4_opt_algebraic.c
@@ -143,15 +143,6 @@ qir_opt_algebraic(struct vc4_compile *c)
case QOP_SEL_X_Y_ZC:
case QOP_SEL_X_Y_NS:
case QOP_SEL_X_Y_NC:
- if (qir_reg_equals(inst->src[0], inst->src[1])) {
- /* Turn "dst = (sf == x) ? a : a)" into
- * "dst = a"
- */
- replace_with_mov(c, inst, inst->src[1]);
- progress = true;
- break;
- }
-
if (is_zero(c, inst->src[1])) {
/* Replace references to a 0 uniform value
* with the SEL_X_0 equivalent.
@@ -207,6 +198,7 @@ qir_opt_algebraic(struct vc4_compile *c)
/* FADD(a, FSUB(0, b)) -> FSUB(a, b) */
if (inst->src[1].file == QFILE_TEMP &&
+ c->defs[inst->src[1].index] &&
c->defs[inst->src[1].index]->op == QOP_FSUB) {
struct qinst *fsub = c->defs[inst->src[1].index];
if (is_zero(c, fsub->src[0])) {
@@ -221,6 +213,7 @@ qir_opt_algebraic(struct vc4_compile *c)
/* FADD(FSUB(0, b), a) -> FSUB(a, b) */
if (inst->src[0].file == QFILE_TEMP &&
+ c->defs[inst->src[0].index] &&
c->defs[inst->src[0].index]->op == QOP_FSUB) {
struct qinst *fsub = c->defs[inst->src[0].index];
if (is_zero(c, fsub->src[0])) {
@@ -236,18 +229,20 @@ qir_opt_algebraic(struct vc4_compile *c)
break;
case QOP_FMUL:
- if (replace_x_0_with_0(c, inst, 0) ||
- replace_x_0_with_0(c, inst, 1) ||
- fmul_replace_one(c, inst, 0) ||
- fmul_replace_one(c, inst, 1)) {
+ if (!inst->dst.pack &&
+ (replace_x_0_with_0(c, inst, 0) ||
+ replace_x_0_with_0(c, inst, 1) ||
+ fmul_replace_one(c, inst, 0) ||
+ fmul_replace_one(c, inst, 1))) {
progress = true;
break;
}
break;
case QOP_MUL24:
- if (replace_x_0_with_0(c, inst, 0) ||
- replace_x_0_with_0(c, inst, 1)) {
+ if (!inst->dst.pack &&
+ (replace_x_0_with_0(c, inst, 0) ||
+ replace_x_0_with_0(c, inst, 1))) {
progress = true;
break;
}
@@ -280,6 +275,14 @@ qir_opt_algebraic(struct vc4_compile *c)
}
break;
+ case QOP_RCP:
+ if (is_1f(c, inst->src[0])) {
+ replace_with_mov(c, inst, inst->src[0]);
+ progress = true;
+ break;
+ }
+ break;
+
default:
break;
}
diff --git a/src/gallium/drivers/vc4/vc4_opt_copy_propagation.c b/src/gallium/drivers/vc4/vc4_opt_copy_propagation.c
index a755de9aa41..fd2539aed95 100644
--- a/src/gallium/drivers/vc4/vc4_opt_copy_propagation.c
+++ b/src/gallium/drivers/vc4/vc4_opt_copy_propagation.c
@@ -39,21 +39,27 @@ qir_opt_copy_propagation(struct vc4_compile *c)
{
bool progress = false;
bool debug = false;
- struct qreg *movs = calloc(c->num_temps, sizeof(struct qreg));
list_for_each_entry(struct qinst, inst, &c->instructions, link) {
for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
int index = inst->src[i].index;
if (inst->src[i].file == QFILE_TEMP &&
- (movs[index].file == QFILE_TEMP ||
- movs[index].file == QFILE_UNIF)) {
+ c->defs[index] &&
+ c->defs[index]->op == QOP_MOV &&
+ (c->defs[index]->src[0].file == QFILE_TEMP ||
+ c->defs[index]->src[0].file == QFILE_UNIF)) {
+ /* If it has a pack, it shouldn't be an SSA
+ * def.
+ */
+ assert(!c->defs[index]->dst.pack);
+
if (debug) {
fprintf(stderr, "Copy propagate: ");
qir_dump_inst(c, inst);
fprintf(stderr, "\n");
}
- inst->src[i] = movs[index];
+ inst->src[i] = c->defs[index]->src[0];
if (debug) {
fprintf(stderr, "to: ");
@@ -64,14 +70,6 @@ qir_opt_copy_propagation(struct vc4_compile *c)
progress = true;
}
}
-
- if (inst->op == QOP_MOV &&
- inst->dst.file == QFILE_TEMP &&
- inst->src[0].file != QFILE_VPM) {
- movs[inst->dst.index] = inst->src[0];
- }
}
-
- free(movs);
return progress;
}
diff --git a/src/gallium/drivers/vc4/vc4_opt_vpm_writes.c b/src/gallium/drivers/vc4/vc4_opt_vpm_writes.c
index e04f02859d5..f2cdf8f694f 100644
--- a/src/gallium/drivers/vc4/vc4_opt_vpm_writes.c
+++ b/src/gallium/drivers/vc4/vc4_opt_vpm_writes.c
@@ -68,7 +68,7 @@ qir_opt_vpm_writes(struct vc4_compile *c)
continue;
struct qinst *inst = c->defs[temp];
- if (qir_is_multi_instruction(inst))
+ if (!inst || qir_is_multi_instruction(inst))
continue;
if (qir_depends_on_flags(inst) || inst->sf)
@@ -79,22 +79,6 @@ qir_opt_vpm_writes(struct vc4_compile *c)
continue;
}
- /* A QOP_TEX_RESULT destination is r4, so we can't move
- * accesses to it past another QOP_TEX_RESULT which would
- * update it.
- */
- int src;
- for (src = 0; src < qir_get_op_nsrc(inst->op); src++) {
- if (inst->src[src].file == QFILE_TEMP) {
- if (c->defs[inst->src[src].index]->op ==
- QOP_TEX_RESULT) {
- break;
- }
- }
- }
- if (src != qir_get_op_nsrc(inst->op))
- continue;
-
/* Move the generating instruction to the end of the program
* to maintain the order of the VPM writes.
*/
diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c
index 13c472152d8..e002983fdbb 100644
--- a/src/gallium/drivers/vc4/vc4_program.c
+++ b/src/gallium/drivers/vc4/vc4_program.c
@@ -818,6 +818,72 @@ declare_uniform_range(struct vc4_compile *c, uint32_t start, uint32_t size)
c->ubo_ranges[array_id].used = false;
}
+static bool
+ntq_src_is_only_ssa_def_user(nir_src *src)
+{
+ if (!src->is_ssa)
+ return false;
+
+ if (!list_empty(&src->ssa->if_uses))
+ return false;
+
+ return (src->ssa->uses.next == &src->use_link &&
+ src->ssa->uses.next->next == &src->ssa->uses);
+}
+
+/**
+ * In general, emits a nir_pack_unorm_4x8 as a series of MOVs with the pack
+ * bit set.
+ *
+ * However, as an optimization, it tries to find the instructions generating
+ * the sources to be packed and just emit the pack flag there, if possible.
+ */
+static void
+ntq_emit_pack_unorm_4x8(struct vc4_compile *c, nir_alu_instr *instr)
+{
+ struct qreg result = qir_get_temp(c);
+ struct nir_alu_instr *vec4 = NULL;
+
+ /* If packing from a vec4 op (as expected), identify it so that we can
+ * peek back at what generated its sources.
+ */
+ if (instr->src[0].src.is_ssa &&
+ instr->src[0].src.ssa->parent_instr->type == nir_instr_type_alu &&
+ nir_instr_as_alu(instr->src[0].src.ssa->parent_instr)->op ==
+ nir_op_vec4) {
+ vec4 = nir_instr_as_alu(instr->src[0].src.ssa->parent_instr);
+ }
+
+ for (int i = 0; i < 4; i++) {
+ int swiz = instr->src[0].swizzle[i];
+ struct qreg src;
+ if (vec4) {
+ src = ntq_get_src(c, vec4->src[swiz].src,
+ vec4->src[swiz].swizzle[0]);
+ } else {
+ src = ntq_get_src(c, instr->src[0].src, swiz);
+ }
+
+ if (vec4 &&
+ ntq_src_is_only_ssa_def_user(&vec4->src[swiz].src) &&
+ src.file == QFILE_TEMP &&
+ c->defs[src.index] &&
+ qir_is_mul(c->defs[src.index]) &&
+ !c->defs[src.index]->dst.pack) {
+ struct qinst *rewrite = c->defs[src.index];
+ c->defs[src.index] = NULL;
+ rewrite->dst = result;
+ rewrite->dst.pack = QPU_PACK_MUL_8A + i;
+ continue;
+ }
+
+ qir_PACK_8_F(c, result, src, i);
+ }
+
+ struct qreg *dest = ntq_get_dest(c, &instr->dest.dest);
+ *dest = result;
+}
+
static void
ntq_emit_alu(struct vc4_compile *c, nir_alu_instr *instr)
{
@@ -839,17 +905,7 @@ ntq_emit_alu(struct vc4_compile *c, nir_alu_instr *instr)
}
if (instr->op == nir_op_pack_unorm_4x8) {
- struct qreg result;
- for (int i = 0; i < 4; i++) {
- struct qreg src = ntq_get_src(c, instr->src[0].src,
- instr->src[0].swizzle[i]);
- if (i == 0)
- result = qir_PACK_8888_F(c, src);
- else
- result = qir_PACK_8_F(c, result, src, i);
- }
- struct qreg *dest = ntq_get_dest(c, &instr->dest.dest);
- *dest = result;
+ ntq_emit_pack_unorm_4x8(c, instr);
return;
}
@@ -1130,20 +1186,24 @@ emit_frag_end(struct vc4_compile *c)
static void
emit_scaled_viewport_write(struct vc4_compile *c, struct qreg rcp_w)
{
- struct qreg xyi[2];
+ struct qreg packed = qir_get_temp(c);
for (int i = 0; i < 2; i++) {
struct qreg scale =
qir_uniform(c, QUNIFORM_VIEWPORT_X_SCALE + i, 0);
- xyi[i] = qir_FTOI(c, qir_FMUL(c,
- qir_FMUL(c,
- c->outputs[c->output_position_index + i],
- scale),
- rcp_w));
+ struct qreg packed_chan = packed;
+ packed_chan.pack = QPU_PACK_A_16A + i;
+
+ qir_FTOI_dest(c, packed_chan,
+ qir_FMUL(c,
+ qir_FMUL(c,
+ c->outputs[c->output_position_index + i],
+ scale),
+ rcp_w));
}
- qir_VPM_WRITE(c, qir_PACK_SCALED(c, xyi[0], xyi[1]));
+ qir_VPM_WRITE(c, packed);
}
static void
diff --git a/src/gallium/drivers/vc4/vc4_qir.c b/src/gallium/drivers/vc4/vc4_qir.c
index 254140a72f5..9d930715f9b 100644
--- a/src/gallium/drivers/vc4/vc4_qir.c
+++ b/src/gallium/drivers/vc4/vc4_qir.c
@@ -71,12 +71,11 @@ static const struct qir_op_info qir_op_info[] = {
[QOP_RSQ] = { "rsq", 1, 1, false, true },
[QOP_EXP2] = { "exp2", 1, 2, false, true },
[QOP_LOG2] = { "log2", 1, 2, false, true },
- [QOP_PACK_8888_F] = { "pack_8888_f", 1, 1, false, true },
- [QOP_PACK_8A_F] = { "pack_8a_f", 1, 2, false, true },
- [QOP_PACK_8B_F] = { "pack_8b_f", 1, 2, false, true },
- [QOP_PACK_8C_F] = { "pack_8c_f", 1, 2, false, true },
- [QOP_PACK_8D_F] = { "pack_8d_f", 1, 2, false, true },
- [QOP_PACK_SCALED] = { "pack_scaled", 1, 2, false, true },
+ [QOP_PACK_8888_F] = { "pack_8888_f", 1, 1 },
+ [QOP_PACK_8A_F] = { "pack_8a_f", 1, 1 },
+ [QOP_PACK_8B_F] = { "pack_8b_f", 1, 1 },
+ [QOP_PACK_8C_F] = { "pack_8c_f", 1, 1 },
+ [QOP_PACK_8D_F] = { "pack_8d_f", 1, 1 },
[QOP_TLB_DISCARD_SETUP] = { "discard", 0, 1, true },
[QOP_TLB_STENCIL_SETUP] = { "tlb_stencil_setup", 0, 1, true },
[QOP_TLB_Z_WRITE] = { "tlb_z", 0, 1, true },
@@ -169,6 +168,18 @@ qir_is_multi_instruction(struct qinst *inst)
}
bool
+qir_is_mul(struct qinst *inst)
+{
+ switch (inst->op) {
+ case QOP_FMUL:
+ case QOP_MUL24:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
qir_is_tex(struct qinst *inst)
{
return inst->op >= QOP_TEX_S && inst->op <= QOP_TEX_DIRECT;
@@ -273,6 +284,14 @@ qir_dump_inst(struct vc4_compile *c, struct qinst *inst)
inst->sf ? ".sf" : "");
qir_print_reg(c, inst->dst, true);
+ if (inst->dst.pack) {
+ if (inst->dst.pack) {
+ if (qir_is_mul(inst))
+ vc4_qpu_disasm_pack_mul(stderr, inst->dst.pack);
+ else
+ vc4_qpu_disasm_pack_a(stderr, inst->dst.pack);
+ }
+ }
for (int i = 0; i < qir_get_op_nsrc(inst->op); i++) {
fprintf(stderr, ", ");
qir_print_reg(c, inst->src[i], false);
@@ -348,7 +367,7 @@ qir_emit(struct vc4_compile *c, struct qinst *inst)
if (inst->dst.file == QFILE_TEMP)
c->defs[inst->dst.index] = inst;
- list_addtail(&inst->link, &c->instructions);
+ qir_emit_nodef(c, inst);
}
bool
@@ -389,8 +408,11 @@ qir_remove_instruction(struct vc4_compile *c, struct qinst *qinst)
struct qreg
qir_follow_movs(struct vc4_compile *c, struct qreg reg)
{
- while (reg.file == QFILE_TEMP && c->defs[reg.index]->op == QOP_MOV)
+ while (reg.file == QFILE_TEMP &&
+ c->defs[reg.index] &&
+ c->defs[reg.index]->op == QOP_MOV) {
reg = c->defs[reg.index]->src[0];
+ }
return reg;
}
diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h
index cade795c12a..a2b21fa17bb 100644
--- a/src/gallium/drivers/vc4/vc4_qir.h
+++ b/src/gallium/drivers/vc4/vc4_qir.h
@@ -58,6 +58,7 @@ enum qfile {
struct qreg {
enum qfile file;
uint32_t index;
+ int pack;
};
enum qop {
@@ -104,7 +105,6 @@ enum qop {
QOP_LOG2,
QOP_VW_SETUP,
QOP_VR_SETUP,
- QOP_PACK_SCALED,
QOP_PACK_8888_F,
QOP_PACK_8A_F,
QOP_PACK_8B_F,
@@ -444,13 +444,20 @@ struct qreg qir_uniform(struct vc4_compile *c,
enum quniform_contents contents,
uint32_t data);
void qir_reorder_uniforms(struct vc4_compile *c);
+
void qir_emit(struct vc4_compile *c, struct qinst *inst);
+static inline void qir_emit_nodef(struct vc4_compile *c, struct qinst *inst)
+{
+ list_addtail(&inst->link, &c->instructions);
+}
+
struct qreg qir_get_temp(struct vc4_compile *c);
int qir_get_op_nsrc(enum qop qop);
bool qir_reg_equals(struct qreg a, struct qreg b);
bool qir_has_side_effects(struct vc4_compile *c, struct qinst *inst);
bool qir_has_side_effect_reads(struct vc4_compile *c, struct qinst *inst);
bool qir_is_multi_instruction(struct qinst *inst);
+bool qir_is_mul(struct qinst *inst);
bool qir_is_tex(struct qinst *inst);
bool qir_depends_on_flags(struct qinst *inst);
bool qir_writes_r4(struct qinst *inst);
@@ -509,6 +516,12 @@ qir_##name(struct vc4_compile *c, struct qreg a) \
struct qreg t = qir_get_temp(c); \
qir_emit(c, qir_inst(QOP_##name, t, a, c->undef)); \
return t; \
+} \
+static inline void \
+qir_##name##_dest(struct vc4_compile *c, struct qreg dest, \
+ struct qreg a) \
+{ \
+ qir_emit_nodef(c, qir_inst(QOP_##name, dest, a, c->undef)); \
}
#define QIR_ALU2(name) \
@@ -518,6 +531,12 @@ qir_##name(struct vc4_compile *c, struct qreg a, struct qreg b) \
struct qreg t = qir_get_temp(c); \
qir_emit(c, qir_inst(QOP_##name, t, a, b)); \
return t; \
+} \
+static inline void \
+qir_##name##_dest(struct vc4_compile *c, struct qreg dest, \
+ struct qreg a, struct qreg b) \
+{ \
+ qir_emit_nodef(c, qir_inst(QOP_##name, dest, a, b)); \
}
#define QIR_NODST_1(name) \
@@ -534,6 +553,14 @@ qir_##name(struct vc4_compile *c, struct qreg a, struct qreg b) \
qir_emit(c, qir_inst(QOP_##name, c->undef, a, b)); \
}
+#define QIR_PACK(name) \
+static inline struct qreg \
+qir_##name(struct vc4_compile *c, struct qreg dest, struct qreg a) \
+{ \
+ qir_emit_nodef(c, qir_inst(QOP_##name, dest, a, c->undef)); \
+ return dest; \
+}
+
QIR_ALU1(MOV)
QIR_ALU2(FADD)
QIR_ALU2(FSUB)
@@ -570,12 +597,11 @@ QIR_ALU1(RCP)
QIR_ALU1(RSQ)
QIR_ALU1(EXP2)
QIR_ALU1(LOG2)
-QIR_ALU2(PACK_SCALED)
QIR_ALU1(PACK_8888_F)
-QIR_ALU2(PACK_8A_F)
-QIR_ALU2(PACK_8B_F)
-QIR_ALU2(PACK_8C_F)
-QIR_ALU2(PACK_8D_F)
+QIR_PACK(PACK_8A_F)
+QIR_PACK(PACK_8B_F)
+QIR_PACK(PACK_8C_F)
+QIR_PACK(PACK_8D_F)
QIR_ALU1(VARY_ADD_C)
QIR_NODST_2(TEX_S)
QIR_NODST_2(TEX_T)
@@ -627,11 +653,12 @@ qir_UNPACK_16_I(struct vc4_compile *c, struct qreg src, int i)
}
static inline struct qreg
-qir_PACK_8_F(struct vc4_compile *c, struct qreg rest, struct qreg val, int chan)
+qir_PACK_8_F(struct vc4_compile *c, struct qreg dest, struct qreg val, int chan)
{
- struct qreg t = qir_get_temp(c);
- qir_emit(c, qir_inst(QOP_PACK_8A_F + chan, t, rest, val));
- return t;
+ qir_emit(c, qir_inst(QOP_PACK_8A_F + chan, dest, val, c->undef));
+ if (dest.file == QFILE_TEMP)
+ c->defs[dest.index] = NULL;
+ return dest;
}
static inline struct qreg
diff --git a/src/gallium/drivers/vc4/vc4_qpu.h b/src/gallium/drivers/vc4/vc4_qpu.h
index fbb90ba12a0..0719d2828b5 100644
--- a/src/gallium/drivers/vc4/vc4_qpu.h
+++ b/src/gallium/drivers/vc4/vc4_qpu.h
@@ -24,6 +24,7 @@
#ifndef VC4_QPU_H
#define VC4_QPU_H
+#include <stdio.h>
#include <stdint.h>
#include "util/u_math.h"
@@ -206,6 +207,12 @@ void
vc4_qpu_disasm(const uint64_t *instructions, int num_instructions);
void
+vc4_qpu_disasm_pack_mul(FILE *out, uint32_t pack);
+
+void
+vc4_qpu_disasm_pack_a(FILE *out, uint32_t pack);
+
+void
vc4_qpu_validate(uint64_t *insts, uint32_t num_inst);
#endif /* VC4_QPU_H */
diff --git a/src/gallium/drivers/vc4/vc4_qpu_disasm.c b/src/gallium/drivers/vc4/vc4_qpu_disasm.c
index 00aeb300a9b..0879787ec03 100644
--- a/src/gallium/drivers/vc4/vc4_qpu_disasm.c
+++ b/src/gallium/drivers/vc4/vc4_qpu_disasm.c
@@ -245,6 +245,18 @@ get_special_write_desc(int reg, bool is_a)
return special_write[reg];
}
+void
+vc4_qpu_disasm_pack_mul(FILE *out, uint32_t pack)
+{
+ fprintf(out, ".%s", DESC(qpu_pack_mul, pack));
+}
+
+void
+vc4_qpu_disasm_pack_a(FILE *out, uint32_t pack)
+{
+ fprintf(out, "%s", DESC(qpu_pack_a, pack));
+}
+
static void
print_alu_dst(uint64_t inst, bool is_mul)
{
@@ -263,9 +275,9 @@ print_alu_dst(uint64_t inst, bool is_mul)
fprintf(stderr, "%s%d?", file, waddr);
if (is_mul && (inst & QPU_PM)) {
- fprintf(stderr, ".%s", DESC(qpu_pack_mul, pack));
+ vc4_qpu_disasm_pack_mul(stderr, pack);
} else if (is_a && !(inst & QPU_PM)) {
- fprintf(stderr, "%s", DESC(qpu_pack_a, pack));
+ vc4_qpu_disasm_pack_a(stderr, pack);
}
}
diff --git a/src/gallium/drivers/vc4/vc4_qpu_emit.c b/src/gallium/drivers/vc4/vc4_qpu_emit.c
index f324056258c..adf3a8b3658 100644
--- a/src/gallium/drivers/vc4/vc4_qpu_emit.c
+++ b/src/gallium/drivers/vc4/vc4_qpu_emit.c
@@ -179,10 +179,9 @@ vc4_generate_code(struct vc4_context *vc4, struct vc4_compile *c)
static const struct {
uint32_t op;
- bool is_mul;
} translate[] = {
-#define A(name) [QOP_##name] = {QPU_A_##name, false}
-#define M(name) [QOP_##name] = {QPU_M_##name, true}
+#define A(name) [QOP_##name] = {QPU_A_##name}
+#define M(name) [QOP_##name] = {QPU_M_##name}
A(FADD),
A(FSUB),
A(FMIN),
@@ -336,28 +335,12 @@ vc4_generate_code(struct vc4_context *vc4, struct vc4_compile *c)
case QOP_PACK_8B_F:
case QOP_PACK_8C_F:
case QOP_PACK_8D_F:
- /* If dst doesn't happen to already contain src[0],
- * then we have to move it in.
- */
- if (qinst->src[0].file != QFILE_NULL &&
- (src[0].mux != dst.mux || src[0].addr != dst.addr)) {
- /* Don't overwrite src1 while setting up
- * the dst!
- */
- if (dst.mux == src[1].mux &&
- dst.addr == src[1].addr) {
- queue(c, qpu_m_MOV(qpu_rb(31), src[1]));
- src[1] = qpu_rb(31);
- }
-
- queue(c, qpu_m_MOV(dst, src[0]));
- }
-
- queue(c, qpu_m_MOV(dst, src[1]));
- *last_inst(c) |= QPU_PM;
- *last_inst(c) |= QPU_SET_FIELD(QPU_PACK_MUL_8A +
- qinst->op - QOP_PACK_8A_F,
- QPU_PACK);
+ queue(c,
+ qpu_m_MOV(dst, src[0]) |
+ QPU_PM |
+ QPU_SET_FIELD(QPU_PACK_MUL_8A +
+ qinst->op - QOP_PACK_8A_F,
+ QPU_PACK));
break;
case QOP_FRAG_X:
@@ -419,24 +402,6 @@ vc4_generate_code(struct vc4_context *vc4, struct vc4_compile *c)
queue(c, qpu_a_FADD(dst, src[0], qpu_r5()));
break;
- case QOP_PACK_SCALED: {
- uint64_t a = (qpu_a_MOV(dst, src[0]) |
- QPU_SET_FIELD(QPU_PACK_A_16A,
- QPU_PACK));
- uint64_t b = (qpu_a_MOV(dst, src[1]) |
- QPU_SET_FIELD(QPU_PACK_A_16B,
- QPU_PACK));
-
- if (dst.mux == src[1].mux && dst.addr == src[1].addr) {
- queue(c, b);
- queue(c, a);
- } else {
- queue(c, a);
- queue(c, b);
- }
- break;
- }
-
case QOP_TEX_S:
case QOP_TEX_T:
case QOP_TEX_R:
@@ -529,14 +494,24 @@ vc4_generate_code(struct vc4_context *vc4, struct vc4_compile *c)
fixup_raddr_conflict(c, dst, &src[0], &src[1]);
- if (translate[qinst->op].is_mul) {
+ if (qir_is_mul(qinst)) {
queue(c, qpu_m_alu2(translate[qinst->op].op,
dst,
src[0], src[1]));
+ if (qinst->dst.pack) {
+ *last_inst(c) |= QPU_PM;
+ *last_inst(c) |= QPU_SET_FIELD(qinst->dst.pack,
+ QPU_PACK);
+ }
} else {
queue(c, qpu_a_alu2(translate[qinst->op].op,
dst,
src[0], src[1]));
+ if (qinst->dst.pack) {
+ assert(dst.mux == QPU_MUX_A);
+ *last_inst(c) |= QPU_SET_FIELD(qinst->dst.pack,
+ QPU_PACK);
+ }
}
break;
diff --git a/src/gallium/drivers/vc4/vc4_register_allocate.c b/src/gallium/drivers/vc4/vc4_register_allocate.c
index a29db1f3abe..3ced50f3a44 100644
--- a/src/gallium/drivers/vc4/vc4_register_allocate.c
+++ b/src/gallium/drivers/vc4/vc4_register_allocate.c
@@ -113,9 +113,10 @@ vc4_alloc_reg_set(struct vc4_context *vc4)
if (vc4->regs)
return;
- vc4->regs = ra_alloc_reg_set(vc4, ARRAY_SIZE(vc4_regs));
+ vc4->regs = ra_alloc_reg_set(vc4, ARRAY_SIZE(vc4_regs), true);
vc4->reg_class_any = ra_alloc_reg_class(vc4->regs);
+ vc4->reg_class_a_or_b_or_acc = ra_alloc_reg_class(vc4->regs);
vc4->reg_class_r4_or_a = ra_alloc_reg_class(vc4->regs);
vc4->reg_class_a = ra_alloc_reg_class(vc4->regs);
for (uint32_t i = 0; i < ARRAY_SIZE(vc4_regs); i++) {
@@ -130,10 +131,12 @@ vc4_alloc_reg_set(struct vc4_context *vc4)
*/
if (vc4_regs[i].mux == QPU_MUX_R4) {
ra_class_add_reg(vc4->regs, vc4->reg_class_r4_or_a, i);
+ ra_class_add_reg(vc4->regs, vc4->reg_class_any, i);
continue;
}
ra_class_add_reg(vc4->regs, vc4->reg_class_any, i);
+ ra_class_add_reg(vc4->regs, vc4->reg_class_a_or_b_or_acc, i);
}
for (uint32_t i = AB_INDEX; i < AB_INDEX + 64; i += 2) {
@@ -177,7 +180,8 @@ vc4_register_allocate(struct vc4_context *vc4, struct vc4_compile *c)
uint8_t class_bits[c->num_temps];
struct qpu_reg *temp_registers = calloc(c->num_temps,
sizeof(*temp_registers));
- memset(def, 0, sizeof(def));
+ for (int i = 0; i < ARRAY_SIZE(def); i++)
+ def[i] = ~0;
memset(use, 0, sizeof(use));
/* If things aren't ever written (undefined values), just read from
@@ -196,7 +200,7 @@ vc4_register_allocate(struct vc4_context *vc4, struct vc4_compile *c)
uint32_t ip = 0;
list_for_each_entry(struct qinst, inst, &c->instructions, link) {
if (inst->dst.file == QFILE_TEMP) {
- def[inst->dst.index] = ip;
+ def[inst->dst.index] = MIN2(ip, def[inst->dst.index]);
use[inst->dst.index] = ip;
}
@@ -267,17 +271,33 @@ vc4_register_allocate(struct vc4_context *vc4, struct vc4_compile *c)
AB_INDEX + QPU_R_FRAG_PAYLOAD_ZW * 2);
break;
- case QOP_PACK_SCALED:
- /* The pack flags require an A-file dst register. */
- class_bits[inst->dst.index] &= CLASS_BIT_A;
- break;
-
default:
break;
}
+ if (inst->dst.pack && !qir_is_mul(inst)) {
+ /* The non-MUL pack flags require an A-file dst
+ * register.
+ */
+ class_bits[inst->dst.index] &= CLASS_BIT_A;
+ }
+
if (qir_src_needs_a_file(inst)) {
- class_bits[inst->src[0].index] &= CLASS_BIT_A;
+ switch (inst->op) {
+ case QOP_UNPACK_8A_F:
+ case QOP_UNPACK_8B_F:
+ case QOP_UNPACK_8C_F:
+ case QOP_UNPACK_8D_F:
+ /* Special case: these can be done as R4
+ * unpacks, as well.
+ */
+ class_bits[inst->src[0].index] &= (CLASS_BIT_A |
+ CLASS_BIT_R4);
+ break;
+ default:
+ class_bits[inst->src[0].index] &= CLASS_BIT_A;
+ break;
+ }
}
ip++;
}
@@ -287,9 +307,11 @@ vc4_register_allocate(struct vc4_context *vc4, struct vc4_compile *c)
switch (class_bits[i]) {
case CLASS_BIT_A | CLASS_BIT_B_OR_ACC | CLASS_BIT_R4:
- case CLASS_BIT_A | CLASS_BIT_B_OR_ACC:
ra_set_node_class(g, node, vc4->reg_class_any);
break;
+ case CLASS_BIT_A | CLASS_BIT_B_OR_ACC:
+ ra_set_node_class(g, node, vc4->reg_class_a_or_b_or_acc);
+ break;
case CLASS_BIT_A | CLASS_BIT_R4:
ra_set_node_class(g, node, vc4->reg_class_r4_or_a);
break;
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 1e493f47ccf..266ebbafe36 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -663,6 +663,7 @@ struct pipe_blit_info
boolean render_condition_enable; /**< whether the blit should honor the
current render condition */
+ boolean alpha_blend; /* dst.rgb = src.rgb * src.a + dst.rgb * (1 - src.a) */
};
diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp
index 63c3f8ee49b..7c23a27150b 100644
--- a/src/gallium/state_trackers/clover/llvm/invocation.cpp
+++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp
@@ -346,6 +346,15 @@ namespace {
// Kernel metadata
+ struct kernel_arg_md {
+ llvm::StringRef type_name;
+ llvm::StringRef access_qual;
+ kernel_arg_md(llvm::StringRef type_name_, llvm::StringRef access_qual_):
+ type_name(type_name_), access_qual(access_qual_) {}
+ };
+
+#if HAVE_LLVM >= 0x0306
+
const llvm::MDNode *
get_kernel_metadata(const llvm::Function *kernel_func) {
auto mod = kernel_func->getParent();
@@ -356,12 +365,8 @@ namespace {
const llvm::MDNode *kernel_node = nullptr;
for (unsigned i = 0; i < kernels_node->getNumOperands(); ++i) {
-#if HAVE_LLVM >= 0x0306
auto func = llvm::mdconst::dyn_extract<llvm::Function>(
-#else
- auto func = llvm::dyn_cast<llvm::Function>(
-#endif
- kernels_node->getOperand(i)->getOperand(0));
+ kernels_node->getOperand(i)->getOperand(0));
if (func == kernel_func) {
kernel_node = kernels_node->getOperand(i);
break;
@@ -387,13 +392,6 @@ namespace {
return node;
}
- struct kernel_arg_md {
- llvm::StringRef type_name;
- llvm::StringRef access_qual;
- kernel_arg_md(llvm::StringRef type_name_, llvm::StringRef access_qual_):
- type_name(type_name_), access_qual(access_qual_) {}
- };
-
std::vector<kernel_arg_md>
get_kernel_arg_md(const llvm::Function *kernel_func) {
auto num_args = kernel_func->getArgumentList().size();
@@ -415,6 +413,17 @@ namespace {
return res;
}
+#else
+
+ std::vector<kernel_arg_md>
+ get_kernel_arg_md(const llvm::Function *kernel_func) {
+ return std::vector<kernel_arg_md>(
+ kernel_func->getArgumentList().size(),
+ kernel_arg_md("", ""));
+ }
+
+#endif // HAVE_LLVM >= 0x0306
+
std::vector<module::argument>
get_kernel_args(const llvm::Module *mod, const std::string &kernel_name,
const clang::LangAS::Map &address_spaces) {
diff --git a/src/gallium/state_trackers/nine/adapter9.c b/src/gallium/state_trackers/nine/adapter9.c
index c5ffcb15a18..69e0fa25961 100644
--- a/src/gallium/state_trackers/nine/adapter9.c
+++ b/src/gallium/state_trackers/nine/adapter9.c
@@ -545,7 +545,7 @@ NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
/*D3DDEVCAPS_RTPATCHES |*/
/*D3DDEVCAPS_RTPATCHHANDLEZERO |*/
/*D3DDEVCAPS_SEPARATETEXTUREMEMORIES |*/
- /*D3DDEVCAPS_TEXTURENONLOCALVIDMEM |*/
+ D3DDEVCAPS_TEXTURENONLOCALVIDMEM |
/* D3DDEVCAPS_TEXTURESYSTEMMEMORY |*/
D3DDEVCAPS_TEXTUREVIDEOMEMORY |
D3DDEVCAPS_TLVERTEXSYSTEMMEMORY |
@@ -561,32 +561,32 @@ NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
D3DPMISCCAPS_TSSARGTEMP |
D3DPMISCCAPS_BLENDOP |
D3DPIPECAP(INDEP_BLEND_ENABLE, D3DPMISCCAPS_INDEPENDENTWRITEMASKS) |
- /*D3DPMISCCAPS_PERSTAGECONSTANT |*/
+ /*D3DPMISCCAPS_PERSTAGECONSTANT |*/ /* TODO */
/*D3DPMISCCAPS_POSTBLENDSRGBCONVERT |*/ /* TODO */
D3DPMISCCAPS_FOGANDSPECULARALPHA |
D3DPIPECAP(BLEND_EQUATION_SEPARATE, D3DPMISCCAPS_SEPARATEALPHABLEND) |
D3DPIPECAP(MIXED_COLORBUFFER_FORMATS, D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS) |
D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING |
- /*D3DPMISCCAPS_FOGVERTEXCLAMPED*/0;
+ D3DPMISCCAPS_FOGVERTEXCLAMPED;
if (!screen->get_param(screen, PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION))
pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_CLIPTLVERTS;
pCaps->RasterCaps =
D3DPIPECAP(ANISOTROPIC_FILTER, D3DPRASTERCAPS_ANISOTROPY) |
- /*D3DPRASTERCAPS_COLORPERSPECTIVE |*/
+ D3DPRASTERCAPS_COLORPERSPECTIVE |
D3DPRASTERCAPS_DITHER |
D3DPRASTERCAPS_DEPTHBIAS |
- /*D3DPRASTERCAPS_FOGRANGE |*/
- /*D3DPRASTERCAPS_FOGTABLE |*/
- /*D3DPRASTERCAPS_FOGVERTEX |*/
+ D3DPRASTERCAPS_FOGRANGE |
+ D3DPRASTERCAPS_FOGTABLE |
+ D3DPRASTERCAPS_FOGVERTEX |
D3DPRASTERCAPS_MIPMAPLODBIAS |
D3DPRASTERCAPS_MULTISAMPLE_TOGGLE |
D3DPRASTERCAPS_SCISSORTEST |
D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
/*D3DPRASTERCAPS_WBUFFER |*/
- /*D3DPRASTERCAPS_WFOG |*/
+ D3DPRASTERCAPS_WFOG |
/*D3DPRASTERCAPS_ZBUFFERLESSHSR |*/
- /*D3DPRASTERCAPS_ZFOG |*/
+ D3DPRASTERCAPS_ZFOG |
D3DPRASTERCAPS_ZTEST;
pCaps->ZCmpCaps = D3DPCMPCAPS_NEVER |
@@ -697,15 +697,12 @@ NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
pCaps->MaxAnisotropy =
(DWORD)screen->get_paramf(screen, PIPE_CAPF_MAX_TEXTURE_ANISOTROPY);
- pCaps->MaxVertexW = 1.0f; /* XXX */
- pCaps->GuardBandLeft = screen->get_paramf(screen,
- PIPE_CAPF_GUARD_BAND_LEFT);
- pCaps->GuardBandTop = screen->get_paramf(screen,
- PIPE_CAPF_GUARD_BAND_TOP);
- pCaps->GuardBandRight = screen->get_paramf(screen,
- PIPE_CAPF_GUARD_BAND_RIGHT);
- pCaps->GuardBandBottom = screen->get_paramf(screen,
- PIPE_CAPF_GUARD_BAND_BOTTOM);
+ /* Values for GeForce 9600 GT */
+ pCaps->MaxVertexW = 1e10f;
+ pCaps->GuardBandLeft = -1e9f;
+ pCaps->GuardBandTop = -1e9f;
+ pCaps->GuardBandRight = 1e9f;
+ pCaps->GuardBandBottom = 1e9f;
pCaps->ExtentsAdjust = 0.0f;
pCaps->StencilCaps =
@@ -724,8 +721,6 @@ NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
/*D3DFVFCAPS_DONOTSTRIPELEMENTS |*/
D3DFVFCAPS_PSIZE;
- /* XXX: Some of these are probably not in SM2.0 so cap them when I figure
- * them out. For now leave them all enabled. */
pCaps->TextureOpCaps = D3DTEXOPCAPS_DISABLE |
D3DTEXOPCAPS_SELECTARG1 |
D3DTEXOPCAPS_SELECTARG2 |
@@ -796,7 +791,8 @@ NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
pCaps->MaxVertexShaderConst = NINE_MAX_CONST_F;
pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
- pCaps->PixelShader1xMaxValue = 8.0f; /* XXX: wine */
+ /* Value for GeForce 9600 GT */
+ pCaps->PixelShader1xMaxValue = 65504.f;
pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET |
D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET |
diff --git a/src/gallium/state_trackers/nine/basetexture9.c b/src/gallium/state_trackers/nine/basetexture9.c
index 17a8f448ee6..d13138b7d5c 100644
--- a/src/gallium/state_trackers/nine/basetexture9.c
+++ b/src/gallium/state_trackers/nine/basetexture9.c
@@ -57,7 +57,8 @@ NineBaseTexture9_ctor( struct NineBaseTexture9 *This,
user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) ||
Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
user_assert(!(Usage & D3DUSAGE_DYNAMIC) ||
- Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);
+ !(Pool == D3DPOOL_MANAGED ||
+ Pool == D3DPOOL_SCRATCH), D3DERR_INVALIDCALL);
hr = NineResource9_ctor(&This->base, pParams, initResource, alloc, Type, Pool, Usage);
if (FAILED(hr))
@@ -85,6 +86,9 @@ NineBaseTexture9_ctor( struct NineBaseTexture9 *This,
util_format_has_depth(util_format_description(This->base.info.format));
list_inithead(&This->list);
+ list_inithead(&This->list2);
+ if (Pool == D3DPOOL_MANAGED)
+ list_add(&This->list2, &This->base.base.device->managed_textures);
return D3D_OK;
}
@@ -98,7 +102,9 @@ NineBaseTexture9_dtor( struct NineBaseTexture9 *This )
pipe_sampler_view_reference(&This->view[1], NULL);
if (This->list.prev != NULL && This->list.next != NULL)
- list_del(&This->list),
+ list_del(&This->list);
+ if (This->list2.prev != NULL && This->list2.next != NULL)
+ list_del(&This->list2);
NineResource9_dtor(&This->base);
}
@@ -153,6 +159,8 @@ NineBaseTexture9_SetAutoGenFilterType( struct NineBaseTexture9 *This,
user_assert(FilterType != D3DTEXF_NONE, D3DERR_INVALIDCALL);
This->mipfilter = FilterType;
+ This->dirty_mip = TRUE;
+ NineBaseTexture9_GenerateMipSubLevels(This);
return D3D_OK;
}
@@ -310,14 +318,12 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This )
tex->dirty_box.width, tex->dirty_box.height, tex->dirty_box.depth);
if (tex->dirty_box.width) {
- for (l = 0; l <= last_level; ++l) {
+ for (l = min_level_dirty; l <= last_level; ++l) {
u_box_minify_2d(&box, &tex->dirty_box, l);
- NineVolume9_AddDirtyRegion(tex->volumes[l], &tex->dirty_box);
+ NineVolume9_UploadSelf(tex->volumes[l], &box);
}
memset(&tex->dirty_box, 0, sizeof(tex->dirty_box));
}
- for (l = min_level_dirty; l <= last_level; ++l)
- NineVolume9_UploadSelf(tex->volumes[l]);
} else {
assert(!"invalid texture type");
}
@@ -361,8 +367,7 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This )
box.width = u_minify(This->base.info.width0, l);
box.height = u_minify(This->base.info.height0, l);
box.depth = u_minify(This->base.info.depth0, l);
- NineVolume9_AddDirtyRegion(tex->volumes[l], &box);
- NineVolume9_UploadSelf(tex->volumes[l]);
+ NineVolume9_UploadSelf(tex->volumes[l], &box);
}
} else {
assert(!"invalid texture type");
@@ -381,8 +386,7 @@ NineBaseTexture9_UploadSelf( struct NineBaseTexture9 *This )
void WINAPI
NineBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This )
{
- struct pipe_resource *resource = This->base.resource;
-
+ struct pipe_resource *resource;
unsigned base_level = 0;
unsigned last_level = This->base.info.last_level - This->managed.lod;
unsigned first_layer = 0;
@@ -405,6 +409,8 @@ NineBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This )
last_layer = util_max_layer(This->view[0]->texture, base_level);
+ resource = This->base.resource;
+
util_gen_mipmap(This->pipe, resource,
resource->format, base_level, last_level,
first_layer, last_layer, filter);
@@ -530,6 +536,11 @@ NineBaseTexture9_UpdateSamplerView( struct NineBaseTexture9 *This,
swizzle[2] = PIPE_SWIZZLE_RED;
swizzle[3] = PIPE_SWIZZLE_RED;
}
+ } else if (resource->format == PIPE_FORMAT_RGTC2_UNORM) {
+ swizzle[0] = PIPE_SWIZZLE_GREEN;
+ swizzle[1] = PIPE_SWIZZLE_RED;
+ swizzle[2] = PIPE_SWIZZLE_ONE;
+ swizzle[3] = PIPE_SWIZZLE_ONE;
} else if (resource->format != PIPE_FORMAT_A8_UNORM &&
resource->format != PIPE_FORMAT_RGTC1_UNORM) {
/* exceptions:
@@ -578,6 +589,21 @@ NineBaseTexture9_PreLoad( struct NineBaseTexture9 *This )
NineBaseTexture9_UploadSelf(This);
}
+void
+NineBaseTexture9_UnLoad( struct NineBaseTexture9 *This )
+{
+ if (This->base.pool != D3DPOOL_MANAGED ||
+ This->managed.lod_resident == -1)
+ return;
+
+ pipe_resource_reference(&This->base.resource, NULL);
+ This->managed.lod_resident = -1;
+ This->managed.dirty = TRUE;
+
+ /* If the texture is bound, we have to re-upload it */
+ BASETEX_REGISTER_UPDATE(This);
+}
+
#ifdef DEBUG
void
NineBaseTexture9_Dump( struct NineBaseTexture9 *This )
diff --git a/src/gallium/state_trackers/nine/basetexture9.h b/src/gallium/state_trackers/nine/basetexture9.h
index 9d6fb0c002a..b19a62195fc 100644
--- a/src/gallium/state_trackers/nine/basetexture9.h
+++ b/src/gallium/state_trackers/nine/basetexture9.h
@@ -30,7 +30,8 @@
struct NineBaseTexture9
{
struct NineResource9 base;
- struct list_head list;
+ struct list_head list; /* for update_textures */
+ struct list_head list2; /* for managed_textures */
/* g3d */
struct pipe_context *pipe;
@@ -94,6 +95,9 @@ NineBaseTexture9_GenerateMipSubLevels( struct NineBaseTexture9 *This );
void WINAPI
NineBaseTexture9_PreLoad( struct NineBaseTexture9 *This );
+void
+NineBaseTexture9_UnLoad( struct NineBaseTexture9 *This );
+
/* For D3DPOOL_MANAGED only (after SetLOD change): */
HRESULT
NineBaseTexture9_CreatePipeResource( struct NineBaseTexture9 *This,
diff --git a/src/gallium/state_trackers/nine/cubetexture9.c b/src/gallium/state_trackers/nine/cubetexture9.c
index edea1f28a8d..abba2637946 100644
--- a/src/gallium/state_trackers/nine/cubetexture9.c
+++ b/src/gallium/state_trackers/nine/cubetexture9.c
@@ -43,7 +43,7 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
struct pipe_screen *screen = pParams->device->screen;
enum pipe_format pf;
unsigned i, l, f, offset, face_size = 0;
- unsigned *level_offsets;
+ unsigned *level_offsets = NULL;
D3DSURFACE_DESC sfdesc;
void *p;
HRESULT hr;
@@ -70,6 +70,13 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
if (Format == D3DFMT_ATI1 || Format == D3DFMT_ATI2)
return D3DERR_INVALIDCALL;
+ if (compressed_format(Format)) {
+ const unsigned w = util_format_get_blockwidth(pf);
+ const unsigned h = util_format_get_blockheight(pf);
+
+ user_assert(!(EdgeLength % w) && !(EdgeLength % h), D3DERR_INVALIDCALL);
+ }
+
info->screen = pParams->device->screen;
info->target = PIPE_TEXTURE_CUBE;
info->format = pf;
@@ -106,7 +113,7 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
face_size = nine_format_get_size_and_offsets(pf, level_offsets,
EdgeLength, EdgeLength,
info->last_level);
- This->managed_buffer = MALLOC(6 * face_size);
+ This->managed_buffer = align_malloc(6 * face_size, 32);
if (!This->managed_buffer)
return E_OUTOFMEMORY;
}
@@ -150,8 +157,12 @@ NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
}
}
- for (i = 0; i < 6; ++i) /* width = 0 means empty, depth stays 1 */
+ for (i = 0; i < 6; ++i) {
+ /* Textures start initially dirty */
+ This->dirty_rect[i].width = EdgeLength;
+ This->dirty_rect[i].height = EdgeLength;
This->dirty_rect[i].depth = 1;
+ }
return D3D_OK;
}
@@ -259,13 +270,17 @@ NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This,
user_assert(FaceType < 6, D3DERR_INVALIDCALL);
if (This->base.base.pool != D3DPOOL_MANAGED) {
- if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP)
+ if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP) {
This->base.dirty_mip = TRUE;
+ BASETEX_REGISTER_UPDATE(&This->base);
+ }
return D3D_OK;
}
- This->base.managed.dirty = TRUE;
- BASETEX_REGISTER_UPDATE(&This->base);
+ if (This->base.base.pool == D3DPOOL_MANAGED) {
+ This->base.managed.dirty = TRUE;
+ BASETEX_REGISTER_UPDATE(&This->base);
+ }
if (!pDirtyRect) {
u_box_origin_2d(This->base.base.info.width0,
diff --git a/src/gallium/state_trackers/nine/device9.c b/src/gallium/state_trackers/nine/device9.c
index 55948cbb67f..99197a4361b 100644
--- a/src/gallium/state_trackers/nine/device9.c
+++ b/src/gallium/state_trackers/nine/device9.c
@@ -119,48 +119,6 @@ NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset )
This, (IDirect3DSurface9 *)This->swapchains[0]->zsbuf);
}
-void
-NineDevice9_RestoreNonCSOState( struct NineDevice9 *This, unsigned mask )
-{
- struct pipe_context *pipe = This->pipe;
-
- DBG("This=%p mask=%u\n", This, mask);
-
- if (mask & 0x1) {
- struct pipe_constant_buffer cb;
- cb.buffer_offset = 0;
-
- if (This->prefer_user_constbuf) {
- cb.buffer = NULL;
- cb.user_buffer = This->state.vs_const_f;
- } else {
- cb.buffer = This->constbuf_vs;
- cb.user_buffer = NULL;
- }
- cb.buffer_size = This->vs_const_size;
- pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &cb);
-
- if (This->prefer_user_constbuf) {
- cb.user_buffer = This->state.ps_const_f;
- } else {
- cb.buffer = This->constbuf_ps;
- }
- cb.buffer_size = This->ps_const_size;
- pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &cb);
- }
-
- if (mask & 0x2) {
- struct pipe_poly_stipple stipple;
- memset(&stipple, ~0, sizeof(stipple));
- pipe->set_polygon_stipple(pipe, &stipple);
- }
-
- This->state.changed.group = NINE_STATE_ALL;
- This->state.changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1;
- This->state.changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
- This->state.changed.texture = NINE_PS_SAMPLERS_MASK | NINE_VS_SAMPLERS_MASK;
-}
-
#define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n)
HRESULT
NineDevice9_ctor( struct NineDevice9 *This,
@@ -186,6 +144,7 @@ NineDevice9_ctor( struct NineDevice9 *This,
if (FAILED(hr)) { return hr; }
list_inithead(&This->update_textures);
+ list_inithead(&This->managed_textures);
This->screen = pScreen;
This->caps = *pCaps;
@@ -341,16 +300,19 @@ NineDevice9_ctor( struct NineDevice9 *This,
This->state.vs_const_f = CALLOC(This->vs_const_size, 1);
This->state.ps_const_f = CALLOC(This->ps_const_size, 1);
This->state.vs_lconstf_temp = CALLOC(This->vs_const_size,1);
+ This->state.ps_lconstf_temp = CALLOC(This->ps_const_size,1);
if (!This->state.vs_const_f || !This->state.ps_const_f ||
- !This->state.vs_lconstf_temp)
+ !This->state.vs_lconstf_temp || !This->state.ps_lconstf_temp)
return E_OUTOFMEMORY;
if (strstr(pScreen->get_name(pScreen), "AMD") ||
strstr(pScreen->get_name(pScreen), "ATI")) {
- This->prefer_user_constbuf = TRUE;
This->driver_bugs.buggy_barycentrics = TRUE;
}
+ /* Disable NV path for now, needs some fixes */
+ This->prefer_user_constbuf = TRUE;
+
tmpl.target = PIPE_BUFFER;
tmpl.format = PIPE_FORMAT_R8_UNORM;
tmpl.height0 = 1;
@@ -376,6 +338,8 @@ NineDevice9_ctor( struct NineDevice9 *This,
{
struct pipe_resource tmplt;
struct pipe_sampler_view templ;
+ struct pipe_sampler_state samp;
+ memset(&samp, 0, sizeof(samp));
tmplt.target = PIPE_TEXTURE_2D;
tmplt.width0 = 1;
@@ -404,22 +368,39 @@ NineDevice9_ctor( struct NineDevice9 *This,
templ.swizzle_a = PIPE_SWIZZLE_ONE;
templ.target = This->dummy_texture->target;
- This->dummy_sampler = This->pipe->create_sampler_view(This->pipe, This->dummy_texture, &templ);
- if (!This->dummy_sampler)
+ This->dummy_sampler_view = This->pipe->create_sampler_view(This->pipe, This->dummy_texture, &templ);
+ if (!This->dummy_sampler_view)
return D3DERR_DRIVERINTERNALERROR;
+
+ samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ samp.max_lod = 15.0f;
+ samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ samp.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ samp.compare_mode = PIPE_TEX_COMPARE_NONE;
+ samp.compare_func = PIPE_FUNC_LEQUAL;
+ samp.normalized_coords = 1;
+ samp.seamless_cube_map = 1;
+ This->dummy_sampler_state = samp;
}
/* Allocate upload helper for drivers that suck (from st pov ;). */
- {
- unsigned bind = 0;
- This->driver_caps.user_vbufs = GET_PCAP(USER_VERTEX_BUFFERS);
- This->driver_caps.user_ibufs = GET_PCAP(USER_INDEX_BUFFERS);
+ This->driver_caps.user_vbufs = GET_PCAP(USER_VERTEX_BUFFERS);
+ This->driver_caps.user_ibufs = GET_PCAP(USER_INDEX_BUFFERS);
+ This->driver_caps.user_cbufs = GET_PCAP(USER_CONSTANT_BUFFERS);
+
+ if (!This->driver_caps.user_vbufs)
+ This->vertex_uploader = u_upload_create(This->pipe, 65536, 4, PIPE_BIND_VERTEX_BUFFER);
+ if (!This->driver_caps.user_ibufs)
+ This->index_uploader = u_upload_create(This->pipe, 128 * 1024, 4, PIPE_BIND_INDEX_BUFFER);
+ if (!This->driver_caps.user_cbufs) {
+ unsigned alignment = GET_PCAP(CONSTANT_BUFFER_OFFSET_ALIGNMENT);
- if (!This->driver_caps.user_vbufs) bind |= PIPE_BIND_VERTEX_BUFFER;
- if (!This->driver_caps.user_ibufs) bind |= PIPE_BIND_INDEX_BUFFER;
- if (bind)
- This->upload = u_upload_create(This->pipe, 1 << 20, 4, bind);
+ This->constbuf_uploader = u_upload_create(This->pipe, This->vs_const_size,
+ alignment, PIPE_BIND_CONSTANT_BUFFER);
}
This->driver_caps.window_space_position_support = GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION);
@@ -429,10 +410,15 @@ NineDevice9_ctor( struct NineDevice9 *This,
nine_ff_init(This); /* initialize fixed function code */
NineDevice9_SetDefaultState(This, FALSE);
- NineDevice9_RestoreNonCSOState(This, ~0);
+
+ {
+ struct pipe_poly_stipple stipple;
+ memset(&stipple, ~0, sizeof(stipple));
+ This->pipe->set_polygon_stipple(This->pipe, &stipple);
+ }
This->update = &This->state;
- nine_update_state(This, ~0);
+ nine_update_state(This);
ID3DPresentGroup_Release(This->present);
@@ -452,12 +438,16 @@ NineDevice9_dtor( struct NineDevice9 *This )
nine_ff_fini(This);
nine_state_clear(&This->state, TRUE);
- if (This->upload)
- u_upload_destroy(This->upload);
+ if (This->vertex_uploader)
+ u_upload_destroy(This->vertex_uploader);
+ if (This->index_uploader)
+ u_upload_destroy(This->index_uploader);
+ if (This->constbuf_uploader)
+ u_upload_destroy(This->constbuf_uploader);
nine_bind(&This->record, NULL);
- pipe_sampler_view_reference(&This->dummy_sampler, NULL);
+ pipe_sampler_view_reference(&This->dummy_sampler_view, NULL);
pipe_resource_reference(&This->dummy_texture, NULL);
pipe_resource_reference(&This->constbuf_vs, NULL);
pipe_resource_reference(&This->constbuf_ps, NULL);
@@ -465,6 +455,7 @@ NineDevice9_dtor( struct NineDevice9 *This )
FREE(This->state.vs_const_f);
FREE(This->state.ps_const_f);
FREE(This->state.vs_lconstf_temp);
+ FREE(This->state.ps_lconstf_temp);
if (This->swapchains) {
for (i = 0; i < This->nswapchains; ++i)
@@ -547,10 +538,14 @@ NineDevice9_GetAvailableTextureMem( struct NineDevice9 *This )
HRESULT WINAPI
NineDevice9_EvictManagedResources( struct NineDevice9 *This )
{
- /* We don't really need to do anything here, but might want to free up
- * the GPU virtual address space by killing pipe_resources.
- */
- STUB(D3D_OK);
+ struct NineBaseTexture9 *tex;
+
+ DBG("This=%p\n", This);
+ LIST_FOR_EACH_ENTRY(tex, &This->managed_textures, list2) {
+ NineBaseTexture9_UnLoad(tex);
+ }
+
+ return D3D_OK;
}
HRESULT WINAPI
@@ -599,11 +594,11 @@ NineDevice9_SetCursorProperties( struct NineDevice9 *This,
UINT YHotSpot,
IDirect3DSurface9 *pCursorBitmap )
{
- /* TODO: hardware cursor */
struct NineSurface9 *surf = NineSurface9(pCursorBitmap);
struct pipe_context *pipe = This->pipe;
struct pipe_box box;
struct pipe_transfer *transfer;
+ BOOL hw_cursor;
void *ptr;
DBG_FLAG(DBG_SWAPCHAIN, "This=%p XHotSpot=%u YHotSpot=%u "
@@ -611,8 +606,15 @@ NineDevice9_SetCursorProperties( struct NineDevice9 *This,
user_assert(pCursorBitmap, D3DERR_INVALIDCALL);
- This->cursor.w = MIN2(surf->desc.Width, This->cursor.image->width0);
- This->cursor.h = MIN2(surf->desc.Height, This->cursor.image->height0);
+ if (This->swapchains[0]->params.Windowed) {
+ This->cursor.w = MIN2(surf->desc.Width, 32);
+ This->cursor.h = MIN2(surf->desc.Height, 32);
+ hw_cursor = 1; /* always use hw cursor for windowed mode */
+ } else {
+ This->cursor.w = MIN2(surf->desc.Width, This->cursor.image->width0);
+ This->cursor.h = MIN2(surf->desc.Height, This->cursor.image->height0);
+ hw_cursor = This->cursor.w == 32 && This->cursor.h == 32;
+ }
u_box_origin_2d(This->cursor.w, This->cursor.h, &box);
@@ -643,16 +645,21 @@ NineDevice9_SetCursorProperties( struct NineDevice9 *This,
lock.pBits, lock.Pitch,
This->cursor.w, This->cursor.h);
- if (!This->cursor.software &&
- This->cursor.w == 32 && This->cursor.h == 32)
- ID3DPresent_SetCursor(This->swapchains[0]->present,
- lock.pBits, &This->cursor.hotspot,
- This->cursor.visible);
+ if (hw_cursor)
+ hw_cursor = ID3DPresent_SetCursor(This->swapchains[0]->present,
+ lock.pBits,
+ &This->cursor.hotspot,
+ This->cursor.visible) == D3D_OK;
NineSurface9_UnlockRect(surf);
}
pipe->transfer_unmap(pipe, transfer);
+ /* hide cursor if we emulate it */
+ if (!hw_cursor)
+ ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, FALSE);
+ This->cursor.software = !hw_cursor;
+
return D3D_OK;
}
@@ -670,7 +677,7 @@ NineDevice9_SetCursorPosition( struct NineDevice9 *This,
This->cursor.pos.y = Y;
if (!This->cursor.software)
- ID3DPresent_SetCursorPos(swap->present, &This->cursor.pos);
+ This->cursor.software = ID3DPresent_SetCursorPos(swap->present, &This->cursor.pos) != D3D_OK;
}
BOOL WINAPI
@@ -683,7 +690,7 @@ NineDevice9_ShowCursor( struct NineDevice9 *This,
This->cursor.visible = bShow && (This->cursor.hotspot.x != -1);
if (!This->cursor.software)
- ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow);
+ This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK;
return old;
}
@@ -752,8 +759,8 @@ NineDevice9_Reset( struct NineDevice9 *This,
for (i = 0; i < This->nswapchains; ++i) {
D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i];
hr = NineSwapChain9_Resize(This->swapchains[i], params, NULL);
- if (FAILED(hr))
- return (hr == D3DERR_OUTOFVIDEOMEMORY) ? hr : D3DERR_DEVICELOST;
+ if (hr != D3D_OK)
+ return hr;
}
nine_pipe_context_clear(This);
@@ -1108,6 +1115,13 @@ create_zs_or_rt_surface(struct NineDevice9 *This,
default: break;
}
+ if (compressed_format(Format)) {
+ const unsigned w = util_format_get_blockwidth(templ.format);
+ const unsigned h = util_format_get_blockheight(templ.format);
+
+ user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL);
+ }
+
if (Pool == D3DPOOL_DEFAULT && Format != D3DFMT_NULL) {
/* resource_create doesn't return an error code, so check format here */
user_assert(templ.format != PIPE_FORMAT_NONE, D3DERR_INVALIDCALL);
@@ -1173,6 +1187,8 @@ NineDevice9_UpdateSurface( struct NineDevice9 *This,
{
struct NineSurface9 *dst = NineSurface9(pDestinationSurface);
struct NineSurface9 *src = NineSurface9(pSourceSurface);
+ int copy_width, copy_height;
+ RECT destRect;
DBG("This=%p pSourceSurface=%p pDestinationSurface=%p "
"pSourceRect=%p pDestPoint=%p\n", This,
@@ -1184,13 +1200,75 @@ NineDevice9_UpdateSurface( struct NineDevice9 *This,
if (pDestPoint)
DBG("pDestPoint = (%u,%u)\n", pDestPoint->x, pDestPoint->y);
+ user_assert(dst && src, D3DERR_INVALIDCALL);
+
user_assert(dst->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
user_assert(src->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
user_assert(dst->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);
user_assert(src->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);
- return NineSurface9_CopySurface(dst, src, pDestPoint, pSourceRect);
+ user_assert(!src->lock_count, D3DERR_INVALIDCALL);
+ user_assert(!dst->lock_count, D3DERR_INVALIDCALL);
+
+ user_assert(dst->desc.Format == src->desc.Format, D3DERR_INVALIDCALL);
+ user_assert(!depth_stencil_format(dst->desc.Format), D3DERR_INVALIDCALL);
+
+ if (pSourceRect) {
+ copy_width = pSourceRect->right - pSourceRect->left;
+ copy_height = pSourceRect->bottom - pSourceRect->top;
+
+ user_assert(pSourceRect->left >= 0 &&
+ copy_width > 0 &&
+ pSourceRect->right <= src->desc.Width &&
+ pSourceRect->top >= 0 &&
+ copy_height > 0 &&
+ pSourceRect->bottom <= src->desc.Height,
+ D3DERR_INVALIDCALL);
+ } else {
+ copy_width = src->desc.Width;
+ copy_height = src->desc.Height;
+ }
+
+ destRect.right = copy_width;
+ destRect.bottom = copy_height;
+
+ if (pDestPoint) {
+ user_assert(pDestPoint->x >= 0 && pDestPoint->y >= 0,
+ D3DERR_INVALIDCALL);
+ destRect.right += pDestPoint->x;
+ destRect.bottom += pDestPoint->y;
+ }
+
+ user_assert(destRect.right <= dst->desc.Width &&
+ destRect.bottom <= dst->desc.Height,
+ D3DERR_INVALIDCALL);
+
+ if (compressed_format(dst->desc.Format)) {
+ const unsigned w = util_format_get_blockwidth(dst->base.info.format);
+ const unsigned h = util_format_get_blockheight(dst->base.info.format);
+
+ if (pDestPoint) {
+ user_assert(!(pDestPoint->x % w) && !(pDestPoint->y % h),
+ D3DERR_INVALIDCALL);
+ }
+
+ if (pSourceRect) {
+ user_assert(!(pSourceRect->left % w) && !(pSourceRect->top % h),
+ D3DERR_INVALIDCALL);
+ }
+ if (!(copy_width == src->desc.Width &&
+ copy_width == dst->desc.Width &&
+ copy_height == src->desc.Height &&
+ copy_height == dst->desc.Height)) {
+ user_assert(!(copy_width % w) && !(copy_height % h),
+ D3DERR_INVALIDCALL);
+ }
+ }
+
+ NineSurface9_CopyMemToDefault(dst, src, pDestPoint, pSourceRect);
+
+ return D3D_OK;
}
HRESULT WINAPI
@@ -1202,6 +1280,7 @@ NineDevice9_UpdateTexture( struct NineDevice9 *This,
struct NineBaseTexture9 *srcb = NineBaseTexture9(pSourceTexture);
unsigned l, m;
unsigned last_level = dstb->base.info.last_level;
+ RECT rect;
DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This,
pSourceTexture, pDestinationTexture);
@@ -1227,10 +1306,6 @@ NineDevice9_UpdateTexture( struct NineDevice9 *This,
user_assert(dstb->base.type == srcb->base.type, D3DERR_INVALIDCALL);
- /* TODO: We can restrict the update to the dirty portions of the source.
- * Yes, this seems silly, but it's what MSDN says ...
- */
-
/* Find src level that matches dst level 0: */
user_assert(srcb->base.info.width0 >= dstb->base.info.width0 &&
srcb->base.info.height0 >= dstb->base.info.height0 &&
@@ -1254,9 +1329,25 @@ NineDevice9_UpdateTexture( struct NineDevice9 *This,
struct NineTexture9 *dst = NineTexture9(dstb);
struct NineTexture9 *src = NineTexture9(srcb);
- for (l = 0; l <= last_level; ++l, ++m)
- NineSurface9_CopySurface(dst->surfaces[l],
- src->surfaces[m], NULL, NULL);
+ if (src->dirty_rect.width == 0)
+ return D3D_OK;
+
+ pipe_box_to_rect(&rect, &src->dirty_rect);
+ for (l = 0; l < m; ++l)
+ rect_minify_inclusive(&rect);
+
+ for (l = 0; l <= last_level; ++l, ++m) {
+ fit_rect_format_inclusive(dst->base.base.info.format,
+ &rect,
+ dst->surfaces[l]->desc.Width,
+ dst->surfaces[l]->desc.Height);
+ NineSurface9_CopyMemToDefault(dst->surfaces[l],
+ src->surfaces[m],
+ (POINT *)&rect,
+ &rect);
+ rect_minify_inclusive(&rect);
+ }
+ u_box_origin_2d(0, 0, &src->dirty_rect);
} else
if (dstb->base.type == D3DRTYPE_CUBETEXTURE) {
struct NineCubeTexture9 *dst = NineCubeTexture9(dstb);
@@ -1265,10 +1356,25 @@ NineDevice9_UpdateTexture( struct NineDevice9 *This,
/* GPUs usually have them stored as arrays of mip-mapped 2D textures. */
for (z = 0; z < 6; ++z) {
+ if (src->dirty_rect[z].width == 0)
+ continue;
+
+ pipe_box_to_rect(&rect, &src->dirty_rect[z]);
+ for (l = 0; l < m; ++l)
+ rect_minify_inclusive(&rect);
+
for (l = 0; l <= last_level; ++l, ++m) {
- NineSurface9_CopySurface(dst->surfaces[l * 6 + z],
- src->surfaces[m * 6 + z], NULL, NULL);
+ fit_rect_format_inclusive(dst->base.base.info.format,
+ &rect,
+ dst->surfaces[l * 6 + z]->desc.Width,
+ dst->surfaces[l * 6 + z]->desc.Height);
+ NineSurface9_CopyMemToDefault(dst->surfaces[l * 6 + z],
+ src->surfaces[m * 6 + z],
+ (POINT *)&rect,
+ &rect);
+ rect_minify_inclusive(&rect);
}
+ u_box_origin_2d(0, 0, &src->dirty_rect[z]);
m -= l;
}
} else
@@ -1276,9 +1382,12 @@ NineDevice9_UpdateTexture( struct NineDevice9 *This,
struct NineVolumeTexture9 *dst = NineVolumeTexture9(dstb);
struct NineVolumeTexture9 *src = NineVolumeTexture9(srcb);
+ if (src->dirty_box.width == 0)
+ return D3D_OK;
for (l = 0; l <= last_level; ++l, ++m)
- NineVolume9_CopyVolume(dst->volumes[l],
- src->volumes[m], 0, 0, 0, NULL);
+ NineVolume9_CopyMemToDefault(dst->volumes[l],
+ src->volumes[m], 0, 0, 0, NULL);
+ u_box_3d(0, 0, 0, 0, 0, 0, &src->dirty_box);
} else{
assert(!"invalid texture type");
}
@@ -1308,7 +1417,12 @@ NineDevice9_GetRenderTargetData( struct NineDevice9 *This,
user_assert(dst->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);
user_assert(src->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);
- return NineSurface9_CopySurface(dst, src, NULL, NULL);
+ user_assert(src->desc.Width == dst->desc.Width, D3DERR_INVALIDCALL);
+ user_assert(src->desc.Height == dst->desc.Height, D3DERR_INVALIDCALL);
+
+ NineSurface9_CopyDefaultToMem(dst, src);
+
+ return D3D_OK;
}
HRESULT WINAPI
@@ -1448,6 +1562,7 @@ NineDevice9_StretchRect( struct NineDevice9 *This,
blit.filter = Filter == D3DTEXF_LINEAR ?
PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST;
blit.scissor_enable = FALSE;
+ blit.alpha_blend = FALSE;
/* If both of a src and dst dimension are negative, flip them. */
if (blit.dst.box.width < 0 && blit.src.box.width < 0) {
@@ -1464,8 +1579,12 @@ NineDevice9_StretchRect( struct NineDevice9 *This,
user_assert(!scaled || dst != src, D3DERR_INVALIDCALL);
user_assert(!scaled ||
- !NineSurface9_IsOffscreenPlain(dst) ||
+ !NineSurface9_IsOffscreenPlain(dst), D3DERR_INVALIDCALL);
+ user_assert(!NineSurface9_IsOffscreenPlain(dst) ||
NineSurface9_IsOffscreenPlain(src), D3DERR_INVALIDCALL);
+ user_assert(NineSurface9_IsOffscreenPlain(dst) ||
+ dst->desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL),
+ D3DERR_INVALIDCALL);
user_assert(!scaled ||
(!util_format_is_compressed(dst->base.info.format) &&
!util_format_is_compressed(src->base.info.format)),
@@ -1561,11 +1680,8 @@ NineDevice9_ColorFill( struct NineDevice9 *This,
}
d3dcolor_to_pipe_color_union(&rgba, color);
- fallback =
- !This->screen->is_format_supported(This->screen, surf->base.info.format,
- surf->base.info.target,
- surf->base.info.nr_samples,
- PIPE_BIND_RENDER_TARGET);
+ fallback = !(surf->base.info.bind & PIPE_BIND_RENDER_TARGET);
+
if (!fallback) {
psurf = NineSurface9_GetSurface(surf, 0);
if (!psurf)
@@ -1774,7 +1890,7 @@ NineDevice9_Clear( struct NineDevice9 *This,
return D3D_OK;
d3dcolor_to_pipe_color_union(&rgba, Color);
- nine_update_state(This, NINE_STATE_FB);
+ nine_update_state_framebuffer(This);
rect.x1 = This->state.viewport.X;
rect.y1 = This->state.viewport.Y;
@@ -2012,8 +2128,10 @@ NineDevice9_SetLight( struct NineDevice9 *This,
return E_OUTOFMEMORY;
state->ff.num_lights = N;
- for (; n < Index; ++n)
+ for (; n < Index; ++n) {
+ memset(&state->ff.light[n], 0, sizeof(D3DLIGHT9));
state->ff.light[n].Type = (D3DLIGHTTYPE)NINED3DLIGHT_INVALID;
+ }
}
state->ff.light[Index] = *pLight;
@@ -2508,6 +2626,7 @@ NineDevice9_SetTextureStageState( struct NineDevice9 *This,
DWORD Value )
{
struct nine_state *state = This->update;
+ int bumpmap_index = -1;
DBG("Stage=%u Type=%u Value=%08x\n", Stage, Type, Value);
nine_dump_D3DTSS_value(DBG_FF, Type, Value);
@@ -2516,6 +2635,36 @@ NineDevice9_SetTextureStageState( struct NineDevice9 *This,
user_assert(Type < Elements(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
state->ff.tex_stage[Stage][Type] = Value;
+ switch (Type) {
+ case D3DTSS_BUMPENVMAT00:
+ bumpmap_index = 4 * Stage;
+ break;
+ case D3DTSS_BUMPENVMAT10:
+ bumpmap_index = 4 * Stage + 1;
+ break;
+ case D3DTSS_BUMPENVMAT01:
+ bumpmap_index = 4 * Stage + 2;
+ break;
+ case D3DTSS_BUMPENVMAT11:
+ bumpmap_index = 4 * Stage + 3;
+ break;
+ case D3DTSS_BUMPENVLSCALE:
+ bumpmap_index = 4 * 8 + 2 * Stage;
+ break;
+ case D3DTSS_BUMPENVLOFFSET:
+ bumpmap_index = 4 * 8 + 2 * Stage + 1;
+ break;
+ case D3DTSS_TEXTURETRANSFORMFLAGS:
+ state->changed.group |= NINE_STATE_PS1X_SHADER;
+ break;
+ default:
+ break;
+ }
+
+ if (bumpmap_index >= 0) {
+ state->bumpmap_vars[bumpmap_index] = Value;
+ state->changed.group |= NINE_STATE_PS_CONST;
+ }
state->changed.group |= NINE_STATE_FF_PSSTAGES;
state->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32);
@@ -2560,12 +2709,11 @@ NineDevice9_SetSamplerState( struct NineDevice9 *This,
if (Sampler >= D3DDMAPSAMPLER)
Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
- state->samp[Sampler][Type] = Value;
- state->changed.group |= NINE_STATE_SAMPLER;
- state->changed.sampler[Sampler] |= 1 << Type;
-
- if (Type == D3DSAMP_SRGBTEXTURE)
- state->changed.srgb = TRUE;
+ if (state->samp[Sampler][Type] != Value || unlikely(This->is_recording)) {
+ state->samp[Sampler][Type] = Value;
+ state->changed.group |= NINE_STATE_SAMPLER;
+ state->changed.sampler[Sampler] |= 1 << Type;
+ }
return D3D_OK;
}
@@ -2724,7 +2872,7 @@ NineDevice9_DrawPrimitive( struct NineDevice9 *This,
DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n",
This, PrimitiveType, StartVertex, PrimitiveCount);
- nine_update_state(This, ~0);
+ nine_update_state(This);
init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
info.indexed = FALSE;
@@ -2757,7 +2905,7 @@ NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This,
user_assert(This->state.idxbuf, D3DERR_INVALIDCALL);
user_assert(This->state.vdecl, D3DERR_INVALIDCALL);
- nine_update_state(This, ~0);
+ nine_update_state(This);
init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
info.indexed = TRUE;
@@ -2789,7 +2937,7 @@ NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This,
user_assert(pVertexStreamZeroData && VertexStreamZeroStride,
D3DERR_INVALIDCALL);
- nine_update_state(This, ~0);
+ nine_update_state(This);
init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
info.indexed = FALSE;
@@ -2803,13 +2951,16 @@ NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This,
vtxbuf.buffer = NULL;
vtxbuf.user_buffer = pVertexStreamZeroData;
- if (!This->driver_caps.user_vbufs)
- u_upload_data(This->upload,
+ if (!This->driver_caps.user_vbufs) {
+ u_upload_data(This->vertex_uploader,
0,
(info.max_index + 1) * VertexStreamZeroStride, /* XXX */
vtxbuf.user_buffer,
&vtxbuf.buffer_offset,
&vtxbuf.buffer);
+ u_upload_unmap(This->vertex_uploader);
+ vtxbuf.user_buffer = NULL;
+ }
This->pipe->set_vertex_buffers(This->pipe, 0, 1, &vtxbuf);
@@ -2851,7 +3002,7 @@ NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
user_assert(IndexDataFormat == D3DFMT_INDEX16 ||
IndexDataFormat == D3DFMT_INDEX32, D3DERR_INVALIDCALL);
- nine_update_state(This, ~0);
+ nine_update_state(This);
init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
info.indexed = TRUE;
@@ -2872,23 +3023,28 @@ NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
if (!This->driver_caps.user_vbufs) {
const unsigned base = info.min_index * VertexStreamZeroStride;
- u_upload_data(This->upload,
+ u_upload_data(This->vertex_uploader,
base,
(info.max_index -
info.min_index + 1) * VertexStreamZeroStride, /* XXX */
(const uint8_t *)vbuf.user_buffer + base,
&vbuf.buffer_offset,
&vbuf.buffer);
+ u_upload_unmap(This->vertex_uploader);
/* Won't be used: */
vbuf.buffer_offset -= base;
+ vbuf.user_buffer = NULL;
}
- if (!This->driver_caps.user_ibufs)
- u_upload_data(This->upload,
+ if (!This->driver_caps.user_ibufs) {
+ u_upload_data(This->index_uploader,
0,
info.count * ibuf.index_size,
ibuf.user_buffer,
&ibuf.offset,
&ibuf.buffer);
+ u_upload_unmap(This->index_uploader);
+ ibuf.user_buffer = NULL;
+ }
This->pipe->set_vertex_buffers(This->pipe, 0, 1, &vbuf);
This->pipe->set_index_buffer(This->pipe, &ibuf);
@@ -2935,7 +3091,7 @@ NineDevice9_ProcessVertices( struct NineDevice9 *This,
if (!screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS))
STUB(D3DERR_INVALIDCALL);
- nine_update_state(This, ~0);
+ nine_update_state(This);
/* TODO: Create shader with stream output. */
STUB(D3DERR_INVALIDCALL);
@@ -3105,6 +3261,13 @@ NineDevice9_SetVertexShader( struct NineDevice9 *This,
DBG("This=%p pShader=%p\n", This, pShader);
+ if (!This->is_recording && state->vs == (struct NineVertexShader9*)pShader)
+ return D3D_OK;
+
+ /* ff -> non-ff: commit back non-ff constants */
+ if (!state->vs && pShader)
+ state->commit |= NINE_STATE_COMMIT_CONST_VS;
+
nine_bind(&state->vs, pShader);
state->changed.group |= NINE_STATE_VS;
@@ -3139,6 +3302,12 @@ NineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This,
return D3D_OK;
user_assert(pConstantData, D3DERR_INVALIDCALL);
+ if (!This->is_recording) {
+ if (!memcmp(&state->vs_const_f[StartRegister * 4], pConstantData,
+ Vector4fCount * 4 * sizeof(state->vs_const_f[0])))
+ return D3D_OK;
+ }
+
memcpy(&state->vs_const_f[StartRegister * 4],
pConstantData,
Vector4fCount * 4 * sizeof(state->vs_const_f[0]));
@@ -3188,6 +3357,11 @@ NineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This,
user_assert(pConstantData, D3DERR_INVALIDCALL);
if (This->driver_caps.vs_integer) {
+ if (!This->is_recording) {
+ if (!memcmp(&state->vs_const_i[StartRegister][0], pConstantData,
+ Vector4iCount * sizeof(state->vs_const_i[0])))
+ return D3D_OK;
+ }
memcpy(&state->vs_const_i[StartRegister][0],
pConstantData,
Vector4iCount * sizeof(state->vs_const_i[0]));
@@ -3252,6 +3426,16 @@ NineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This,
user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
user_assert(pConstantData, D3DERR_INVALIDCALL);
+ if (!This->is_recording) {
+ bool noChange = true;
+ for (i = 0; i < BoolCount; i++) {
+ if (!!state->vs_const_b[StartRegister + i] != !!pConstantData[i])
+ noChange = false;
+ }
+ if (noChange)
+ return D3D_OK;
+ }
+
for (i = 0; i < BoolCount; i++)
state->vs_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0;
@@ -3433,6 +3617,13 @@ NineDevice9_SetPixelShader( struct NineDevice9 *This,
DBG("This=%p pShader=%p\n", This, pShader);
+ if (!This->is_recording && state->ps == (struct NinePixelShader9*)pShader)
+ return D3D_OK;
+
+ /* ff -> non-ff: commit back non-ff constants */
+ if (!state->ps && pShader)
+ state->commit |= NINE_STATE_COMMIT_CONST_PS;
+
nine_bind(&state->ps, pShader);
state->changed.group |= NINE_STATE_PS;
@@ -3473,6 +3664,12 @@ NineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This,
return D3D_OK;
user_assert(pConstantData, D3DERR_INVALIDCALL);
+ if (!This->is_recording) {
+ if (!memcmp(&state->ps_const_f[StartRegister * 4], pConstantData,
+ Vector4fCount * 4 * sizeof(state->ps_const_f[0])))
+ return D3D_OK;
+ }
+
memcpy(&state->ps_const_f[StartRegister * 4],
pConstantData,
Vector4fCount * 4 * sizeof(state->ps_const_f[0]));
@@ -3522,6 +3719,11 @@ NineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This,
user_assert(pConstantData, D3DERR_INVALIDCALL);
if (This->driver_caps.ps_integer) {
+ if (!This->is_recording) {
+ if (!memcmp(&state->ps_const_i[StartRegister][0], pConstantData,
+ Vector4iCount * sizeof(state->ps_const_i[0])))
+ return D3D_OK;
+ }
memcpy(&state->ps_const_i[StartRegister][0],
pConstantData,
Vector4iCount * sizeof(state->ps_const_i[0]));
@@ -3585,6 +3787,16 @@ NineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This,
user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
user_assert(pConstantData, D3DERR_INVALIDCALL);
+ if (!This->is_recording) {
+ bool noChange = true;
+ for (i = 0; i < BoolCount; i++) {
+ if (!!state->ps_const_b[StartRegister + i] != !!pConstantData[i])
+ noChange = false;
+ }
+ if (noChange)
+ return D3D_OK;
+ }
+
for (i = 0; i < BoolCount; i++)
state->ps_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0;
diff --git a/src/gallium/state_trackers/nine/device9.h b/src/gallium/state_trackers/nine/device9.h
index 74607451c5f..98d9c4df06a 100644
--- a/src/gallium/state_trackers/nine/device9.h
+++ b/src/gallium/state_trackers/nine/device9.h
@@ -69,6 +69,7 @@ struct NineDevice9
struct nine_state state; /* device state */
struct list_head update_textures;
+ struct list_head managed_textures;
boolean is_recording;
boolean in_scene;
@@ -83,7 +84,8 @@ struct NineDevice9
uint16_t max_ps_const_f;
struct pipe_resource *dummy_texture;
- struct pipe_sampler_view *dummy_sampler;
+ struct pipe_sampler_view *dummy_sampler_view;
+ struct pipe_sampler_state dummy_sampler_state;
struct gen_mipmap_state *gen_mipmap;
@@ -113,6 +115,7 @@ struct NineDevice9
struct {
boolean user_vbufs;
boolean user_ibufs;
+ boolean user_cbufs;
boolean window_space_position_support;
boolean vs_integer;
boolean ps_integer;
@@ -122,7 +125,9 @@ struct NineDevice9
boolean buggy_barycentrics;
} driver_bugs;
- struct u_upload_mgr *upload;
+ struct u_upload_mgr *vertex_uploader;
+ struct u_upload_mgr *index_uploader;
+ struct u_upload_mgr *constbuf_uploader;
struct nine_range_pool range_pool;
@@ -180,10 +185,6 @@ NineDevice9_GetCSO( struct NineDevice9 *This );
const D3DCAPS9 *
NineDevice9_GetCaps( struct NineDevice9 *This );
-/* Mask: 0x1 = constant buffers, 0x2 = stipple */
-void
-NineDevice9_RestoreNonCSOState( struct NineDevice9 *This, unsigned mask );
-
/*** Direct3D public ***/
HRESULT WINAPI
diff --git a/src/gallium/state_trackers/nine/nine_ff.c b/src/gallium/state_trackers/nine/nine_ff.c
index 8a53f0d9038..fe8933be69a 100644
--- a/src/gallium/state_trackers/nine/nine_ff.c
+++ b/src/gallium/state_trackers/nine/nine_ff.c
@@ -22,6 +22,7 @@
#include "tgsi/tgsi_dump.h"
#include "util/u_box.h"
#include "util/u_hash_table.h"
+#include "util/u_upload_mgr.h"
#define NINE_TGSI_LAZY_DEVS 1
@@ -30,13 +31,6 @@
#define NINE_FF_NUM_VS_CONST 256
#define NINE_FF_NUM_PS_CONST 24
-#define NINED3DTSS_TCI_DISABLE 0
-#define NINED3DTSS_TCI_PASSTHRU 1
-#define NINED3DTSS_TCI_CAMERASPACENORMAL 2
-#define NINED3DTSS_TCI_CAMERASPACEPOSITION 3
-#define NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR 4
-#define NINED3DTSS_TCI_SPHEREMAP 5
-
struct fvec4
{
float x, y, z, w;
@@ -63,16 +57,20 @@ struct nine_ff_vs_key
uint32_t fog_range : 1;
uint32_t color0in_one : 1;
uint32_t color1in_one : 1;
- uint32_t pad1 : 8;
- uint32_t tc_gen : 24; /* 8 * 3 bits */
- uint32_t pad2 : 8;
- uint32_t tc_idx : 24;
+ uint32_t fog : 1;
+ uint32_t pad1 : 7;
+ uint32_t tc_dim_input: 16; /* 8 * 2 bits */
+ uint32_t pad2 : 16;
+ uint32_t tc_dim_output: 24; /* 8 * 3 bits */
uint32_t pad3 : 8;
- uint32_t tc_dim : 24; /* 8 * 3 bits */
+ uint32_t tc_gen : 24; /* 8 * 3 bits */
uint32_t pad4 : 8;
+ uint32_t tc_idx : 24;
+ uint32_t pad5 : 8;
+ uint32_t passthrough;
};
- uint64_t value64[2]; /* don't forget to resize VertexShader9.ff_key */
- uint32_t value32[4];
+ uint64_t value64[3]; /* don't forget to resize VertexShader9.ff_key */
+ uint32_t value32[6];
};
};
@@ -106,15 +104,18 @@ struct nine_ff_ps_key
uint32_t alphaarg2 : 3;
uint32_t resultarg : 1; /* CURRENT:0 or TEMP:1 */
uint32_t textarget : 2; /* 1D/2D/3D/CUBE */
- uint32_t projected : 1;
+ uint32_t pad : 1;
/* that's 32 bit exactly */
} ts[8];
- uint32_t fog : 1; /* for vFog with programmable VS */
+ uint32_t projected : 16;
+ uint32_t fog : 1; /* for vFog coming from VS */
uint32_t fog_mode : 2;
- uint32_t specular : 1; /* 9 32-bit words with this */
+ uint32_t specular : 1;
+ uint32_t pad1 : 12; /* 9 32-bit words with this */
uint8_t colorarg_b4[3];
uint8_t colorarg_b5[3];
uint8_t alphaarg_b4[3]; /* 11 32-bit words plus a byte */
+ uint8_t pad2[3];
};
uint64_t value64[6]; /* don't forget to resize PixelShader9.ff_key */
uint32_t value32[12];
@@ -222,7 +223,6 @@ static void nine_ureg_tgsi_dump(struct ureg_program *ureg, boolean override)
* CONST[28].x___ RS.FogEnd
* CONST[28]._y__ 1.0f / (RS.FogEnd - RS.FogStart)
* CONST[28].__z_ RS.FogDensity
- * CONST[29] RS.FogColor
* CONST[30].x___ TWEENFACTOR
*
@@ -334,16 +334,15 @@ nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs)
{
const struct nine_ff_vs_key *key = vs->key;
struct ureg_program *ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
- struct ureg_dst oPos, oCol[2], oTex[8], oPsz, oFog;
- struct ureg_dst rCol[2]; /* oCol if no fog, TEMP otherwise */
+ struct ureg_dst oPos, oCol[2], oPsz, oFog;
struct ureg_dst rVtx, rNrm;
struct ureg_dst r[8];
struct ureg_dst AR;
- struct ureg_dst tmp, tmp_x, tmp_z;
+ struct ureg_dst tmp, tmp_x, tmp_y, tmp_z;
unsigned i, c;
unsigned label[32], l = 0;
unsigned num_r = 8;
- boolean need_rNrm = key->lighting || key->pointscale;
+ boolean need_rNrm = key->lighting || key->pointscale || key->passthrough & (1 << NINE_DECLUSAGE_NORMAL);
boolean need_rVtx = key->lighting || key->fog_mode;
const unsigned texcoord_sn = get_texcoord_sn(device->screen);
@@ -406,9 +405,9 @@ nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs)
if (key->vertexpointsize)
vs->aPsz = build_vs_add_input(vs, NINE_DECLUSAGE_PSIZE);
- if (key->vertexblend_indexed)
+ if (key->vertexblend_indexed || key->passthrough & (1 << NINE_DECLUSAGE_BLENDINDICES))
vs->aInd = build_vs_add_input(vs, NINE_DECLUSAGE_BLENDINDICES);
- if (key->vertexblend)
+ if (key->vertexblend || key->passthrough & (1 << NINE_DECLUSAGE_BLENDWEIGHT))
vs->aWgt = build_vs_add_input(vs, NINE_DECLUSAGE_BLENDWEIGHT);
if (key->vertextween) {
vs->aVtx1 = build_vs_add_input(vs, NINE_DECLUSAGE_i(POSITION,1));
@@ -420,19 +419,16 @@ nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs)
oPos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); /* HPOS */
oCol[0] = ureg_saturate(ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0));
oCol[1] = ureg_saturate(ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1));
+ if (key->fog || key->passthrough & (1 << NINE_DECLUSAGE_FOG)) {
+ oFog = ureg_DECL_output(ureg, TGSI_SEMANTIC_FOG, 0);
+ oFog = ureg_writemask(oFog, TGSI_WRITEMASK_X);
+ }
if (key->vertexpointsize || key->pointscale) {
oPsz = ureg_DECL_output_masked(ureg, TGSI_SEMANTIC_PSIZE, 0,
TGSI_WRITEMASK_X, 0, 1);
oPsz = ureg_writemask(oPsz, TGSI_WRITEMASK_X);
}
- if (key->fog_mode) {
- /* We apply fog to the vertex colors, oFog is for programmable shaders only ?
- */
- oFog = ureg_DECL_output_masked(ureg, TGSI_SEMANTIC_FOG, 0,
- TGSI_WRITEMASK_X, 0, 1);
- oFog = ureg_writemask(oFog, TGSI_WRITEMASK_X);
- }
/* Declare TEMPs:
*/
@@ -440,18 +436,11 @@ nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs)
r[i] = ureg_DECL_local_temporary(ureg);
tmp = r[0];
tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X);
+ tmp_y = ureg_writemask(tmp, TGSI_WRITEMASK_Y);
tmp_z = ureg_writemask(tmp, TGSI_WRITEMASK_Z);
if (key->lighting || key->vertexblend)
AR = ureg_DECL_address(ureg);
- if (key->fog_mode) {
- rCol[0] = r[2];
- rCol[1] = r[3];
- } else {
- rCol[0] = oCol[0];
- rCol[1] = oCol[1];
- }
-
rVtx = ureg_writemask(r[1], TGSI_WRITEMASK_XYZ);
rNrm = ureg_writemask(r[2], TGSI_WRITEMASK_XYZ);
@@ -560,8 +549,6 @@ nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs)
ureg_CLAMP(ureg, oPsz, vs->aPsz, _XXXX(cPsz1), _YYYY(cPsz1));
#endif
} else if (key->pointscale) {
- struct ureg_dst tmp_x = ureg_writemask(tmp, TGSI_WRITEMASK_X);
- struct ureg_dst tmp_y = ureg_writemask(tmp, TGSI_WRITEMASK_Y);
struct ureg_src cPsz1 = ureg_DECL_constant(ureg, 26);
struct ureg_src cPsz2 = ureg_DECL_constant(ureg, 27);
@@ -582,72 +569,85 @@ nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs)
#endif
}
- /* Texture coordinate generation:
- * XXX: D3DTTFF_PROJECTED, transform matrix
- */
for (i = 0; i < 8; ++i) {
- struct ureg_dst dst[5];
- struct ureg_src src;
- unsigned c;
+ struct ureg_dst oTex, input_coord, transformed, t;
+ unsigned c, writemask;
const unsigned tci = (key->tc_gen >> (i * 3)) & 0x7;
const unsigned idx = (key->tc_idx >> (i * 3)) & 0x7;
- const unsigned dim = (key->tc_dim >> (i * 3)) & 0x7;
+ unsigned dim_input = 1 + ((key->tc_dim_input >> (i * 2)) & 0x3);
+ const unsigned dim_output = (key->tc_dim_output >> (i * 3)) & 0x7;
+ /* No texture output of index s */
if (tci == NINED3DTSS_TCI_DISABLE)
continue;
- oTex[i] = ureg_DECL_output(ureg, texcoord_sn, i);
-
- if (tci == NINED3DTSS_TCI_PASSTHRU)
- vs->aTex[idx] = build_vs_add_input(vs, NINE_DECLUSAGE_i(TEXCOORD,idx));
-
- if (!dim) {
- dst[c = 4] = oTex[i];
- } else {
- dst[4] = r[5];
- src = ureg_src(dst[4]);
- for (c = 0; c < (dim - 1); ++c)
- dst[c] = ureg_writemask(tmp, (1 << dim) - 1);
- dst[c] = ureg_writemask(oTex[i], (1 << dim) - 1);
- }
+ oTex = ureg_DECL_output(ureg, texcoord_sn, i);
+ input_coord = r[5];
+ transformed = r[6];
+ /* Get the coordinate */
switch (tci) {
case NINED3DTSS_TCI_PASSTHRU:
- ureg_MOV(ureg, dst[4], vs->aTex[idx]);
+ /* NINED3DTSS_TCI_PASSTHRU => Use texcoord coming from index idx *
+ * Else the idx is used only to determine wrapping mode. */
+ vs->aTex[idx] = build_vs_add_input(vs, NINE_DECLUSAGE_i(TEXCOORD,idx));
+ ureg_MOV(ureg, input_coord, vs->aTex[idx]);
break;
case NINED3DTSS_TCI_CAMERASPACENORMAL:
- assert(dim <= 3);
- ureg_MOV(ureg, ureg_writemask(dst[4], TGSI_WRITEMASK_XYZ), ureg_src(rNrm));
- ureg_MOV(ureg, ureg_writemask(dst[4], TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
+ ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XYZ), ureg_src(rNrm));
+ ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
+ dim_input = 4;
break;
case NINED3DTSS_TCI_CAMERASPACEPOSITION:
- ureg_MOV(ureg, ureg_writemask(dst[4], TGSI_WRITEMASK_XYZ), ureg_src(rVtx));
- ureg_MOV(ureg, ureg_writemask(dst[4], TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
+ ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XYZ), ureg_src(rVtx));
+ ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
+ dim_input = 4;
break;
case NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
tmp.WriteMask = TGSI_WRITEMASK_XYZ;
ureg_DP3(ureg, tmp_x, ureg_src(rVtx), ureg_src(rNrm));
ureg_MUL(ureg, tmp, ureg_src(rNrm), _X(tmp));
ureg_ADD(ureg, tmp, ureg_src(tmp), ureg_src(tmp));
- ureg_SUB(ureg, ureg_writemask(dst[4], TGSI_WRITEMASK_XYZ), ureg_src(rVtx), ureg_src(tmp));
- ureg_MOV(ureg, ureg_writemask(dst[4], TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
+ ureg_SUB(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_XYZ), ureg_src(rVtx), ureg_src(tmp));
+ ureg_MOV(ureg, ureg_writemask(input_coord, TGSI_WRITEMASK_W), ureg_imm1f(ureg, 1.0f));
+ dim_input = 4;
tmp.WriteMask = TGSI_WRITEMASK_XYZW;
break;
case NINED3DTSS_TCI_SPHEREMAP:
assert(!"TODO");
break;
default:
+ assert(0);
break;
}
- if (!dim)
- continue;
- dst[c].WriteMask = ~dst[c].WriteMask;
- if (dst[c].WriteMask)
- ureg_MOV(ureg, dst[c], src); /* store untransformed components */
- dst[c].WriteMask = ~dst[c].WriteMask;
- if (dim > 0) ureg_MUL(ureg, dst[0], _XXXX(src), _CONST(128 + i * 4));
- if (dim > 1) ureg_MAD(ureg, dst[1], _YYYY(src), _CONST(129 + i * 4), ureg_src(tmp));
- if (dim > 2) ureg_MAD(ureg, dst[2], _ZZZZ(src), _CONST(130 + i * 4), ureg_src(tmp));
- if (dim > 3) ureg_MAD(ureg, dst[3], _WWWW(src), _CONST(131 + i * 4), ureg_src(tmp));
+
+ /* Apply the transformation */
+ /* dim_output == 0 => do not transform the components.
+ * XYZRHW also disables transformation */
+ if (!dim_output || key->position_t) {
+ transformed = input_coord;
+ writemask = TGSI_WRITEMASK_XYZW;
+ } else {
+ for (c = 0; c < dim_output; c++) {
+ t = ureg_writemask(transformed, 1 << c);
+ switch (dim_input) {
+ /* dim_input = 1 2 3: -> we add trailing 1 to input*/
+ case 1: ureg_MAD(ureg, t, _X(input_coord), _XXXX(_CONST(128 + i * 4 + c)), _YYYY(_CONST(128 + i * 4 + c)));
+ break;
+ case 2: ureg_DP2(ureg, t, ureg_src(input_coord), _CONST(128 + i * 4 + c));
+ ureg_ADD(ureg, t, ureg_src(transformed), _ZZZZ(_CONST(128 + i * 4 + c)));
+ break;
+ case 3: ureg_DP3(ureg, t, ureg_src(input_coord), _CONST(128 + i * 4 + c));
+ ureg_ADD(ureg, t, ureg_src(transformed), _WWWW(_CONST(128 + i * 4 + c)));
+ break;
+ case 4: ureg_DP4(ureg, t, ureg_src(input_coord), _CONST(128 + i * 4 + c)); break;
+ default:
+ assert(0);
+ }
+ }
+ writemask = (1 << dim_output) - 1;
+ }
+
+ ureg_MOV(ureg, ureg_writemask(oTex, writemask), ureg_src(transformed));
}
/* === Lighting:
@@ -692,8 +692,6 @@ nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs)
* specular += light.specular * atten * powFact;
*/
if (key->lighting) {
- struct ureg_dst tmp_y = ureg_writemask(tmp, TGSI_WRITEMASK_Y);
-
struct ureg_dst rAtt = ureg_writemask(r[1], TGSI_WRITEMASK_W);
struct ureg_dst rHit = ureg_writemask(r[3], TGSI_WRITEMASK_XYZ);
struct ureg_dst rMid = ureg_writemask(r[4], TGSI_WRITEMASK_XYZ);
@@ -851,22 +849,22 @@ nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs)
ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), vs->mtlA, ureg_src(tmp), vs->mtlE);
ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W ), vs->mtlA, vs->mtlE);
}
- ureg_MAD(ureg, rCol[0], ureg_src(rD), vs->mtlD, ureg_src(tmp));
- ureg_MUL(ureg, rCol[1], ureg_src(rS), vs->mtlS);
+ ureg_MAD(ureg, oCol[0], ureg_src(rD), vs->mtlD, ureg_src(tmp));
+ ureg_MUL(ureg, oCol[1], ureg_src(rS), vs->mtlS);
} else
/* COLOR */
if (key->darkness) {
if (key->mtl_emissive == 0 && key->mtl_ambient == 0) {
- ureg_MAD(ureg, rCol[0], vs->mtlD, ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 1.0f), _CONST(19));
+ ureg_MAD(ureg, oCol[0], vs->mtlD, ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 1.0f), _CONST(19));
} else {
- ureg_MAD(ureg, ureg_writemask(rCol[0], TGSI_WRITEMASK_XYZ), vs->mtlA, _CONST(25), vs->mtlE);
+ ureg_MAD(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_XYZ), vs->mtlA, _CONST(25), vs->mtlE);
ureg_ADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), vs->mtlA, vs->mtlE);
- ureg_ADD(ureg, ureg_writemask(rCol[0], TGSI_WRITEMASK_W), vs->mtlD, _W(tmp));
+ ureg_ADD(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_W), vs->mtlD, _W(tmp));
}
- ureg_MUL(ureg, rCol[1], ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 1.0f), vs->mtlS);
+ ureg_MUL(ureg, oCol[1], ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 1.0f), vs->mtlS);
} else {
- ureg_MOV(ureg, rCol[0], vs->aCol[0]);
- ureg_MOV(ureg, rCol[1], vs->aCol[1]);
+ ureg_MOV(ureg, oCol[0], vs->aCol[0]);
+ ureg_MOV(ureg, oCol[1], vs->aCol[1]);
}
/* === Process fog.
@@ -874,10 +872,6 @@ nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs)
* exp(x) = ex2(log2(e) * x)
*/
if (key->fog_mode) {
- /* Fog doesn't affect alpha, TODO: combine with light code output */
- ureg_MOV(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_W), _W(rCol[0]));
- ureg_MOV(ureg, ureg_writemask(oCol[1], TGSI_WRITEMASK_W), _W(rCol[1]));
-
if (key->position_t) {
ureg_MOV(ureg, ureg_saturate(tmp_x), ureg_scalar(vs->aCol[1], TGSI_SWIZZLE_W));
} else
@@ -905,10 +899,58 @@ nine_ff_build_vs(struct NineDevice9 *device, struct vs_build_ctx *vs)
ureg_MUL(ureg, ureg_saturate(tmp_x), _X(tmp), _YYYY(_CONST(28)));
}
ureg_MOV(ureg, oFog, _X(tmp));
- ureg_LRP(ureg, ureg_writemask(oCol[0], TGSI_WRITEMASK_XYZ), _X(tmp), ureg_src(rCol[0]), _CONST(29));
- ureg_LRP(ureg, ureg_writemask(oCol[1], TGSI_WRITEMASK_XYZ), _X(tmp), ureg_src(rCol[1]), _CONST(29));
+ } else if (key->fog && !(key->passthrough & (1 << NINE_DECLUSAGE_FOG))) {
+ ureg_MOV(ureg, oFog, ureg_scalar(vs->aCol[1], TGSI_SWIZZLE_W));
}
+ if (key->passthrough & (1 << NINE_DECLUSAGE_BLENDWEIGHT)) {
+ struct ureg_src input;
+ struct ureg_dst output;
+ input = vs->aWgt;
+ output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 18);
+ ureg_MOV(ureg, output, input);
+ }
+ if (key->passthrough & (1 << NINE_DECLUSAGE_BLENDINDICES)) {
+ struct ureg_src input;
+ struct ureg_dst output;
+ input = vs->aInd;
+ output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 19);
+ ureg_MOV(ureg, output, input);
+ }
+ if (key->passthrough & (1 << NINE_DECLUSAGE_NORMAL)) {
+ struct ureg_src input;
+ struct ureg_dst output;
+ input = vs->aNrm;
+ output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 20);
+ ureg_MOV(ureg, output, input);
+ }
+ if (key->passthrough & (1 << NINE_DECLUSAGE_TANGENT)) {
+ struct ureg_src input;
+ struct ureg_dst output;
+ input = build_vs_add_input(vs, NINE_DECLUSAGE_TANGENT);
+ output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 21);
+ ureg_MOV(ureg, output, input);
+ }
+ if (key->passthrough & (1 << NINE_DECLUSAGE_BINORMAL)) {
+ struct ureg_src input;
+ struct ureg_dst output;
+ input = build_vs_add_input(vs, NINE_DECLUSAGE_BINORMAL);
+ output = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 22);
+ ureg_MOV(ureg, output, input);
+ }
+ if (key->passthrough & (1 << NINE_DECLUSAGE_FOG)) {
+ struct ureg_src input;
+ struct ureg_dst output;
+ input = build_vs_add_input(vs, NINE_DECLUSAGE_FOG);
+ input = ureg_scalar(input, TGSI_SWIZZLE_X);
+ output = oFog;
+ ureg_MOV(ureg, output, input);
+ }
+ if (key->passthrough & (1 << NINE_DECLUSAGE_DEPTH)) {
+ (void) 0; /* TODO: replace z of position output ? */
+ }
+
+
if (key->position_t && device->driver_caps.window_space_position_support)
ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE);
@@ -1270,10 +1312,18 @@ nine_ff_build_ps(struct NineDevice9 *device, struct nine_ff_ps_key *key)
if (key->ts[s].colorop == D3DTOP_BUMPENVMAP ||
key->ts[s].colorop == D3DTOP_BUMPENVMAPLUMINANCE) {
}
- if (key->ts[s].projected)
- ureg_TXP(ureg, ps.rTex, target, ps.vT[s], ps.s[s]);
- else
+ if (key->projected & (3 << (s *2))) {
+ unsigned dim = 1 + ((key->projected >> (2 * s)) & 3);
+ if (dim == 4)
+ ureg_TXP(ureg, ps.rTex, target, ps.vT[s], ps.s[s]);
+ else {
+ ureg_RCP(ureg, ureg_writemask(ps.rTmp, TGSI_WRITEMASK_X), ureg_scalar(ps.vT[s], dim-1));
+ ureg_MUL(ureg, ps.rTmp, _XXXX(ps.rTmpSrc), ps.vT[s]);
+ ureg_TEX(ureg, ps.rTex, target, ps.rTmpSrc, ps.s[s]);
+ }
+ } else {
ureg_TEX(ureg, ps.rTex, target, ps.vT[s], ps.s[s]);
+ }
}
if (s == 0 &&
@@ -1316,6 +1366,10 @@ nine_ff_build_ps(struct NineDevice9 *device, struct nine_ff_ps_key *key)
colorarg[2] != alphaarg[2])
dst.WriteMask = TGSI_WRITEMASK_XYZ;
+ /* Special DOTPRODUCT behaviour (see wine tests) */
+ if (key->ts[s].colorop == D3DTOP_DOTPRODUCT3)
+ dst.WriteMask = TGSI_WRITEMASK_XYZW;
+
if (used_c & 0x1) arg[0] = ps_get_ts_arg(&ps, colorarg[0]);
if (used_c & 0x2) arg[1] = ps_get_ts_arg(&ps, colorarg[1]);
if (used_c & 0x4) arg[2] = ps_get_ts_arg(&ps, colorarg[2]);
@@ -1406,12 +1460,18 @@ nine_ff_get_vs(struct NineDevice9 *device)
else if (usage % NINE_DECLUSAGE_COUNT == NINE_DECLUSAGE_TEXCOORD) {
s = usage / NINE_DECLUSAGE_COUNT;
if (s < 8)
- input_texture_coord[s] = 1;
+ input_texture_coord[s] = nine_decltype_get_dim(state->vdecl->decls[i].Type);
else
DBG("FF given texture coordinate >= 8. Ignoring\n");
- }
+ } else if (usage < NINE_DECLUSAGE_NONE)
+ key.passthrough |= 1 << usage;
}
}
+ /* ff vs + ps 3.0: some elements are passed to the ps (wine test).
+ * We do restrict to indices 0 */
+ key.passthrough &= ~((1 << NINE_DECLUSAGE_POSITION) | (1 << NINE_DECLUSAGE_PSIZE) |
+ (1 << NINE_DECLUSAGE_TEXCOORD) | (1 << NINE_DECLUSAGE_POSITIONT) |
+ (1 << NINE_DECLUSAGE_TESSFACTOR) | (1 << NINE_DECLUSAGE_SAMPLE));
if (!key.vertexpointsize)
key.pointscale = !!state->rs[D3DRS_POINTSCALEENABLE];
@@ -1427,6 +1487,7 @@ nine_ff_get_vs(struct NineDevice9 *device)
key.mtl_specular = state->rs[D3DRS_SPECULARMATERIALSOURCE];
key.mtl_emissive = state->rs[D3DRS_EMISSIVEMATERIALSOURCE];
}
+ key.fog = !!state->rs[D3DRS_FOGENABLE];
key.fog_mode = state->rs[D3DRS_FOGENABLE] ? state->rs[D3DRS_FOGVERTEXMODE] : 0;
if (key.fog_mode)
key.fog_range = !key.position_t && state->rs[D3DRS_RANGEFOGENABLE];
@@ -1448,7 +1509,7 @@ nine_ff_get_vs(struct NineDevice9 *device)
for (s = 0; s < 8; ++s) {
unsigned gen = (state->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] >> 16) + 1;
- unsigned dim = MIN2(state->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & 0x7, 4);
+ unsigned dim;
if (key.position_t && gen > NINED3DTSS_TCI_PASSTHRU)
gen = NINED3DTSS_TCI_PASSTHRU;
@@ -1458,7 +1519,14 @@ nine_ff_get_vs(struct NineDevice9 *device)
key.tc_gen |= gen << (s * 3);
key.tc_idx |= (state->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] & 7) << (s * 3);
- key.tc_dim |= dim << (s * 3);
+ key.tc_dim_input |= ((input_texture_coord[s]-1) & 0x3) << (s * 2);
+
+ dim = state->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & 0x7;
+ if (dim > 4)
+ dim = input_texture_coord[s];
+ if (dim == 1) /* NV behaviour */
+ dim = 0;
+ key.tc_dim_output |= dim << (s * 3);
}
vs = util_hash_table_get(device->ff.ht_vs, &key);
@@ -1473,6 +1541,7 @@ nine_ff_get_vs(struct NineDevice9 *device)
memcpy(&vs->ff_key, &key, sizeof(vs->ff_key));
err = util_hash_table_set(device->ff.ht_vs, &vs->ff_key, vs);
+ (void)err;
assert(err == PIPE_OK);
device->ff.num_vs++;
NineUnknown_ConvertRefToBind(NineUnknown(vs));
@@ -1543,8 +1612,6 @@ nine_ff_get_ps(struct NineDevice9 *device)
}
key.ts[s].resultarg = state->ff.tex_stage[s][D3DTSS_RESULTARG] == D3DTA_TEMP;
- key.ts[s].projected = !!(state->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
-
if (state->texture[s]) {
switch (state->texture[s]->base.type) {
case D3DRTYPE_TEXTURE: key.ts[s].textarget = 1; break;
@@ -1558,10 +1625,14 @@ nine_ff_get_ps(struct NineDevice9 *device)
key.ts[s].textarget = 1;
}
}
+
+ key.projected = nine_ff_get_projected_key(state);
+
for (; s < 8; ++s)
key.ts[s].colorop = key.ts[s].alphaop = D3DTOP_DISABLE;
if (state->rs[D3DRS_FOGENABLE])
key.fog_mode = state->rs[D3DRS_FOGTABLEMODE];
+ key.fog = !!state->rs[D3DRS_FOGENABLE];
ps = util_hash_table_get(device->ff.ht_ps, &key);
if (ps)
@@ -1573,6 +1644,7 @@ nine_ff_get_ps(struct NineDevice9 *device)
memcpy(&ps->ff_key, &key, sizeof(ps->ff_key));
err = util_hash_table_set(device->ff.ht_ps, &ps->ff_key, ps);
+ (void)err;
assert(err == PIPE_OK);
device->ff.num_ps++;
NineUnknown_ConvertRefToBind(NineUnknown(ps));
@@ -1689,7 +1761,6 @@ nine_ff_load_point_and_fog_params(struct NineDevice9 *device)
if (isinf(dst[28].y))
dst[28].y = 0.0f;
dst[28].z = asfloat(state->rs[D3DRS_FOGDENSITY]);
- d3dcolor_to_rgba(&dst[29].x, state->rs[D3DRS_FOGCOLOR]);
}
static void
@@ -1703,7 +1774,7 @@ nine_ff_load_tex_matrices(struct NineDevice9 *device)
return;
for (s = 0; s < 8; ++s) {
if (IS_D3DTS_DIRTY(state, TEXTURE0 + s))
- M[32 + s] = *nine_state_access_transform(state, D3DTS_TEXTURE0 + s, FALSE);
+ nine_d3d_matrix_transpose(&M[32 + s], nine_state_access_transform(state, D3DTS_TEXTURE0 + s, FALSE));
}
}
@@ -1762,28 +1833,22 @@ nine_ff_load_viewport_info(struct NineDevice9 *device)
void
nine_ff_update(struct NineDevice9 *device)
{
- struct pipe_context *pipe = device->pipe;
struct nine_state *state = &device->state;
+ struct pipe_constant_buffer cb;
DBG("vs=%p ps=%p\n", device->state.vs, device->state.ps);
/* NOTE: the only reference belongs to the hash table */
- if (!device->state.vs)
+ if (!device->state.vs) {
device->ff.vs = nine_ff_get_vs(device);
- if (!device->state.ps)
+ device->state.changed.group |= NINE_STATE_VS;
+ }
+ if (!device->state.ps) {
device->ff.ps = nine_ff_get_ps(device);
+ device->state.changed.group |= NINE_STATE_PS;
+ }
if (!device->state.vs) {
- if (device->state.ff.clobber.vs_const) {
- device->state.ff.clobber.vs_const = FALSE;
- device->state.changed.group |=
- NINE_STATE_FF_VSTRANSF |
- NINE_STATE_FF_MATERIAL |
- NINE_STATE_FF_LIGHTING |
- NINE_STATE_FF_OTHER;
- device->state.ff.changed.transform[0] |= 0xff000c;
- device->state.ff.changed.transform[8] |= 0xff;
- }
nine_ff_load_vs_transforms(device);
nine_ff_load_tex_matrices(device);
nine_ff_load_lights(device);
@@ -1792,57 +1857,45 @@ nine_ff_update(struct NineDevice9 *device)
memset(state->ff.changed.transform, 0, sizeof(state->ff.changed.transform));
- device->state.changed.group |= NINE_STATE_VS;
- device->state.changed.group |= NINE_STATE_VS_CONST;
-
- if (device->prefer_user_constbuf) {
- struct pipe_context *pipe = device->pipe;
- struct pipe_constant_buffer cb;
- cb.buffer_offset = 0;
- cb.buffer = NULL;
- cb.user_buffer = device->ff.vs_const;
- cb.buffer_size = NINE_FF_NUM_VS_CONST * 4 * sizeof(float);
- pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &cb);
- } else {
- struct pipe_box box;
- u_box_1d(0, NINE_FF_NUM_VS_CONST * 4 * sizeof(float), &box);
- pipe->transfer_inline_write(pipe, device->constbuf_vs, 0,
- 0, &box,
- device->ff.vs_const, 0, 0);
- nine_ranges_insert(&device->state.changed.vs_const_f, 0, NINE_FF_NUM_VS_CONST,
- &device->range_pool);
+ cb.buffer_offset = 0;
+ cb.buffer = NULL;
+ cb.user_buffer = device->ff.vs_const;
+ cb.buffer_size = NINE_FF_NUM_VS_CONST * 4 * sizeof(float);
+
+ if (!device->driver_caps.user_cbufs) {
+ u_upload_data(device->constbuf_uploader,
+ 0,
+ cb.buffer_size,
+ cb.user_buffer,
+ &cb.buffer_offset,
+ &cb.buffer);
+ u_upload_unmap(device->constbuf_uploader);
+ cb.user_buffer = NULL;
}
+ state->pipe.cb_vs_ff = cb;
+ state->commit |= NINE_STATE_COMMIT_CONST_VS;
}
if (!device->state.ps) {
- if (device->state.ff.clobber.ps_const) {
- device->state.ff.clobber.ps_const = FALSE;
- device->state.changed.group |=
- NINE_STATE_FF_PSSTAGES |
- NINE_STATE_FF_OTHER;
- }
nine_ff_load_ps_params(device);
- device->state.changed.group |= NINE_STATE_PS;
- device->state.changed.group |= NINE_STATE_PS_CONST;
-
- if (device->prefer_user_constbuf) {
- struct pipe_context *pipe = device->pipe;
- struct pipe_constant_buffer cb;
- cb.buffer_offset = 0;
- cb.buffer = NULL;
- cb.user_buffer = device->ff.ps_const;
- cb.buffer_size = NINE_FF_NUM_PS_CONST * 4 * sizeof(float);
- pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &cb);
- } else {
- struct pipe_box box;
- u_box_1d(0, NINE_FF_NUM_PS_CONST * 4 * sizeof(float), &box);
- pipe->transfer_inline_write(pipe, device->constbuf_ps, 0,
- 0, &box,
- device->ff.ps_const, 0, 0);
- nine_ranges_insert(&device->state.changed.ps_const_f, 0, NINE_FF_NUM_PS_CONST,
- &device->range_pool);
+ cb.buffer_offset = 0;
+ cb.buffer = NULL;
+ cb.user_buffer = device->ff.ps_const;
+ cb.buffer_size = NINE_FF_NUM_PS_CONST * 4 * sizeof(float);
+
+ if (!device->driver_caps.user_cbufs) {
+ u_upload_data(device->constbuf_uploader,
+ 0,
+ cb.buffer_size,
+ cb.user_buffer,
+ &cb.buffer_offset,
+ &cb.buffer);
+ u_upload_unmap(device->constbuf_uploader);
+ cb.user_buffer = NULL;
}
+ state->pipe.cb_ps_ff = cb;
+ state->commit |= NINE_STATE_COMMIT_CONST_PS;
}
device->state.changed.group &= ~NINE_STATE_FF;
diff --git a/src/gallium/state_trackers/nine/nine_ff.h b/src/gallium/state_trackers/nine/nine_ff.h
index 7cefa65b1c4..9c33c76370d 100644
--- a/src/gallium/state_trackers/nine/nine_ff.h
+++ b/src/gallium/state_trackers/nine/nine_ff.h
@@ -3,6 +3,7 @@
#define _NINE_FF_H_
#include "device9.h"
+#include "vertexdeclaration9.h"
boolean nine_ff_init(struct NineDevice9 *);
void nine_ff_fini(struct NineDevice9 *);
@@ -29,4 +30,84 @@ nine_d3d_matrix_inverse_3x3(D3DMATRIX *, const D3DMATRIX *);
void
nine_d3d_matrix_transpose(D3DMATRIX *, const D3DMATRIX *);
+#define NINED3DTSS_TCI_DISABLE 0
+#define NINED3DTSS_TCI_PASSTHRU 1
+#define NINED3DTSS_TCI_CAMERASPACENORMAL 2
+#define NINED3DTSS_TCI_CAMERASPACEPOSITION 3
+#define NINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR 4
+#define NINED3DTSS_TCI_SPHEREMAP 5
+
+static inline unsigned
+nine_decltype_get_dim(BYTE type)
+{
+ switch (type) {
+ case D3DDECLTYPE_FLOAT1: return 1;
+ case D3DDECLTYPE_FLOAT2: return 2;
+ case D3DDECLTYPE_FLOAT3: return 3;
+ case D3DDECLTYPE_FLOAT4: return 4;
+ case D3DDECLTYPE_D3DCOLOR: return 1;
+ case D3DDECLTYPE_UBYTE4: return 4;
+ case D3DDECLTYPE_SHORT2: return 2;
+ case D3DDECLTYPE_SHORT4: return 4;
+ case D3DDECLTYPE_UBYTE4N: return 4;
+ case D3DDECLTYPE_SHORT2N: return 2;
+ case D3DDECLTYPE_SHORT4N: return 4;
+ case D3DDECLTYPE_USHORT2N: return 2;
+ case D3DDECLTYPE_USHORT4N: return 4;
+ case D3DDECLTYPE_UDEC3: return 3;
+ case D3DDECLTYPE_DEC3N: return 3;
+ case D3DDECLTYPE_FLOAT16_2: return 2;
+ case D3DDECLTYPE_FLOAT16_4: return 4;
+ default:
+ assert(!"Implementation error !");
+ }
+ return 0;
+}
+
+static inline uint16_t
+nine_ff_get_projected_key(struct nine_state *state)
+{
+ unsigned s, i;
+ uint16_t projected = 0;
+ char input_texture_coord[8];
+ memset(&input_texture_coord, 0, sizeof(input_texture_coord));
+
+ if (state->vdecl) {
+ for (i = 0; i < state->vdecl->nelems; i++) {
+ uint16_t usage = state->vdecl->usage_map[i];
+ if (usage % NINE_DECLUSAGE_COUNT == NINE_DECLUSAGE_TEXCOORD) {
+ s = usage / NINE_DECLUSAGE_COUNT;
+ if (s < 8)
+ input_texture_coord[s] = nine_decltype_get_dim(state->vdecl->decls[i].Type);
+ }
+ }
+ }
+
+ for (s = 0; s < 8; ++s) {
+ unsigned gen = (state->ff.tex_stage[s][D3DTSS_TEXCOORDINDEX] >> 16) + 1;
+ unsigned dim = state->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & 0x7;
+ unsigned proj = !!(state->ff.tex_stage[s][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
+
+ if (!state->vs) {
+ if (dim > 4)
+ dim = input_texture_coord[s];
+
+ if (!dim && gen == NINED3DTSS_TCI_PASSTHRU)
+ dim = input_texture_coord[s];
+ else if (!dim)
+ dim = 4;
+
+ if (dim == 1) /* NV behaviour */
+ proj = 0;
+ if (dim > input_texture_coord[s] && gen == NINED3DTSS_TCI_PASSTHRU)
+ proj = 0;
+ } else {
+ dim = 4;
+ }
+ if (proj)
+ projected |= (dim-1) << (2 * s);
+ }
+ return projected;
+}
+
#endif /* _NINE_FF_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_pipe.c b/src/gallium/state_trackers/nine/nine_pipe.c
index 4cf37b9f59c..2be30f7e097 100644
--- a/src/gallium/state_trackers/nine/nine_pipe.c
+++ b/src/gallium/state_trackers/nine/nine_pipe.c
@@ -27,7 +27,8 @@
#include "cso_cache/cso_context.h"
void
-nine_convert_dsa_state(struct cso_context *ctx, const DWORD *rs)
+nine_convert_dsa_state(struct pipe_depth_stencil_alpha_state *dsa_state,
+ const DWORD *rs)
{
struct pipe_depth_stencil_alpha_state dsa;
@@ -65,16 +66,15 @@ nine_convert_dsa_state(struct cso_context *ctx, const DWORD *rs)
dsa.alpha.ref_value = (float)rs[D3DRS_ALPHAREF] / 255.0f;
}
- cso_set_depth_stencil_alpha(ctx, &dsa);
+ *dsa_state = dsa;
}
-/* TODO: Keep a static copy in device so we don't have to memset every time ? */
void
-nine_convert_rasterizer_state(struct cso_context *ctx, const DWORD *rs)
+nine_convert_rasterizer_state(struct pipe_rasterizer_state *rast_state, const DWORD *rs)
{
struct pipe_rasterizer_state rast;
- memset(&rast, 0, sizeof(rast)); /* memcmp safety */
+ memset(&rast, 0, sizeof(rast));
rast.flatshade = rs[D3DRS_SHADEMODE] == D3DSHADE_FLAT;
/* rast.light_twoside = 0; */
@@ -92,7 +92,7 @@ nine_convert_rasterizer_state(struct cso_context *ctx, const DWORD *rs)
/* rast.poly_stipple_enable = 0; */
/* rast.point_smooth = 0; */
rast.sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT;
- rast.point_quad_rasterization = !!rs[D3DRS_POINTSPRITEENABLE];
+ rast.point_quad_rasterization = 1;
rast.point_size_per_vertex = rs[NINED3DRS_VSPOINTSIZE];
rast.multisample = !!rs[D3DRS_MULTISAMPLEANTIALIAS];
rast.line_smooth = !!rs[D3DRS_ANTIALIASEDLINEENABLE];
@@ -110,12 +110,28 @@ nine_convert_rasterizer_state(struct cso_context *ctx, const DWORD *rs)
/* rast.line_stipple_pattern = 0; */
rast.sprite_coord_enable = rs[D3DRS_POINTSPRITEENABLE] ? 0xff : 0x00;
rast.line_width = 1.0f;
- rast.point_size = rs[NINED3DRS_VSPOINTSIZE] ? 1.0f : asfloat(rs[D3DRS_POINTSIZE]); /* XXX: D3DRS_POINTSIZE_MIN/MAX */
- rast.offset_units = asfloat(rs[D3DRS_DEPTHBIAS]) * asfloat(rs[NINED3DRS_ZBIASSCALE]);
+ if (rs[NINED3DRS_VSPOINTSIZE]) {
+ rast.point_size = 1.0f;
+ } else {
+ rast.point_size = CLAMP(asfloat(rs[D3DRS_POINTSIZE]),
+ asfloat(rs[D3DRS_POINTSIZE_MIN]),
+ asfloat(rs[D3DRS_POINTSIZE_MAX]));
+ }
+ /* offset_units has the ogl/d3d11 meaning.
+ * d3d9: offset = scale * dz + bias
+ * ogl/d3d11: offset = scale * dz + r * bias
+ * with r implementation dependant and is supposed to be
+ * the smallest value the depth buffer format can hold.
+ * In practice on current and past hw it seems to be 2^-23
+ * for all formats except float formats where it varies depending
+ * on the content.
+ * For now use 1 << 23, but in the future perhaps add a way in gallium
+ * to get r for the format or get the gallium behaviour */
+ rast.offset_units = asfloat(rs[D3DRS_DEPTHBIAS]) * (float)(1 << 23);
rast.offset_scale = asfloat(rs[D3DRS_SLOPESCALEDEPTHBIAS]);
/* rast.offset_clamp = 0.0f; */
- cso_set_rasterizer(ctx, &rast);
+ *rast_state = rast;
}
static inline void
@@ -137,7 +153,7 @@ nine_convert_blend_state_fixup(struct pipe_blend_state *blend, const DWORD *rs)
}
void
-nine_convert_blend_state(struct cso_context *ctx, const DWORD *rs)
+nine_convert_blend_state(struct pipe_blend_state *blend_state, const DWORD *rs)
{
struct pipe_blend_state blend;
@@ -181,7 +197,7 @@ nine_convert_blend_state(struct cso_context *ctx, const DWORD *rs)
/* blend.force_srgb = !!rs[D3DRS_SRGBWRITEENABLE]; */
- cso_set_blend(ctx, &blend);
+ *blend_state = blend;
}
void
@@ -239,8 +255,8 @@ nine_pipe_context_clear(struct NineDevice9 *This)
cso_set_samplers(cso, PIPE_SHADER_VERTEX, 0, NULL);
cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, 0, NULL);
- pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 0, NULL);
- pipe->set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0, 0, NULL);
+ cso_set_sampler_views(cso, PIPE_SHADER_VERTEX, 0, NULL);
+ cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, 0, NULL);
pipe->set_vertex_buffers(pipe, 0, This->caps.MaxStreams, NULL);
pipe->set_index_buffer(pipe, NULL);
diff --git a/src/gallium/state_trackers/nine/nine_pipe.h b/src/gallium/state_trackers/nine/nine_pipe.h
index 43a7737cdf9..86117866ed5 100644
--- a/src/gallium/state_trackers/nine/nine_pipe.h
+++ b/src/gallium/state_trackers/nine/nine_pipe.h
@@ -27,6 +27,7 @@
#include "pipe/p_format.h"
#include "pipe/p_screen.h"
#include "pipe/p_state.h" /* pipe_box */
+#include "util/macros.h"
#include "util/u_rect.h"
#include "util/u_format.h"
#include "nine_helpers.h"
@@ -36,9 +37,9 @@ struct cso_context;
extern const enum pipe_format nine_d3d9_to_pipe_format_map[120];
extern const D3DFORMAT nine_pipe_to_d3d9_format_map[PIPE_FORMAT_COUNT];
-void nine_convert_dsa_state(struct cso_context *, const DWORD *);
-void nine_convert_rasterizer_state(struct cso_context *, const DWORD *);
-void nine_convert_blend_state(struct cso_context *, const DWORD *);
+void nine_convert_dsa_state(struct pipe_depth_stencil_alpha_state *, const DWORD *);
+void nine_convert_rasterizer_state(struct pipe_rasterizer_state *, const DWORD *);
+void nine_convert_blend_state(struct pipe_blend_state *, const DWORD *);
void nine_convert_sampler_state(struct cso_context *, int idx, const DWORD *);
void nine_pipe_context_clear(struct NineDevice9 *);
@@ -81,6 +82,49 @@ rect_to_pipe_box(struct pipe_box *dst, const RECT *src)
dst->depth = 1;
}
+static inline void
+pipe_box_to_rect(RECT *dst, const struct pipe_box *src)
+{
+ dst->left = src->x;
+ dst->right = src->x + src->width;
+ dst->top = src->y;
+ dst->bottom = src->y + src->height;
+}
+
+static inline void
+rect_minify_inclusive(RECT *rect)
+{
+ rect->left = rect->left >> 2;
+ rect->top = rect->top >> 2;
+ rect->right = DIV_ROUND_UP(rect->right, 2);
+ rect->bottom = DIV_ROUND_UP(rect->bottom, 2);
+}
+
+/* We suppose:
+ * 0 <= rect->left < rect->right
+ * 0 <= rect->top < rect->bottom
+ */
+static inline void
+fit_rect_format_inclusive(enum pipe_format format, RECT *rect, int width, int height)
+{
+ const unsigned w = util_format_get_blockwidth(format);
+ const unsigned h = util_format_get_blockheight(format);
+
+ if (util_format_is_compressed(format)) {
+ rect->left = rect->left - rect->left % w;
+ rect->top = rect->top - rect->top % h;
+ rect->right = (rect->right % w) == 0 ?
+ rect->right :
+ rect->right - (rect->right % w) + w;
+ rect->bottom = (rect->bottom % h) == 0 ?
+ rect->bottom :
+ rect->bottom - (rect->bottom % h) + h;
+ }
+
+ rect->right = MIN2(rect->right, width);
+ rect->bottom = MIN2(rect->bottom, height);
+}
+
static inline boolean
rect_to_pipe_box_clamp(struct pipe_box *dst, const RECT *src)
{
@@ -164,6 +208,23 @@ pipe_to_d3d9_format(enum pipe_format format)
return nine_pipe_to_d3d9_format_map[format];
}
+/* ATI1 and ATI2 are not officially compressed in d3d9 */
+static inline boolean
+compressed_format( D3DFORMAT fmt )
+{
+ switch (fmt) {
+ case D3DFMT_DXT1:
+ case D3DFMT_DXT2:
+ case D3DFMT_DXT3:
+ case D3DFMT_DXT4:
+ case D3DFMT_DXT5:
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
static inline boolean
depth_stencil_format( D3DFORMAT fmt )
{
diff --git a/src/gallium/state_trackers/nine/nine_shader.c b/src/gallium/state_trackers/nine/nine_shader.c
index 754f5af6b8e..28f27870dc8 100644
--- a/src/gallium/state_trackers/nine/nine_shader.c
+++ b/src/gallium/state_trackers/nine/nine_shader.c
@@ -89,6 +89,15 @@ static inline const char *d3dsio_to_string(unsigned opcode);
#define NINE_SWIZZLE4(x,y,z,w) \
TGSI_SWIZZLE_##x, TGSI_SWIZZLE_##y, TGSI_SWIZZLE_##z, TGSI_SWIZZLE_##w
+#define NINE_CONSTANT_SRC(index) \
+ ureg_src_register(TGSI_FILE_CONSTANT, index)
+
+#define NINE_APPLY_SWIZZLE(src, s) \
+ ureg_swizzle(src, NINE_SWIZZLE4(s, s, s, s))
+
+#define NINE_CONSTANT_SRC_SWIZZLE(index, s) \
+ NINE_APPLY_SWIZZLE(NINE_CONSTANT_SRC(index), s)
+
#define NINED3DSPDM_SATURATE (D3DSPDM_SATURATE >> D3DSP_DSTMOD_SHIFT)
#define NINED3DSPDM_PARTIALP (D3DSPDM_PARTIALPRECISION >> D3DSP_DSTMOD_SHIFT)
#define NINED3DSPDM_CENTROID (D3DSPDM_MSAMPCENTROID >> D3DSP_DSTMOD_SHIFT)
@@ -444,6 +453,9 @@ struct shader_translator
BYTE minor;
} version;
unsigned processor; /* TGSI_PROCESSOR_VERTEX/FRAMGENT */
+ unsigned num_constf_allowed;
+ unsigned num_consti_allowed;
+ unsigned num_constb_allowed;
boolean native_integers;
boolean inline_subroutines;
@@ -505,7 +517,6 @@ struct shader_translator
#define IS_VS (tx->processor == TGSI_PROCESSOR_VERTEX)
#define IS_PS (tx->processor == TGSI_PROCESSOR_FRAGMENT)
-#define NINE_MAX_CONST_F_SHADER (tx->processor == TGSI_PROCESSOR_VERTEX ? NINE_MAX_CONST_F : NINE_MAX_CONST_F_PS3)
#define FAILURE_VOID(cond) if ((cond)) {tx->failure=1;return;}
@@ -528,7 +539,7 @@ static boolean
tx_lconstf(struct shader_translator *tx, struct ureg_src *src, INT index)
{
INT i;
- if (index < 0 || index >= NINE_MAX_CONST_F_SHADER) {
+ if (index < 0 || index >= tx->num_constf_allowed) {
tx->failure = TRUE;
return FALSE;
}
@@ -543,7 +554,7 @@ tx_lconstf(struct shader_translator *tx, struct ureg_src *src, INT index)
static boolean
tx_lconsti(struct shader_translator *tx, struct ureg_src *src, INT index)
{
- if (index < 0 || index >= NINE_MAX_CONST_I) {
+ if (index < 0 || index >= tx->num_consti_allowed) {
tx->failure = TRUE;
return FALSE;
}
@@ -554,7 +565,7 @@ tx_lconsti(struct shader_translator *tx, struct ureg_src *src, INT index)
static boolean
tx_lconstb(struct shader_translator *tx, struct ureg_src *src, INT index)
{
- if (index < 0 || index >= NINE_MAX_CONST_B) {
+ if (index < 0 || index >= tx->num_constb_allowed) {
tx->failure = TRUE;
return FALSE;
}
@@ -568,9 +579,7 @@ tx_set_lconstf(struct shader_translator *tx, INT index, float f[4])
{
unsigned n;
- FAILURE_VOID(index < 0 || index >= NINE_MAX_CONST_F_SHADER)
- if (IS_VS && index >= NINE_MAX_CONST_F_SHADER)
- WARN("lconstf index %i too high, indirect access won't work\n", index);
+ FAILURE_VOID(index < 0 || index >= tx->num_constf_allowed)
for (n = 0; n < tx->num_lconstf; ++n)
if (tx->lconstf[n].idx == index)
@@ -592,7 +601,7 @@ tx_set_lconstf(struct shader_translator *tx, INT index, float f[4])
static void
tx_set_lconsti(struct shader_translator *tx, INT index, int i[4])
{
- FAILURE_VOID(index < 0 || index >= NINE_MAX_CONST_I)
+ FAILURE_VOID(index < 0 || index >= tx->num_consti_allowed)
tx->lconsti[index].idx = index;
tx->lconsti[index].reg = tx->native_integers ?
ureg_imm4i(tx->ureg, i[0], i[1], i[2], i[3]) :
@@ -601,7 +610,7 @@ tx_set_lconsti(struct shader_translator *tx, INT index, int i[4])
static void
tx_set_lconstb(struct shader_translator *tx, INT index, BOOL b)
{
- FAILURE_VOID(index < 0 || index >= NINE_MAX_CONST_B)
+ FAILURE_VOID(index < 0 || index >= tx->num_constb_allowed)
tx->lconstb[index].idx = index;
tx->lconstb[index].reg = tx->native_integers ?
ureg_imm1u(tx->ureg, b ? 0xffffffff : 0) :
@@ -672,6 +681,54 @@ tx_pred_alloc(struct shader_translator *tx, INT idx)
tx->regs.p = ureg_DECL_predicate(tx->ureg);
}
+/* NOTE: It's not very clear on which ps1.1-ps1.3 instructions
+ * the projection should be applied on the texture. It doesn't
+ * apply on texkill.
+ * The doc is very imprecise here (it says the projection is done
+ * before rasterization, thus in vs, which seems wrong since ps instructions
+ * are affected differently)
+ * For now we only apply to the ps TEX instruction and TEXBEM.
+ * Perhaps some other instructions would need it */
+static inline void
+apply_ps1x_projection(struct shader_translator *tx, struct ureg_dst dst,
+ struct ureg_src src, INT idx)
+{
+ struct ureg_dst tmp;
+ unsigned dim = 1 + ((tx->info->projected >> (2 * idx)) & 3);
+
+ /* no projection */
+ if (dim == 1) {
+ ureg_MOV(tx->ureg, dst, src);
+ } else {
+ tmp = tx_scratch_scalar(tx);
+ ureg_RCP(tx->ureg, tmp, ureg_scalar(src, dim-1));
+ ureg_MUL(tx->ureg, dst, tx_src_scalar(tmp), src);
+ }
+}
+
+static inline void
+TEX_with_ps1x_projection(struct shader_translator *tx, struct ureg_dst dst,
+ unsigned target, struct ureg_src src0,
+ struct ureg_src src1, INT idx)
+{
+ unsigned dim = 1 + ((tx->info->projected >> (2 * idx)) & 3);
+ struct ureg_dst tmp;
+
+ /* dim == 1: no projection
+ * Looks like must be disabled when it makes no
+ * sense according the texture dimensions
+ */
+ if (dim == 1 || dim <= target) {
+ ureg_TEX(tx->ureg, dst, target, src0, src1);
+ } else if (dim == 4) {
+ ureg_TXP(tx->ureg, dst, target, src0, src1);
+ } else {
+ tmp = tx_scratch(tx);
+ apply_ps1x_projection(tx, tmp, src0, idx);
+ ureg_TEX(tx->ureg, dst, target, ureg_src(tmp), src1);
+ }
+}
+
static inline void
tx_texcoord_alloc(struct shader_translator *tx, INT idx)
{
@@ -1086,9 +1143,18 @@ _tx_dst_param(struct shader_translator *tx, const struct sm1_dst_param *param)
assert(param->idx >= 0 && param->idx < 4);
assert(!param->rel);
tx->info->rt_mask |= 1 << param->idx;
- if (ureg_dst_is_undef(tx->regs.oCol[param->idx]))
- tx->regs.oCol[param->idx] =
- ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_COLOR, param->idx);
+ if (ureg_dst_is_undef(tx->regs.oCol[param->idx])) {
+ /* ps < 3: oCol[0] will have fog blending afterward
+ * vs < 3: oD1.w (D3DPMISCCAPS_FOGANDSPECULARALPHA) set to 0 even if set */
+ if (!IS_VS && tx->version.major < 3 && param->idx == 0) {
+ tx->regs.oCol[0] = ureg_DECL_temporary(tx->ureg);
+ } else if (IS_VS && tx->version.major < 3 && param->idx == 1) {
+ tx->regs.oCol[1] = ureg_DECL_temporary(tx->ureg);
+ } else {
+ tx->regs.oCol[param->idx] =
+ ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_COLOR, param->idx);
+ }
+ }
dst = tx->regs.oCol[param->idx];
if (IS_VS && tx->version.major < 3)
dst = ureg_saturate(dst);
@@ -1824,7 +1890,7 @@ sm1_declusage_to_tgsi(struct tgsi_declaration_semantic *sem,
sem->Index = 0;
break;
default:
- assert(!"Invalid DECLUSAGE.");
+ unreachable(!"Invalid DECLUSAGE.");
break;
}
}
@@ -2135,12 +2201,79 @@ DECL_SPECIAL(TEXKILL)
DECL_SPECIAL(TEXBEM)
{
- STUB(D3DERR_INVALIDCALL);
-}
+ struct ureg_program *ureg = tx->ureg;
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+ struct ureg_dst tmp, tmp2, texcoord;
+ struct ureg_src sample, m00, m01, m10, m11;
+ struct ureg_src bumpenvlscale, bumpenvloffset;
+ const int m = tx->insn.dst[0].idx;
+ const int n = tx->insn.src[0].idx;
-DECL_SPECIAL(TEXBEML)
-{
- STUB(D3DERR_INVALIDCALL);
+ assert(tx->version.major == 1);
+
+ sample = ureg_DECL_sampler(ureg, m);
+ tx->info->sampler_mask |= 1 << m;
+
+ tx_texcoord_alloc(tx, m);
+
+ tmp = tx_scratch(tx);
+ tmp2 = tx_scratch(tx);
+ texcoord = tx_scratch(tx);
+ /*
+ * Bump-env-matrix:
+ * 00 is X
+ * 01 is Y
+ * 10 is Z
+ * 11 is W
+ */
+ nine_info_mark_const_f_used(tx->info, 8 + 8 + m/2);
+ m00 = NINE_CONSTANT_SRC_SWIZZLE(8 + m, X);
+ m01 = NINE_CONSTANT_SRC_SWIZZLE(8 + m, Y);
+ m10 = NINE_CONSTANT_SRC_SWIZZLE(8 + m, Z);
+ m11 = NINE_CONSTANT_SRC_SWIZZLE(8 + m, W);
+
+ /* These two attributes are packed as X=scale0 Y=offset0 Z=scale1 W=offset1 etc */
+ if (m % 2 == 0) {
+ bumpenvlscale = NINE_CONSTANT_SRC_SWIZZLE(8 + 8 + m / 2, X);
+ bumpenvloffset = NINE_CONSTANT_SRC_SWIZZLE(8 + 8 + m / 2, Y);
+ } else {
+ bumpenvlscale = NINE_CONSTANT_SRC_SWIZZLE(8 + 8 + m / 2, Z);
+ bumpenvloffset = NINE_CONSTANT_SRC_SWIZZLE(8 + 8 + m / 2, W);
+ }
+
+ apply_ps1x_projection(tx, texcoord, tx->regs.vT[m], m);
+
+ /* u' = TextureCoordinates(stage m)u + D3DTSS_BUMPENVMAT00(stage m)*t(n)R */
+ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m00,
+ NINE_APPLY_SWIZZLE(ureg_src(tx->regs.tS[n]), X), ureg_src(texcoord));
+ /* u' = u' + D3DTSS_BUMPENVMAT10(stage m)*t(n)G */
+ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m10,
+ NINE_APPLY_SWIZZLE(ureg_src(tx->regs.tS[n]), Y),
+ NINE_APPLY_SWIZZLE(ureg_src(tmp), X));
+
+ /* v' = TextureCoordinates(stage m)v + D3DTSS_BUMPENVMAT01(stage m)*t(n)R */
+ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m01,
+ NINE_APPLY_SWIZZLE(ureg_src(tx->regs.tS[n]), X), ureg_src(texcoord));
+ /* v' = v' + D3DTSS_BUMPENVMAT11(stage m)*t(n)G*/
+ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m11,
+ NINE_APPLY_SWIZZLE(ureg_src(tx->regs.tS[n]), Y),
+ NINE_APPLY_SWIZZLE(ureg_src(tmp), Y));
+
+ /* Now the texture coordinates are in tmp.xy */
+
+ if (tx->insn.opcode == D3DSIO_TEXBEM) {
+ ureg_TEX(ureg, dst, ps1x_sampler_type(tx->info, m), ureg_src(tmp), sample);
+ } else if (tx->insn.opcode == D3DSIO_TEXBEML) {
+ /* t(m)RGBA = t(m)RGBA * [(t(n)B * D3DTSS_BUMPENVLSCALE(stage m)) + D3DTSS_BUMPENVLOFFSET(stage m)] */
+ ureg_TEX(ureg, tmp, ps1x_sampler_type(tx->info, m), ureg_src(tmp), sample);
+ ureg_MAD(ureg, tmp2, NINE_APPLY_SWIZZLE(ureg_src(tx->regs.tS[n]), Z),
+ bumpenvlscale, bumpenvloffset);
+ ureg_MUL(ureg, dst, ureg_src(tmp), ureg_src(tmp2));
+ }
+
+ tx->info->bumpenvmat_needed = 1;
+
+ return D3D_OK;
}
DECL_SPECIAL(TEXREG2AR)
@@ -2421,7 +2554,43 @@ DECL_SPECIAL(TEXDEPTH)
DECL_SPECIAL(BEM)
{
- STUB(D3DERR_INVALIDCALL);
+ struct ureg_program *ureg = tx->ureg;
+ struct ureg_dst dst = tx_dst_param(tx, &tx->insn.dst[0]);
+ struct ureg_src src0 = tx_src_param(tx, &tx->insn.src[0]);
+ struct ureg_src src1 = tx_src_param(tx, &tx->insn.src[1]);
+ struct ureg_src m00, m01, m10, m11;
+ const int m = tx->insn.dst[0].idx;
+ struct ureg_dst tmp;
+ /*
+ * Bump-env-matrix:
+ * 00 is X
+ * 01 is Y
+ * 10 is Z
+ * 11 is W
+ */
+ nine_info_mark_const_f_used(tx->info, 8 + m);
+ m00 = NINE_CONSTANT_SRC_SWIZZLE(8 + m, X);
+ m01 = NINE_CONSTANT_SRC_SWIZZLE(8 + m, Y);
+ m10 = NINE_CONSTANT_SRC_SWIZZLE(8 + m, Z);
+ m11 = NINE_CONSTANT_SRC_SWIZZLE(8 + m, W);
+ /* dest.r = src0.r + D3DTSS_BUMPENVMAT00(stage n) * src1.r */
+ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m00,
+ NINE_APPLY_SWIZZLE(src1, X), NINE_APPLY_SWIZZLE(src0, X));
+ /* dest.r = dest.r + D3DTSS_BUMPENVMAT10(stage n) * src1.g; */
+ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), m10,
+ NINE_APPLY_SWIZZLE(src1, Y), NINE_APPLY_SWIZZLE(ureg_src(tmp), X));
+
+ /* dest.g = src0.g + D3DTSS_BUMPENVMAT01(stage n) * src1.r */
+ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m01,
+ NINE_APPLY_SWIZZLE(src1, X), src0);
+ /* dest.g = dest.g + D3DTSS_BUMPENVMAT11(stage n) * src1.g */
+ ureg_MAD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), m11,
+ NINE_APPLY_SWIZZLE(src1, Y), NINE_APPLY_SWIZZLE(ureg_src(tmp), Y));
+ ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_XY), ureg_src(tmp));
+
+ tx->info->bumpenvmat_needed = 1;
+
+ return D3D_OK;
}
DECL_SPECIAL(TEXLD)
@@ -2482,7 +2651,7 @@ DECL_SPECIAL(TEX)
src[1] = ureg_DECL_sampler(ureg, s);
tx->info->sampler_mask |= 1 << s;
- ureg_TEX(ureg, dst, t, src[0], src[1]);
+ TEX_with_ps1x_projection(tx, dst, t, src[0], src[1], s);
return D3D_OK;
}
@@ -2616,7 +2785,7 @@ struct sm1_op_info inst_table[] =
_OPI(TEX, TEX, V(0,0), V(0,0), V(1,4), V(1,4), 1, 1, SPECIAL(TEXLD_14)),
_OPI(TEX, TEX, V(0,0), V(0,0), V(2,0), V(3,0), 1, 2, SPECIAL(TEXLD)),
_OPI(TEXBEM, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXBEM)),
- _OPI(TEXBEML, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXBEML)),
+ _OPI(TEXBEML, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXBEM)),
_OPI(TEXREG2AR, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXREG2AR)),
_OPI(TEXREG2GB, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXREG2GB)),
_OPI(TEXM3x2PAD, TEX, V(0,0), V(0,0), V(0,0), V(1,3), 1, 1, SPECIAL(TEXM3x2PAD)),
@@ -3023,6 +3192,8 @@ tx_ctor(struct shader_translator *tx, struct nine_shader_info *info)
info->lconstf.data = NULL;
info->lconstf.ranges = NULL;
+ info->bumpenvmat_needed = 0;
+
for (i = 0; i < Elements(tx->regs.rL); ++i) {
tx->regs.rL[i] = ureg_dst_undef();
}
@@ -3074,6 +3245,57 @@ tgsi_processor_from_type(unsigned shader_type)
}
}
+static void
+shader_add_ps_fog_stage(struct shader_translator *tx, struct ureg_src src_col)
+{
+ struct ureg_program *ureg = tx->ureg;
+ struct ureg_dst oCol0 = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
+ struct ureg_src fog_end, fog_coeff, fog_density;
+ struct ureg_src fog_vs, depth, fog_color;
+ struct ureg_dst fog_factor;
+
+ if (!tx->info->fog_enable) {
+ ureg_MOV(ureg, oCol0, src_col);
+ return;
+ }
+
+ if (tx->info->fog_mode != D3DFOG_NONE)
+ depth = ureg_scalar(ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, 0,
+ TGSI_INTERPOLATE_LINEAR),
+ TGSI_SWIZZLE_Z);
+
+ nine_info_mark_const_f_used(tx->info, 33);
+ fog_color = NINE_CONSTANT_SRC(32);
+ fog_factor = tx_scratch_scalar(tx);
+
+ if (tx->info->fog_mode == D3DFOG_LINEAR) {
+ fog_end = NINE_CONSTANT_SRC_SWIZZLE(33, X);
+ fog_coeff = NINE_CONSTANT_SRC_SWIZZLE(33, Y);
+ ureg_SUB(ureg, fog_factor, fog_end, depth);
+ ureg_MUL(ureg, ureg_saturate(fog_factor), tx_src_scalar(fog_factor), fog_coeff);
+ } else if (tx->info->fog_mode == D3DFOG_EXP) {
+ fog_density = NINE_CONSTANT_SRC_SWIZZLE(33, X);
+ ureg_MUL(ureg, fog_factor, depth, fog_density);
+ ureg_MUL(ureg, fog_factor, tx_src_scalar(fog_factor), ureg_imm1f(ureg, -1.442695f));
+ ureg_EX2(ureg, fog_factor, tx_src_scalar(fog_factor));
+ } else if (tx->info->fog_mode == D3DFOG_EXP2) {
+ fog_density = NINE_CONSTANT_SRC_SWIZZLE(33, X);
+ ureg_MUL(ureg, fog_factor, depth, fog_density);
+ ureg_MUL(ureg, fog_factor, tx_src_scalar(fog_factor), tx_src_scalar(fog_factor));
+ ureg_MUL(ureg, fog_factor, tx_src_scalar(fog_factor), ureg_imm1f(ureg, -1.442695f));
+ ureg_EX2(ureg, fog_factor, tx_src_scalar(fog_factor));
+ } else {
+ fog_vs = ureg_scalar(ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_FOG, 0,
+ TGSI_INTERPOLATE_PERSPECTIVE),
+ TGSI_SWIZZLE_X);
+ ureg_MOV(ureg, fog_factor, fog_vs);
+ }
+
+ ureg_LRP(ureg, ureg_writemask(oCol0, TGSI_WRITEMASK_XYZ),
+ tx_src_scalar(fog_factor), src_col, fog_color);
+ ureg_MOV(ureg, ureg_writemask(oCol0, TGSI_WRITEMASK_W), src_col);
+}
+
#define GET_CAP(n) device->screen->get_param( \
device->screen, PIPE_CAP_##n)
#define GET_SHADER_CAP(n) device->screen->get_shader_param( \
@@ -3123,6 +3345,24 @@ nine_translate_shader(struct NineDevice9 *device, struct nine_shader_info *info)
tx->texcoord_sn = tx->want_texcoord ?
TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC;
+ if (IS_VS) {
+ tx->num_constf_allowed = NINE_MAX_CONST_F;
+ } else if (tx->version.major < 2) {/* IS_PS v1 */
+ tx->num_constf_allowed = 8;
+ } else if (tx->version.major == 2) {/* IS_PS v2 */
+ tx->num_constf_allowed = 32;
+ } else {/* IS_PS v3 */
+ tx->num_constf_allowed = NINE_MAX_CONST_F_PS3;
+ }
+
+ if (tx->version.major < 2) {
+ tx->num_consti_allowed = 0;
+ tx->num_constb_allowed = 0;
+ } else {
+ tx->num_consti_allowed = NINE_MAX_CONST_I;
+ tx->num_constb_allowed = NINE_MAX_CONST_B;
+ }
+
/* VS must always write position. Declare it here to make it the 1st output.
* (Some drivers like nv50 are buggy and rely on that.)
*/
@@ -3145,10 +3385,26 @@ nine_translate_shader(struct NineDevice9 *device, struct nine_shader_info *info)
goto out;
}
- if (IS_PS && (tx->version.major < 2) && tx->num_temp) {
- ureg_MOV(tx->ureg, ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_COLOR, 0),
- ureg_src(tx->regs.r[0]));
- info->rt_mask |= 0x1;
+ if (IS_PS && tx->version.major < 3) {
+ if (tx->version.major < 2) {
+ assert(tx->num_temp); /* there must be color output */
+ info->rt_mask |= 0x1;
+ shader_add_ps_fog_stage(tx, ureg_src(tx->regs.r[0]));
+ } else {
+ shader_add_ps_fog_stage(tx, ureg_src(tx->regs.oCol[0]));
+ }
+ }
+
+ if (IS_VS && tx->version.major < 3 && ureg_dst_is_undef(tx->regs.oFog) && info->fog_enable) {
+ tx->regs.oFog = ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_FOG, 0);
+ ureg_MOV(tx->ureg, ureg_writemask(tx->regs.oFog, TGSI_WRITEMASK_X), ureg_imm1f(tx->ureg, 0.0f));
+ }
+
+ /* vs < 3: oD1.w (D3DPMISCCAPS_FOGANDSPECULARALPHA) set to 0 even if set */
+ if (IS_VS && tx->version.major < 3 && !ureg_dst_is_undef(tx->regs.oCol[1])) {
+ struct ureg_dst dst = ureg_DECL_output(tx->ureg, TGSI_SEMANTIC_COLOR, 1);
+ ureg_MOV(tx->ureg, ureg_writemask(dst, TGSI_WRITEMASK_XYZ), ureg_src(tx->regs.oCol[1]));
+ ureg_MOV(tx->ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), ureg_imm1f(tx->ureg, 0.0f));
}
if (info->position_t)
@@ -3233,6 +3489,7 @@ nine_translate_shader(struct NineDevice9 *device, struct nine_shader_info *info)
info->const_int_slots > 0 ?
max_const_f + info->const_int_slots :
info->const_float_slots;
+
info->const_used_size = sizeof(float[4]) * slot_max; /* slots start from 1 */
for (s = 0; s < slot_max; s++)
diff --git a/src/gallium/state_trackers/nine/nine_shader.h b/src/gallium/state_trackers/nine/nine_shader.h
index ec256c153a9..41577ac572b 100644
--- a/src/gallium/state_trackers/nine/nine_shader.h
+++ b/src/gallium/state_trackers/nine/nine_shader.h
@@ -59,6 +59,10 @@ struct nine_shader_info
uint16_t sampler_mask_shadow; /* in, which samplers use depth compare */
uint8_t rt_mask; /* out, which render targets are being written */
+ uint8_t fog_enable;
+ uint8_t fog_mode;
+ uint16_t projected; /* ps 1.1 to 1.3 */
+
unsigned const_i_base; /* in vec4 (16 byte) units */
unsigned const_b_base; /* in vec4 (16 byte) units */
unsigned const_used_size;
@@ -68,6 +72,7 @@ struct nine_shader_info
unsigned const_bool_slots;
struct nine_lconstf lconstf; /* out, NOTE: members to be free'd by user */
+ uint8_t bumpenvmat_needed;
};
static inline void
@@ -137,4 +142,48 @@ nine_shader_variants_free(struct nine_shader_variant *list)
}
}
+struct nine_shader_variant64
+{
+ struct nine_shader_variant64 *next;
+ void *cso;
+ uint64_t key;
+};
+
+static inline void *
+nine_shader_variant_get64(struct nine_shader_variant64 *list, uint64_t key)
+{
+ while (list->key != key && list->next)
+ list = list->next;
+ if (list->key == key)
+ return list->cso;
+ return NULL;
+}
+
+static inline boolean
+nine_shader_variant_add64(struct nine_shader_variant64 *list,
+ uint64_t key, void *cso)
+{
+ while (list->next) {
+ assert(list->key != key);
+ list = list->next;
+ }
+ list->next = MALLOC_STRUCT(nine_shader_variant64);
+ if (!list->next)
+ return FALSE;
+ list->next->next = NULL;
+ list->next->key = key;
+ list->next->cso = cso;
+ return TRUE;
+}
+
+static inline void
+nine_shader_variants_free64(struct nine_shader_variant64 *list)
+{
+ while (list->next) {
+ struct nine_shader_variant64 *ptr = list->next;
+ list->next = ptr->next;
+ FREE(ptr);
+ }
+}
+
#endif /* _NINE_SHADER_H_ */
diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c
index 6c835858d18..558d07a2bd0 100644
--- a/src/gallium/state_trackers/nine/nine_state.c
+++ b/src/gallium/state_trackers/nine/nine_state.c
@@ -33,352 +33,36 @@
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "cso_cache/cso_context.h"
+#include "util/u_upload_mgr.h"
#include "util/u_math.h"
#define DBG_CHANNEL DBG_DEVICE
-static uint32_t
-update_framebuffer(struct NineDevice9 *device)
-{
- struct pipe_context *pipe = device->pipe;
- struct nine_state *state = &device->state;
- struct pipe_framebuffer_state *fb = &device->state.fb;
- unsigned i;
- struct NineSurface9 *rt0 = state->rt[0];
- unsigned w = rt0->desc.Width;
- unsigned h = rt0->desc.Height;
- D3DMULTISAMPLE_TYPE nr_samples = rt0->desc.MultiSampleType;
- unsigned mask = state->ps ? state->ps->rt_mask : 1;
- const int sRGB = state->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0;
-
- DBG("\n");
-
- state->rt_mask = 0x0;
- fb->nr_cbufs = 0;
-
- /* all render targets must have the same size and the depth buffer must be
- * bigger. Multisample has to match, according to spec. But some apps do
- * things wrong there, and no error is returned. The behaviour they get
- * apparently is that depth buffer is disabled if it doesn't match.
- * Surely the same for render targets. */
-
- /* Special case: D3DFMT_NULL is used to bound no real render target,
- * but render to depth buffer. We have to not take into account the render
- * target info. TODO: know what should happen when there are several render targers
- * and the first one is D3DFMT_NULL */
- if (rt0->desc.Format == D3DFMT_NULL && state->ds) {
- w = state->ds->desc.Width;
- h = state->ds->desc.Height;
- nr_samples = state->ds->desc.MultiSampleType;
- }
-
- for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) {
- struct NineSurface9 *rt = state->rt[i];
-
- if (rt && rt->desc.Format != D3DFMT_NULL && (mask & (1 << i)) &&
- rt->desc.Width == w && rt->desc.Height == h &&
- rt->desc.MultiSampleType == nr_samples) {
- fb->cbufs[i] = NineSurface9_GetSurface(rt, sRGB);
- state->rt_mask |= 1 << i;
- fb->nr_cbufs = i + 1;
-
- if (unlikely(rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP)) {
- assert(rt->texture == D3DRTYPE_TEXTURE ||
- rt->texture == D3DRTYPE_CUBETEXTURE);
- NineBaseTexture9(rt->base.base.container)->dirty_mip = TRUE;
- }
- } else {
- /* Color outputs must match RT slot,
- * drivers will have to handle NULL entries for GL, too.
- */
- fb->cbufs[i] = NULL;
- }
- }
-
- if (state->ds && state->ds->desc.Width >= w &&
- state->ds->desc.Height >= h &&
- state->ds->desc.MultiSampleType == nr_samples) {
- fb->zsbuf = NineSurface9_GetSurface(state->ds, 0);
- } else {
- fb->zsbuf = NULL;
- }
-
- fb->width = w;
- fb->height = h;
-
- pipe->set_framebuffer_state(pipe, fb); /* XXX: cso ? */
-
- if (fb->zsbuf) {
- DWORD scale;
- switch (fb->zsbuf->format) {
- case PIPE_FORMAT_Z32_FLOAT:
- case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
- scale = fui(1.0f);
- break;
- case PIPE_FORMAT_Z16_UNORM:
- scale = fui((float)(1 << 16));
- break;
- default:
- scale = fui((float)(1 << 24));
- break;
- }
- if (state->rs[NINED3DRS_ZBIASSCALE] != scale) {
- state->rs[NINED3DRS_ZBIASSCALE] = scale;
- state->changed.group |= NINE_STATE_RASTERIZER;
- }
- }
-
- return state->changed.group;
-}
-
-static void
-update_viewport(struct NineDevice9 *device)
-{
- struct pipe_context *pipe = device->pipe;
- const D3DVIEWPORT9 *vport = &device->state.viewport;
- struct pipe_viewport_state pvport;
-
- /* D3D coordinates are:
- * -1 .. +1 for X,Y and
- * 0 .. +1 for Z (we use pipe_rasterizer_state.clip_halfz)
- */
- pvport.scale[0] = (float)vport->Width * 0.5f;
- pvport.scale[1] = (float)vport->Height * -0.5f;
- pvport.scale[2] = vport->MaxZ - vport->MinZ;
- pvport.translate[0] = (float)vport->Width * 0.5f + (float)vport->X;
- pvport.translate[1] = (float)vport->Height * 0.5f + (float)vport->Y;
- pvport.translate[2] = vport->MinZ;
-
- /* We found R600 and SI cards have some imprecision
- * on the barycentric coordinates used for interpolation.
- * Some shaders rely on having something precise.
- * We found that the proprietary driver has the imprecision issue,
- * except when the render target width and height are powers of two.
- * It is using some sort of workaround for these cases
- * which covers likely all the cases the applications rely
- * on something precise.
- * We haven't found the workaround, but it seems like it's better
- * for applications if the imprecision is biased towards infinity
- * instead of -infinity (which is what measured). So shift slightly
- * the viewport: not enough to change rasterization result (in particular
- * for multisampling), but enough to make the imprecision biased
- * towards infinity. We do this shift only if render target width and
- * height are powers of two.
- * Solves 'red shadows' bug on UE3 games.
- */
- if (device->driver_bugs.buggy_barycentrics &&
- ((vport->Width & (vport->Width-1)) == 0) &&
- ((vport->Height & (vport->Height-1)) == 0)) {
- pvport.translate[0] -= 1.0f / 128.0f;
- pvport.translate[1] -= 1.0f / 128.0f;
- }
-
- pipe->set_viewport_states(pipe, 0, 1, &pvport);
-}
-
-static inline void
-update_scissor(struct NineDevice9 *device)
-{
- struct pipe_context *pipe = device->pipe;
-
- pipe->set_scissor_states(pipe, 0, 1, &device->state.scissor);
-}
+/* State preparation only */
static inline void
-update_blend(struct NineDevice9 *device)
+prepare_blend(struct NineDevice9 *device)
{
- nine_convert_blend_state(device->cso, device->state.rs);
+ nine_convert_blend_state(&device->state.pipe.blend, device->state.rs);
+ device->state.commit |= NINE_STATE_COMMIT_BLEND;
}
static inline void
-update_dsa(struct NineDevice9 *device)
+prepare_dsa(struct NineDevice9 *device)
{
- nine_convert_dsa_state(device->cso, device->state.rs);
+ nine_convert_dsa_state(&device->state.pipe.dsa, device->state.rs);
+ device->state.commit |= NINE_STATE_COMMIT_DSA;
}
static inline void
-update_rasterizer(struct NineDevice9 *device)
+prepare_rasterizer(struct NineDevice9 *device)
{
- nine_convert_rasterizer_state(device->cso, device->state.rs);
+ nine_convert_rasterizer_state(&device->state.pipe.rast, device->state.rs);
+ device->state.commit |= NINE_STATE_COMMIT_RASTERIZER;
}
-/* Loop through VS inputs and pick the vertex elements with the declared
- * usage from the vertex declaration, then insert the instance divisor from
- * the stream source frequency setting.
- */
static void
-update_vertex_elements(struct NineDevice9 *device)
-{
- struct nine_state *state = &device->state;
- const struct NineVertexDeclaration9 *vdecl = device->state.vdecl;
- const struct NineVertexShader9 *vs;
- unsigned n, b, i;
- int index;
- char vdecl_index_map[16]; /* vs->num_inputs <= 16 */
- char used_streams[device->caps.MaxStreams];
- int dummy_vbo_stream = -1;
- BOOL need_dummy_vbo = FALSE;
- struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
-
- state->stream_usage_mask = 0;
- memset(vdecl_index_map, -1, 16);
- memset(used_streams, 0, device->caps.MaxStreams);
- vs = device->state.vs ? device->state.vs : device->ff.vs;
-
- if (vdecl) {
- for (n = 0; n < vs->num_inputs; ++n) {
- DBG("looking up input %u (usage %u) from vdecl(%p)\n",
- n, vs->input_map[n].ndecl, vdecl);
-
- for (i = 0; i < vdecl->nelems; i++) {
- if (vdecl->usage_map[i] == vs->input_map[n].ndecl) {
- vdecl_index_map[n] = i;
- used_streams[vdecl->elems[i].vertex_buffer_index] = 1;
- break;
- }
- }
- if (vdecl_index_map[n] < 0)
- need_dummy_vbo = TRUE;
- }
- } else {
- /* No vertex declaration. Likely will never happen in practice,
- * but we need not crash on this */
- need_dummy_vbo = TRUE;
- }
-
- if (need_dummy_vbo) {
- for (i = 0; i < device->caps.MaxStreams; i++ ) {
- if (!used_streams[i]) {
- dummy_vbo_stream = i;
- break;
- }
- }
- }
- /* there are less vertex shader inputs than stream slots,
- * so if we need a slot for the dummy vbo, we should have found one */
- assert (!need_dummy_vbo || dummy_vbo_stream != -1);
-
- for (n = 0; n < vs->num_inputs; ++n) {
- index = vdecl_index_map[n];
- if (index >= 0) {
- ve[n] = vdecl->elems[index];
- b = ve[n].vertex_buffer_index;
- state->stream_usage_mask |= 1 << b;
- /* XXX wine just uses 1 here: */
- if (state->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA)
- ve[n].instance_divisor = state->stream_freq[b] & 0x7FFFFF;
- } else {
- /* if the vertex declaration is incomplete compared to what the
- * vertex shader needs, we bind a dummy vbo with 0 0 0 0.
- * This is not precised by the spec, but is the behaviour
- * tested on win */
- ve[n].vertex_buffer_index = dummy_vbo_stream;
- ve[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
- ve[n].src_offset = 0;
- ve[n].instance_divisor = 0;
- }
- }
-
- if (state->dummy_vbo_bound_at != dummy_vbo_stream) {
- if (state->dummy_vbo_bound_at >= 0)
- state->changed.vtxbuf |= 1 << state->dummy_vbo_bound_at;
- if (dummy_vbo_stream >= 0) {
- state->changed.vtxbuf |= 1 << dummy_vbo_stream;
- state->vbo_bound_done = FALSE;
- }
- state->dummy_vbo_bound_at = dummy_vbo_stream;
- }
-
- cso_set_vertex_elements(device->cso, vs->num_inputs, ve);
-
- state->changed.stream_freq = 0;
-}
-
-static inline uint32_t
-update_shader_variant_keys(struct NineDevice9 *device)
-{
- struct nine_state *state = &device->state;
- uint32_t mask = 0;
- uint32_t vs_key = state->samplers_shadow;
- uint32_t ps_key = state->samplers_shadow;
-
- vs_key = (vs_key & NINE_VS_SAMPLERS_MASK) >> NINE_SAMPLER_VS(0);
- ps_key = (ps_key & NINE_PS_SAMPLERS_MASK) >> NINE_SAMPLER_PS(0);
-
- if (state->vs) vs_key &= state->vs->sampler_mask;
- if (state->ps) {
- if (unlikely(state->ps->byte_code.version < 0x20)) {
- /* no depth textures, but variable targets */
- uint32_t m = state->ps->sampler_mask;
- ps_key = 0;
- while (m) {
- int s = ffs(m) - 1;
- m &= ~(1 << s);
- ps_key |= (state->texture[s] ? state->texture[s]->pstype : 1) << (s * 2);
- }
- } else {
- ps_key &= state->ps->sampler_mask;
- }
- }
-
- if (state->vs && state->vs_key != vs_key) {
- state->vs_key = vs_key;
- mask |= NINE_STATE_VS;
- }
- if (state->ps && state->ps_key != ps_key) {
- state->ps_key = ps_key;
- mask |= NINE_STATE_PS;
- }
- return mask;
-}
-
-static inline uint32_t
-update_vs(struct NineDevice9 *device)
-{
- struct nine_state *state = &device->state;
- struct NineVertexShader9 *vs = state->vs;
- uint32_t changed_group = 0;
-
- /* likely because we dislike FF */
- if (likely(vs)) {
- state->cso.vs = NineVertexShader9_GetVariant(vs, state->vs_key);
- } else {
- vs = device->ff.vs;
- state->cso.vs = vs->variant.cso;
- }
- device->pipe->bind_vs_state(device->pipe, state->cso.vs);
-
- if (state->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) {
- state->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size;
- changed_group |= NINE_STATE_RASTERIZER;
- }
-
- if ((state->bound_samplers_mask_vs & vs->sampler_mask) != vs->sampler_mask)
- /* Bound dummy sampler. */
- changed_group |= NINE_STATE_SAMPLER;
- return changed_group;
-}
-
-static inline uint32_t
-update_ps(struct NineDevice9 *device)
-{
- struct nine_state *state = &device->state;
- struct NinePixelShader9 *ps = state->ps;
- uint32_t changed_group = 0;
-
- if (likely(ps)) {
- state->cso.ps = NinePixelShader9_GetVariant(ps, state->ps_key);
- } else {
- ps = device->ff.ps;
- state->cso.ps = ps->variant.cso;
- }
- device->pipe->bind_fs_state(device->pipe, state->cso.ps);
-
- if ((state->bound_samplers_mask_ps & ps->sampler_mask) != ps->sampler_mask)
- /* Bound dummy sampler. */
- changed_group |= NINE_STATE_SAMPLER;
- return changed_group;
-}
+prepare_ps_constants_userbuf(struct NineDevice9 *device);
#define DO_UPLOAD_CONST_F(buf,p,c,d) \
do { \
@@ -391,7 +75,7 @@ update_ps(struct NineDevice9 *device)
/* OK, this is a bit ugly ... */
static void
-update_constants(struct NineDevice9 *device, unsigned shader_type)
+upload_constants(struct NineDevice9 *device, unsigned shader_type)
{
struct pipe_context *pipe = device->pipe;
struct pipe_resource *buf;
@@ -438,10 +122,17 @@ update_constants(struct NineDevice9 *device, unsigned shader_type)
lconstf_ranges = device->state.vs->lconstf.ranges;
lconstf_data = device->state.vs->lconstf.data;
- device->state.ff.clobber.vs_const = TRUE;
device->state.changed.group &= ~NINE_STATE_VS_CONST;
} else {
DBG("PS\n");
+ /* features only implemented on the userbuf path */
+ if (device->state.ps->bumpenvmat_needed || (
+ device->state.ps->byte_code.version < 0x30 &&
+ device->state.rs[D3DRS_FOGENABLE])) {
+ device->prefer_user_constbuf = TRUE;
+ prepare_ps_constants_userbuf(device);
+ return;
+ }
buf = device->constbuf_ps;
const_f = device->state.ps_const_f;
@@ -464,7 +155,6 @@ update_constants(struct NineDevice9 *device, unsigned shader_type)
lconstf_ranges = NULL;
lconstf_data = NULL;
- device->state.ff.clobber.ps_const = TRUE;
device->state.changed.group &= ~NINE_STATE_PS_CONST;
}
@@ -524,10 +214,9 @@ update_constants(struct NineDevice9 *device, unsigned shader_type)
}
static void
-update_vs_constants_userbuf(struct NineDevice9 *device)
+prepare_vs_constants_userbuf(struct NineDevice9 *device)
{
struct nine_state *state = &device->state;
- struct pipe_context *pipe = device->pipe;
struct pipe_constant_buffer cb;
cb.buffer = NULL;
cb.buffer_offset = 0;
@@ -567,7 +256,18 @@ update_vs_constants_userbuf(struct NineDevice9 *device)
cb.user_buffer = dst;
}
- pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &cb);
+ if (!device->driver_caps.user_cbufs) {
+ u_upload_data(device->constbuf_uploader,
+ 0,
+ cb.buffer_size,
+ cb.user_buffer,
+ &cb.buffer_offset,
+ &cb.buffer);
+ u_upload_unmap(device->constbuf_uploader);
+ cb.user_buffer = NULL;
+ }
+
+ state->pipe.cb_vs = cb;
if (device->state.changed.vs_const_f) {
struct nine_range *r = device->state.changed.vs_const_f;
@@ -578,22 +278,19 @@ update_vs_constants_userbuf(struct NineDevice9 *device)
device->state.changed.vs_const_f = NULL;
}
state->changed.group &= ~NINE_STATE_VS_CONST;
+ state->commit |= NINE_STATE_COMMIT_CONST_VS;
}
static void
-update_ps_constants_userbuf(struct NineDevice9 *device)
+prepare_ps_constants_userbuf(struct NineDevice9 *device)
{
struct nine_state *state = &device->state;
- struct pipe_context *pipe = device->pipe;
struct pipe_constant_buffer cb;
cb.buffer = NULL;
cb.buffer_offset = 0;
cb.buffer_size = device->state.ps->const_used_size;
cb.user_buffer = device->state.ps_const_f;
- if (!cb.buffer_size)
- return;
-
if (state->changed.ps_const_i) {
int *idst = (int *)&state->ps_const_f[4 * device->max_ps_const_f];
memcpy(idst, state->ps_const_i, sizeof(state->ps_const_i));
@@ -606,7 +303,47 @@ update_ps_constants_userbuf(struct NineDevice9 *device)
state->changed.ps_const_b = 0;
}
- pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &cb);
+ /* Upload special constants needed to implement PS1.x instructions like TEXBEM,TEXBEML and BEM */
+ if (device->state.ps->bumpenvmat_needed) {
+ memcpy(device->state.ps_lconstf_temp, cb.user_buffer, cb.buffer_size);
+ memcpy(&device->state.ps_lconstf_temp[4 * 8], &device->state.bumpmap_vars, sizeof(device->state.bumpmap_vars));
+
+ cb.user_buffer = device->state.ps_lconstf_temp;
+ }
+
+ if (state->ps->byte_code.version < 0x30 &&
+ state->rs[D3DRS_FOGENABLE]) {
+ float *dst = &state->ps_lconstf_temp[4 * 32];
+ if (cb.user_buffer != state->ps_lconstf_temp) {
+ memcpy(state->ps_lconstf_temp, cb.user_buffer, cb.buffer_size);
+ cb.user_buffer = state->ps_lconstf_temp;
+ }
+
+ d3dcolor_to_rgba(dst, state->rs[D3DRS_FOGCOLOR]);
+ if (state->rs[D3DRS_FOGTABLEMODE] == D3DFOG_LINEAR) {
+ dst[4] = asfloat(state->rs[D3DRS_FOGEND]);
+ dst[5] = 1.0f / (asfloat(state->rs[D3DRS_FOGEND]) - asfloat(state->rs[D3DRS_FOGSTART]));
+ } else if (state->rs[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
+ dst[4] = asfloat(state->rs[D3DRS_FOGDENSITY]);
+ }
+ cb.buffer_size = 4 * 4 * 34;
+ }
+
+ if (!cb.buffer_size)
+ return;
+
+ if (!device->driver_caps.user_cbufs) {
+ u_upload_data(device->constbuf_uploader,
+ 0,
+ cb.buffer_size,
+ cb.user_buffer,
+ &cb.buffer_offset,
+ &cb.buffer);
+ u_upload_unmap(device->constbuf_uploader);
+ cb.user_buffer = NULL;
+ }
+
+ state->pipe.cb_ps = cb;
if (device->state.changed.ps_const_f) {
struct nine_range *r = device->state.changed.ps_const_f;
@@ -617,6 +354,286 @@ update_ps_constants_userbuf(struct NineDevice9 *device)
device->state.changed.ps_const_f = NULL;
}
state->changed.group &= ~NINE_STATE_PS_CONST;
+ state->commit |= NINE_STATE_COMMIT_CONST_PS;
+}
+
+static inline uint32_t
+prepare_vs(struct NineDevice9 *device, uint8_t shader_changed)
+{
+ struct nine_state *state = &device->state;
+ struct NineVertexShader9 *vs = state->vs;
+ uint32_t changed_group = 0;
+ int has_key_changed = 0;
+
+ if (likely(vs))
+ has_key_changed = NineVertexShader9_UpdateKey(vs, state);
+
+ if (!shader_changed && !has_key_changed)
+ return 0;
+
+ /* likely because we dislike FF */
+ if (likely(vs)) {
+ state->cso.vs = NineVertexShader9_GetVariant(vs);
+ } else {
+ vs = device->ff.vs;
+ state->cso.vs = vs->ff_cso;
+ }
+
+ if (state->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) {
+ state->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size;
+ changed_group |= NINE_STATE_RASTERIZER;
+ }
+
+ if ((state->bound_samplers_mask_vs & vs->sampler_mask) != vs->sampler_mask)
+ /* Bound dummy sampler. */
+ changed_group |= NINE_STATE_SAMPLER;
+
+ state->commit |= NINE_STATE_COMMIT_VS;
+ return changed_group;
+}
+
+static inline uint32_t
+prepare_ps(struct NineDevice9 *device, uint8_t shader_changed)
+{
+ struct nine_state *state = &device->state;
+ struct NinePixelShader9 *ps = state->ps;
+ uint32_t changed_group = 0;
+ int has_key_changed = 0;
+
+ if (likely(ps))
+ has_key_changed = NinePixelShader9_UpdateKey(ps, state);
+
+ if (!shader_changed && !has_key_changed)
+ return 0;
+
+ if (likely(ps)) {
+ state->cso.ps = NinePixelShader9_GetVariant(ps);
+ } else {
+ ps = device->ff.ps;
+ state->cso.ps = ps->ff_cso;
+ }
+
+ if ((state->bound_samplers_mask_ps & ps->sampler_mask) != ps->sampler_mask)
+ /* Bound dummy sampler. */
+ changed_group |= NINE_STATE_SAMPLER;
+
+ state->commit |= NINE_STATE_COMMIT_PS;
+ return changed_group;
+}
+
+/* State preparation incremental */
+
+/* State preparation + State commit */
+
+static uint32_t
+update_framebuffer(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+ struct nine_state *state = &device->state;
+ struct pipe_framebuffer_state *fb = &device->state.fb;
+ unsigned i;
+ struct NineSurface9 *rt0 = state->rt[0];
+ unsigned w = rt0->desc.Width;
+ unsigned h = rt0->desc.Height;
+ D3DMULTISAMPLE_TYPE nr_samples = rt0->desc.MultiSampleType;
+ unsigned mask = state->ps ? state->ps->rt_mask : 1;
+ const int sRGB = state->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0;
+
+ DBG("\n");
+
+ state->rt_mask = 0x0;
+ fb->nr_cbufs = 0;
+
+ /* all render targets must have the same size and the depth buffer must be
+ * bigger. Multisample has to match, according to spec. But some apps do
+ * things wrong there, and no error is returned. The behaviour they get
+ * apparently is that depth buffer is disabled if it doesn't match.
+ * Surely the same for render targets. */
+
+ /* Special case: D3DFMT_NULL is used to bound no real render target,
+ * but render to depth buffer. We have to not take into account the render
+ * target info. TODO: know what should happen when there are several render targers
+ * and the first one is D3DFMT_NULL */
+ if (rt0->desc.Format == D3DFMT_NULL && state->ds) {
+ w = state->ds->desc.Width;
+ h = state->ds->desc.Height;
+ nr_samples = state->ds->desc.MultiSampleType;
+ }
+
+ for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) {
+ struct NineSurface9 *rt = state->rt[i];
+
+ if (rt && rt->desc.Format != D3DFMT_NULL && (mask & (1 << i)) &&
+ rt->desc.Width == w && rt->desc.Height == h &&
+ rt->desc.MultiSampleType == nr_samples) {
+ fb->cbufs[i] = NineSurface9_GetSurface(rt, sRGB);
+ state->rt_mask |= 1 << i;
+ fb->nr_cbufs = i + 1;
+
+ if (unlikely(rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP)) {
+ assert(rt->texture == D3DRTYPE_TEXTURE ||
+ rt->texture == D3DRTYPE_CUBETEXTURE);
+ NineBaseTexture9(rt->base.base.container)->dirty_mip = TRUE;
+ }
+ } else {
+ /* Color outputs must match RT slot,
+ * drivers will have to handle NULL entries for GL, too.
+ */
+ fb->cbufs[i] = NULL;
+ }
+ }
+
+ if (state->ds && state->ds->desc.Width >= w &&
+ state->ds->desc.Height >= h &&
+ state->ds->desc.MultiSampleType == nr_samples) {
+ fb->zsbuf = NineSurface9_GetSurface(state->ds, 0);
+ } else {
+ fb->zsbuf = NULL;
+ }
+
+ fb->width = w;
+ fb->height = h;
+
+ pipe->set_framebuffer_state(pipe, fb); /* XXX: cso ? */
+
+ return state->changed.group;
+}
+
+static void
+update_viewport(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+ const D3DVIEWPORT9 *vport = &device->state.viewport;
+ struct pipe_viewport_state pvport;
+
+ /* D3D coordinates are:
+ * -1 .. +1 for X,Y and
+ * 0 .. +1 for Z (we use pipe_rasterizer_state.clip_halfz)
+ */
+ pvport.scale[0] = (float)vport->Width * 0.5f;
+ pvport.scale[1] = (float)vport->Height * -0.5f;
+ pvport.scale[2] = vport->MaxZ - vport->MinZ;
+ pvport.translate[0] = (float)vport->Width * 0.5f + (float)vport->X;
+ pvport.translate[1] = (float)vport->Height * 0.5f + (float)vport->Y;
+ pvport.translate[2] = vport->MinZ;
+
+ /* We found R600 and SI cards have some imprecision
+ * on the barycentric coordinates used for interpolation.
+ * Some shaders rely on having something precise.
+ * We found that the proprietary driver has the imprecision issue,
+ * except when the render target width and height are powers of two.
+ * It is using some sort of workaround for these cases
+ * which covers likely all the cases the applications rely
+ * on something precise.
+ * We haven't found the workaround, but it seems like it's better
+ * for applications if the imprecision is biased towards infinity
+ * instead of -infinity (which is what measured). So shift slightly
+ * the viewport: not enough to change rasterization result (in particular
+ * for multisampling), but enough to make the imprecision biased
+ * towards infinity. We do this shift only if render target width and
+ * height are powers of two.
+ * Solves 'red shadows' bug on UE3 games.
+ */
+ if (device->driver_bugs.buggy_barycentrics &&
+ ((vport->Width & (vport->Width-1)) == 0) &&
+ ((vport->Height & (vport->Height-1)) == 0)) {
+ pvport.translate[0] -= 1.0f / 128.0f;
+ pvport.translate[1] -= 1.0f / 128.0f;
+ }
+
+ pipe->set_viewport_states(pipe, 0, 1, &pvport);
+}
+
+/* Loop through VS inputs and pick the vertex elements with the declared
+ * usage from the vertex declaration, then insert the instance divisor from
+ * the stream source frequency setting.
+ */
+static void
+update_vertex_elements(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+ const struct NineVertexDeclaration9 *vdecl = device->state.vdecl;
+ const struct NineVertexShader9 *vs;
+ unsigned n, b, i;
+ int index;
+ char vdecl_index_map[16]; /* vs->num_inputs <= 16 */
+ char used_streams[device->caps.MaxStreams];
+ int dummy_vbo_stream = -1;
+ BOOL need_dummy_vbo = FALSE;
+ struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
+
+ state->stream_usage_mask = 0;
+ memset(vdecl_index_map, -1, 16);
+ memset(used_streams, 0, device->caps.MaxStreams);
+ vs = device->state.vs ? device->state.vs : device->ff.vs;
+
+ if (vdecl) {
+ for (n = 0; n < vs->num_inputs; ++n) {
+ DBG("looking up input %u (usage %u) from vdecl(%p)\n",
+ n, vs->input_map[n].ndecl, vdecl);
+
+ for (i = 0; i < vdecl->nelems; i++) {
+ if (vdecl->usage_map[i] == vs->input_map[n].ndecl) {
+ vdecl_index_map[n] = i;
+ used_streams[vdecl->elems[i].vertex_buffer_index] = 1;
+ break;
+ }
+ }
+ if (vdecl_index_map[n] < 0)
+ need_dummy_vbo = TRUE;
+ }
+ } else {
+ /* No vertex declaration. Likely will never happen in practice,
+ * but we need not crash on this */
+ need_dummy_vbo = TRUE;
+ }
+
+ if (need_dummy_vbo) {
+ for (i = 0; i < device->caps.MaxStreams; i++ ) {
+ if (!used_streams[i]) {
+ dummy_vbo_stream = i;
+ break;
+ }
+ }
+ }
+ /* there are less vertex shader inputs than stream slots,
+ * so if we need a slot for the dummy vbo, we should have found one */
+ assert (!need_dummy_vbo || dummy_vbo_stream != -1);
+
+ for (n = 0; n < vs->num_inputs; ++n) {
+ index = vdecl_index_map[n];
+ if (index >= 0) {
+ ve[n] = vdecl->elems[index];
+ b = ve[n].vertex_buffer_index;
+ state->stream_usage_mask |= 1 << b;
+ /* XXX wine just uses 1 here: */
+ if (state->stream_freq[b] & D3DSTREAMSOURCE_INSTANCEDATA)
+ ve[n].instance_divisor = state->stream_freq[b] & 0x7FFFFF;
+ } else {
+ /* if the vertex declaration is incomplete compared to what the
+ * vertex shader needs, we bind a dummy vbo with 0 0 0 0.
+ * This is not precised by the spec, but is the behaviour
+ * tested on win */
+ ve[n].vertex_buffer_index = dummy_vbo_stream;
+ ve[n].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ ve[n].src_offset = 0;
+ ve[n].instance_divisor = 0;
+ }
+ }
+
+ if (state->dummy_vbo_bound_at != dummy_vbo_stream) {
+ if (state->dummy_vbo_bound_at >= 0)
+ state->changed.vtxbuf |= 1 << state->dummy_vbo_bound_at;
+ if (dummy_vbo_stream >= 0) {
+ state->changed.vtxbuf |= 1 << dummy_vbo_stream;
+ state->vbo_bound_done = FALSE;
+ }
+ state->dummy_vbo_bound_at = dummy_vbo_stream;
+ }
+
+ cso_set_vertex_elements(device->cso, vs->num_inputs, ve);
+
+ state->changed.stream_freq = 0;
}
static void
@@ -627,7 +644,6 @@ update_vertex_buffers(struct NineDevice9 *device)
struct pipe_vertex_buffer dummy_vtxbuf;
uint32_t mask = state->changed.vtxbuf;
unsigned i;
- unsigned start;
DBG("mask=%x\n", mask);
@@ -656,27 +672,6 @@ update_vertex_buffers(struct NineDevice9 *device)
state->changed.vtxbuf = 0;
}
-static inline void
-update_index_buffer(struct NineDevice9 *device)
-{
- struct pipe_context *pipe = device->pipe;
- if (device->state.idxbuf)
- pipe->set_index_buffer(pipe, &device->state.idxbuf->buffer);
- else
- pipe->set_index_buffer(pipe, NULL);
-}
-
-/* TODO: only go through dirty textures */
-static void
-validate_textures(struct NineDevice9 *device)
-{
- struct NineBaseTexture9 *tex, *ptr;
- LIST_FOR_EACH_ENTRY_SAFE(tex, ptr, &device->update_textures, list) {
- list_delinit(&tex->list);
- NineBaseTexture9_Validate(tex);
- }
-}
-
static inline boolean
update_sampler_derived(struct nine_state *state, unsigned s)
{
@@ -706,20 +701,16 @@ update_sampler_derived(struct nine_state *state, unsigned s)
static void
update_textures_and_samplers(struct NineDevice9 *device)
{
- struct pipe_context *pipe = device->pipe;
struct nine_state *state = &device->state;
struct pipe_sampler_view *view[NINE_MAX_SAMPLERS];
- struct pipe_sampler_state samp;
unsigned num_textures;
unsigned i;
- boolean commit_views;
boolean commit_samplers;
uint16_t sampler_mask = state->ps ? state->ps->sampler_mask :
device->ff.ps->sampler_mask;
/* TODO: Can we reduce iterations here ? */
- commit_views = FALSE;
commit_samplers = FALSE;
state->bound_samplers_mask_ps = 0;
for (num_textures = 0, i = 0; i < NINE_MAX_SAMPLERS_PS; ++i) {
@@ -749,26 +740,12 @@ update_textures_and_samplers(struct NineDevice9 *device)
* unbind dummy sampler directly when they are not needed
* anymore, but they're going to be removed as long as texture
* or sampler states are changed. */
- view[i] = device->dummy_sampler;
+ view[i] = device->dummy_sampler_view;
num_textures = i + 1;
- memset(&samp, 0, sizeof(samp));
- samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
- samp.max_lod = 15.0f;
- samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- samp.min_img_filter = PIPE_TEX_FILTER_NEAREST;
- samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
- samp.compare_mode = PIPE_TEX_COMPARE_NONE;
- samp.compare_func = PIPE_FUNC_LEQUAL;
- samp.normalized_coords = 1;
- samp.seamless_cube_map = 1;
-
cso_single_sampler(device->cso, PIPE_SHADER_FRAGMENT,
- s - NINE_SAMPLER_PS(0), &samp);
+ s - NINE_SAMPLER_PS(0), &device->dummy_sampler_state);
- commit_views = TRUE;
commit_samplers = TRUE;
state->changed.sampler[s] = ~0;
}
@@ -776,16 +753,11 @@ update_textures_and_samplers(struct NineDevice9 *device)
state->bound_samplers_mask_ps |= (1 << s);
}
- commit_views |= (state->changed.texture & NINE_PS_SAMPLERS_MASK) != 0;
- commit_views |= state->changed.srgb;
- if (commit_views)
- pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0,
- num_textures, view);
+ cso_set_sampler_views(device->cso, PIPE_SHADER_FRAGMENT, num_textures, view);
if (commit_samplers)
cso_single_sampler_done(device->cso, PIPE_SHADER_FRAGMENT);
- commit_views = FALSE;
commit_samplers = FALSE;
sampler_mask = state->vs ? state->vs->sampler_mask : 0;
state->bound_samplers_mask_vs = 0;
@@ -816,76 +788,170 @@ update_textures_and_samplers(struct NineDevice9 *device)
* unbind dummy sampler directly when they are not needed
* anymore, but they're going to be removed as long as texture
* or sampler states are changed. */
- view[i] = device->dummy_sampler;
+ view[i] = device->dummy_sampler_view;
num_textures = i + 1;
- memset(&samp, 0, sizeof(samp));
- samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
- samp.max_lod = 15.0f;
- samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- samp.min_img_filter = PIPE_TEX_FILTER_NEAREST;
- samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
- samp.compare_mode = PIPE_TEX_COMPARE_NONE;
- samp.compare_func = PIPE_FUNC_LEQUAL;
- samp.normalized_coords = 1;
- samp.seamless_cube_map = 1;
-
cso_single_sampler(device->cso, PIPE_SHADER_VERTEX,
- s - NINE_SAMPLER_VS(0), &samp);
+ s - NINE_SAMPLER_VS(0), &device->dummy_sampler_state);
- commit_views = TRUE;
commit_samplers = TRUE;
state->changed.sampler[s] = ~0;
}
state->bound_samplers_mask_vs |= (1 << s);
}
- commit_views |= (state->changed.texture & NINE_VS_SAMPLERS_MASK) != 0;
- commit_views |= state->changed.srgb;
- if (commit_views)
- pipe->set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0,
- num_textures, view);
+
+ cso_set_sampler_views(device->cso, PIPE_SHADER_VERTEX, num_textures, view);
if (commit_samplers)
cso_single_sampler_done(device->cso, PIPE_SHADER_VERTEX);
- state->changed.srgb = FALSE;
state->changed.texture = 0;
}
+/* State commit only */
+
+static inline void
+commit_blend(struct NineDevice9 *device)
+{
+ cso_set_blend(device->cso, &device->state.pipe.blend);
+}
+
+static inline void
+commit_dsa(struct NineDevice9 *device)
+{
+ cso_set_depth_stencil_alpha(device->cso, &device->state.pipe.dsa);
+}
+
+static inline void
+commit_scissor(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+
+ pipe->set_scissor_states(pipe, 0, 1, &device->state.scissor);
+}
+
+static inline void
+commit_rasterizer(struct NineDevice9 *device)
+{
+ cso_set_rasterizer(device->cso, &device->state.pipe.rast);
+}
-#define NINE_STATE_FREQ_GROUP_0 \
- (NINE_STATE_FB | \
- NINE_STATE_VIEWPORT | \
- NINE_STATE_SCISSOR | \
- NINE_STATE_BLEND | \
- NINE_STATE_DSA | \
- NINE_STATE_RASTERIZER | \
- NINE_STATE_VS | \
- NINE_STATE_PS | \
- NINE_STATE_BLEND_COLOR | \
- NINE_STATE_STENCIL_REF | \
+static inline void
+commit_index_buffer(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+ if (device->state.idxbuf)
+ pipe->set_index_buffer(pipe, &device->state.idxbuf->buffer);
+ else
+ pipe->set_index_buffer(pipe, NULL);
+}
+
+static inline void
+commit_vs_constants(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+
+ if (unlikely(!device->state.vs))
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &device->state.pipe.cb_vs_ff);
+ else
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &device->state.pipe.cb_vs);
+}
+
+static inline void
+commit_ps_constants(struct NineDevice9 *device)
+{
+ struct pipe_context *pipe = device->pipe;
+
+ if (unlikely(!device->state.ps))
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &device->state.pipe.cb_ps_ff);
+ else
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &device->state.pipe.cb_ps);
+}
+
+static inline void
+commit_vs(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+
+ device->pipe->bind_vs_state(device->pipe, state->cso.vs);
+}
+
+
+static inline void
+commit_ps(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+
+ device->pipe->bind_fs_state(device->pipe, state->cso.ps);
+}
+/* State Update */
+
+#define NINE_STATE_SHADER_CHANGE_VS \
+ (NINE_STATE_VS | \
+ NINE_STATE_TEXTURE | \
+ NINE_STATE_FOG_SHADER)
+
+#define NINE_STATE_SHADER_CHANGE_PS \
+ (NINE_STATE_PS | \
+ NINE_STATE_TEXTURE | \
+ NINE_STATE_FOG_SHADER | \
+ NINE_STATE_PS1X_SHADER)
+
+#define NINE_STATE_FREQUENT \
+ (NINE_STATE_RASTERIZER | \
+ NINE_STATE_TEXTURE | \
+ NINE_STATE_SAMPLER | \
+ NINE_STATE_VS_CONST | \
+ NINE_STATE_PS_CONST)
+
+#define NINE_STATE_COMMON \
+ (NINE_STATE_FB | \
+ NINE_STATE_BLEND | \
+ NINE_STATE_DSA | \
+ NINE_STATE_VIEWPORT | \
+ NINE_STATE_VDECL | \
+ NINE_STATE_IDXBUF)
+
+#define NINE_STATE_RARE \
+ (NINE_STATE_SCISSOR | \
+ NINE_STATE_BLEND_COLOR | \
+ NINE_STATE_STENCIL_REF | \
NINE_STATE_SAMPLE_MASK)
-#define NINE_STATE_FREQ_GROUP_1 ~NINE_STATE_FREQ_GROUP_0
-#define NINE_STATE_SHADER_VARIANT_GROUP \
- (NINE_STATE_TEXTURE | \
- NINE_STATE_VS | \
- NINE_STATE_PS)
+/* TODO: only go through dirty textures */
+static void
+validate_textures(struct NineDevice9 *device)
+{
+ struct NineBaseTexture9 *tex, *ptr;
+ LIST_FOR_EACH_ENTRY_SAFE(tex, ptr, &device->update_textures, list) {
+ list_delinit(&tex->list);
+ NineBaseTexture9_Validate(tex);
+ }
+}
+
+void
+nine_update_state_framebuffer(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+
+ validate_textures(device);
+
+ if (state->changed.group & NINE_STATE_FB)
+ update_framebuffer(device);
+
+ state->changed.group &= ~NINE_STATE_FB;
+}
boolean
-nine_update_state(struct NineDevice9 *device, uint32_t mask)
+nine_update_state(struct NineDevice9 *device)
{
struct pipe_context *pipe = device->pipe;
struct nine_state *state = &device->state;
uint32_t group;
- DBG("changed state groups: %x | %x\n",
- state->changed.group & NINE_STATE_FREQ_GROUP_0,
- state->changed.group & NINE_STATE_FREQ_GROUP_1);
+ DBG("changed state groups: %x\n", state->changed.group);
/* NOTE: We may want to use the cso cache for everything, or let
* NineDevice9.RestoreNonCSOState actually set the states, then we wouldn't
@@ -896,35 +962,79 @@ nine_update_state(struct NineDevice9 *device, uint32_t mask)
validate_textures(device); /* may clobber state */
/* ff_update may change VS/PS dirty bits */
- if ((mask & NINE_STATE_FF) && unlikely(!state->vs || !state->ps))
+ if (unlikely(!state->vs || !state->ps))
nine_ff_update(device);
- group = state->changed.group & mask;
+ group = state->changed.group;
- if (group & NINE_STATE_SHADER_VARIANT_GROUP)
- group |= update_shader_variant_keys(device);
+ if (group & (NINE_STATE_SHADER_CHANGE_VS | NINE_STATE_SHADER_CHANGE_PS)) {
+ if (group & NINE_STATE_SHADER_CHANGE_VS)
+ group |= prepare_vs(device, (group & NINE_STATE_VS) != 0); /* may set NINE_STATE_RASTERIZER and NINE_STATE_SAMPLER*/
+ if (group & NINE_STATE_SHADER_CHANGE_PS)
+ group |= prepare_ps(device, (group & NINE_STATE_PS) != 0);
+ }
- if (group & NINE_STATE_FREQ_GROUP_0) {
+ if (group & (NINE_STATE_COMMON | NINE_STATE_VS)) {
if (group & NINE_STATE_FB)
- group = update_framebuffer(device) & mask;
+ group |= update_framebuffer(device); /* may set NINE_STATE_RASTERIZER */
+ if (group & NINE_STATE_BLEND)
+ prepare_blend(device);
+ if (group & NINE_STATE_DSA)
+ prepare_dsa(device);
if (group & NINE_STATE_VIEWPORT)
update_viewport(device);
- if (group & NINE_STATE_SCISSOR)
- update_scissor(device);
-
- if (group & NINE_STATE_DSA)
- update_dsa(device);
- if (group & NINE_STATE_BLEND)
- update_blend(device);
-
- if (group & NINE_STATE_VS)
- group |= update_vs(device);
+ if ((group & (NINE_STATE_VDECL | NINE_STATE_VS)) ||
+ state->changed.stream_freq & ~1)
+ update_vertex_elements(device);
+ if (group & NINE_STATE_IDXBUF)
+ commit_index_buffer(device);
+ }
+ if (likely(group & (NINE_STATE_FREQUENT | NINE_STATE_VS | NINE_STATE_PS))) {
if (group & NINE_STATE_RASTERIZER)
- update_rasterizer(device);
+ prepare_rasterizer(device);
+ if (group & (NINE_STATE_TEXTURE | NINE_STATE_SAMPLER))
+ update_textures_and_samplers(device);
+ if (device->prefer_user_constbuf) {
+ if ((group & (NINE_STATE_VS_CONST | NINE_STATE_VS)) && state->vs)
+ prepare_vs_constants_userbuf(device);
+ if ((group & (NINE_STATE_PS_CONST | NINE_STATE_PS)) && state->ps)
+ prepare_ps_constants_userbuf(device);
+ } else {
+ if ((group & NINE_STATE_VS_CONST) && state->vs)
+ upload_constants(device, PIPE_SHADER_VERTEX);
+ if ((group & NINE_STATE_PS_CONST) && state->ps)
+ upload_constants(device, PIPE_SHADER_FRAGMENT);
+ }
+ }
- if (group & NINE_STATE_PS)
- group |= update_ps(device);
+ if (state->changed.vtxbuf)
+ update_vertex_buffers(device);
+
+ if (state->commit & NINE_STATE_COMMIT_BLEND)
+ commit_blend(device);
+ if (state->commit & NINE_STATE_COMMIT_DSA)
+ commit_dsa(device);
+ if (state->commit & NINE_STATE_COMMIT_RASTERIZER)
+ commit_rasterizer(device);
+ if (state->commit & NINE_STATE_COMMIT_CONST_VS)
+ commit_vs_constants(device);
+ if (state->commit & NINE_STATE_COMMIT_CONST_PS)
+ commit_ps_constants(device);
+ if (state->commit & NINE_STATE_COMMIT_VS)
+ commit_vs(device);
+ if (state->commit & NINE_STATE_COMMIT_PS)
+ commit_ps(device);
+
+ state->commit = 0;
+
+ if (unlikely(state->changed.ucp)) {
+ pipe->set_clip_state(pipe, &state->clip);
+ state->changed.ucp = 0;
+ }
+ if (unlikely(group & NINE_STATE_RARE)) {
+ if (group & NINE_STATE_SCISSOR)
+ commit_scissor(device);
if (group & NINE_STATE_BLEND_COLOR) {
struct pipe_blend_color color;
d3dcolor_to_rgba(&color.color[0], state->rs[D3DRS_BLENDFACTOR]);
@@ -941,38 +1051,7 @@ nine_update_state(struct NineDevice9 *device, uint32_t mask)
}
}
- if (state->changed.ucp) {
- pipe->set_clip_state(pipe, &state->clip);
- state->changed.ucp = 0;
- }
-
- if (group & (NINE_STATE_FREQ_GROUP_1 | NINE_STATE_VS)) {
- if (group & (NINE_STATE_TEXTURE | NINE_STATE_SAMPLER))
- update_textures_and_samplers(device);
-
- if (group & NINE_STATE_IDXBUF)
- update_index_buffer(device);
-
- if ((group & (NINE_STATE_VDECL | NINE_STATE_VS)) ||
- state->changed.stream_freq & ~1)
- update_vertex_elements(device);
-
- if (device->prefer_user_constbuf) {
- if ((group & (NINE_STATE_VS_CONST | NINE_STATE_VS)) && state->vs)
- update_vs_constants_userbuf(device);
- if ((group & (NINE_STATE_PS_CONST | NINE_STATE_PS)) && state->ps)
- update_ps_constants_userbuf(device);
- } else {
- if ((group & NINE_STATE_VS_CONST) && state->vs)
- update_constants(device, PIPE_SHADER_VERTEX);
- if ((group & NINE_STATE_PS_CONST) && state->ps)
- update_constants(device, PIPE_SHADER_FRAGMENT);
- }
- }
- if (state->changed.vtxbuf)
- update_vertex_buffers(device);
-
- device->state.changed.group &= ~mask |
+ device->state.changed.group &=
(NINE_STATE_FF | NINE_STATE_VS_CONST | NINE_STATE_PS_CONST);
DBG("finished\n");
@@ -980,6 +1059,7 @@ nine_update_state(struct NineDevice9 *device, uint32_t mask)
return TRUE;
}
+/* State defaults */
static const DWORD nine_render_state_defaults[NINED3DRS_LAST + 1] =
{
@@ -1134,6 +1214,18 @@ static const DWORD nine_samp_state_defaults[NINED3DSAMP_LAST + 1] =
[NINED3DSAMP_MINLOD] = 0,
[NINED3DSAMP_SHADOW] = 0
};
+
+void nine_state_restore_non_cso(struct NineDevice9 *device)
+{
+ struct nine_state *state = &device->state;
+
+ state->changed.group = NINE_STATE_ALL;
+ state->changed.vtxbuf = (1ULL << device->caps.MaxStreams) - 1;
+ state->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
+ state->changed.texture = NINE_PS_SAMPLERS_MASK | NINE_VS_SAMPLERS_MASK;
+ state->commit |= NINE_STATE_COMMIT_CONST_VS | NINE_STATE_COMMIT_CONST_PS;
+}
+
void
nine_state_set_defaults(struct NineDevice9 *device, const D3DCAPS9 *caps,
boolean is_reset)
@@ -1152,6 +1244,7 @@ nine_state_set_defaults(struct NineDevice9 *device, const D3DCAPS9 *caps,
}
state->ff.tex_stage[0][D3DTSS_COLOROP] = D3DTOP_MODULATE;
state->ff.tex_stage[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1;
+ memset(&state->bumpmap_vars, 0, sizeof(state->bumpmap_vars));
for (s = 0; s < Elements(state->samp); ++s) {
memcpy(&state->samp[s], nine_samp_state_defaults,
@@ -1170,6 +1263,9 @@ nine_state_set_defaults(struct NineDevice9 *device, const D3DCAPS9 *caps,
/* Set changed flags to initialize driver.
*/
state->changed.group = NINE_STATE_ALL;
+ state->changed.vtxbuf = (1ULL << device->caps.MaxStreams) - 1;
+ state->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
+ state->changed.texture = NINE_PS_SAMPLERS_MASK | NINE_VS_SAMPLERS_MASK;
state->ff.changed.transform[0] = ~0;
state->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32);
@@ -1186,6 +1282,23 @@ nine_state_set_defaults(struct NineDevice9 *device, const D3DCAPS9 *caps,
state->dummy_vbo_bound_at = -1;
state->vbo_bound_done = FALSE;
}
+
+ if (!device->prefer_user_constbuf) {
+ /* fill cb_vs and cb_ps for the non user constbuf path */
+ struct pipe_constant_buffer cb;
+
+ cb.buffer_offset = 0;
+ cb.buffer_size = device->vs_const_size;
+ cb.buffer = device->constbuf_vs;
+ cb.user_buffer = NULL;
+ state->pipe.cb_vs = cb;
+
+ cb.buffer_size = device->ps_const_size;
+ cb.buffer = device->constbuf_ps;
+ state->pipe.cb_ps = cb;
+
+ state->commit |= NINE_STATE_COMMIT_CONST_VS | NINE_STATE_COMMIT_CONST_PS;
+ }
}
void
@@ -1353,15 +1466,15 @@ const uint32_t nine_render_state_group[NINED3DRS_LAST + 1] =
[D3DRS_ZFUNC] = NINE_STATE_DSA,
[D3DRS_ALPHAREF] = NINE_STATE_DSA,
[D3DRS_ALPHAFUNC] = NINE_STATE_DSA,
- [D3DRS_DITHERENABLE] = NINE_STATE_RASTERIZER,
+ [D3DRS_DITHERENABLE] = NINE_STATE_BLEND,
[D3DRS_ALPHABLENDENABLE] = NINE_STATE_BLEND,
- [D3DRS_FOGENABLE] = NINE_STATE_FF_OTHER,
+ [D3DRS_FOGENABLE] = NINE_STATE_FF_OTHER | NINE_STATE_FOG_SHADER | NINE_STATE_PS_CONST,
[D3DRS_SPECULARENABLE] = NINE_STATE_FF_LIGHTING,
- [D3DRS_FOGCOLOR] = NINE_STATE_FF_OTHER,
- [D3DRS_FOGTABLEMODE] = NINE_STATE_FF_OTHER,
- [D3DRS_FOGSTART] = NINE_STATE_FF_OTHER,
- [D3DRS_FOGEND] = NINE_STATE_FF_OTHER,
- [D3DRS_FOGDENSITY] = NINE_STATE_FF_OTHER,
+ [D3DRS_FOGCOLOR] = NINE_STATE_FF_OTHER | NINE_STATE_PS_CONST,
+ [D3DRS_FOGTABLEMODE] = NINE_STATE_FF_OTHER | NINE_STATE_FOG_SHADER | NINE_STATE_PS_CONST,
+ [D3DRS_FOGSTART] = NINE_STATE_FF_OTHER | NINE_STATE_PS_CONST,
+ [D3DRS_FOGEND] = NINE_STATE_FF_OTHER | NINE_STATE_PS_CONST,
+ [D3DRS_FOGDENSITY] = NINE_STATE_FF_OTHER | NINE_STATE_PS_CONST,
[D3DRS_RANGEFOGENABLE] = NINE_STATE_FF_OTHER,
[D3DRS_STENCILENABLE] = NINE_STATE_DSA,
[D3DRS_STENCILFAIL] = NINE_STATE_DSA,
@@ -1394,7 +1507,7 @@ const uint32_t nine_render_state_group[NINED3DRS_LAST + 1] =
[D3DRS_VERTEXBLEND] = NINE_STATE_FF_OTHER,
[D3DRS_CLIPPLANEENABLE] = NINE_STATE_RASTERIZER,
[D3DRS_POINTSIZE] = NINE_STATE_RASTERIZER,
- [D3DRS_POINTSIZE_MIN] = NINE_STATE_MISC_CONST,
+ [D3DRS_POINTSIZE_MIN] = NINE_STATE_RASTERIZER,
[D3DRS_POINTSPRITEENABLE] = NINE_STATE_RASTERIZER,
[D3DRS_POINTSCALEENABLE] = NINE_STATE_FF_OTHER,
[D3DRS_POINTSCALE_A] = NINE_STATE_FF_OTHER,
@@ -1404,7 +1517,7 @@ const uint32_t nine_render_state_group[NINED3DRS_LAST + 1] =
[D3DRS_MULTISAMPLEMASK] = NINE_STATE_SAMPLE_MASK,
[D3DRS_PATCHEDGESTYLE] = NINE_STATE_UNHANDLED,
[D3DRS_DEBUGMONITORTOKEN] = NINE_STATE_UNHANDLED,
- [D3DRS_POINTSIZE_MAX] = NINE_STATE_MISC_CONST,
+ [D3DRS_POINTSIZE_MAX] = NINE_STATE_RASTERIZER,
[D3DRS_INDEXEDVERTEXBLENDENABLE] = NINE_STATE_FF_OTHER,
[D3DRS_COLORWRITEENABLE] = NINE_STATE_BLEND,
[D3DRS_TWEENFACTOR] = NINE_STATE_FF_OTHER,
@@ -1446,6 +1559,8 @@ const uint32_t nine_render_state_group[NINED3DRS_LAST + 1] =
[D3DRS_BLENDOPALPHA] = NINE_STATE_BLEND
};
+/* Misc */
+
D3DMATRIX *
nine_state_access_transform(struct nine_state *state, D3DTRANSFORMSTATETYPE t,
boolean alloc)
@@ -1601,4 +1716,3 @@ const char *nine_d3drs_to_string(DWORD State)
return "(invalid)";
}
}
-
diff --git a/src/gallium/state_trackers/nine/nine_state.h b/src/gallium/state_trackers/nine/nine_state.h
index 2bf3f637f93..b34da70ef48 100644
--- a/src/gallium/state_trackers/nine/nine_state.h
+++ b/src/gallium/state_trackers/nine/nine_state.h
@@ -33,8 +33,7 @@
#define NINED3DRS_VSPOINTSIZE (D3DRS_BLENDOPALPHA + 1)
#define NINED3DRS_RTMASK (D3DRS_BLENDOPALPHA + 2)
-#define NINED3DRS_ZBIASSCALE (D3DRS_BLENDOPALPHA + 3)
-#define NINED3DRS_ALPHACOVERAGE (D3DRS_BLENDOPALPHA + 4)
+#define NINED3DRS_ALPHACOVERAGE (D3DRS_BLENDOPALPHA + 3)
#define D3DRS_LAST D3DRS_BLENDOPALPHA
#define NINED3DRS_LAST NINED3DRS_ALPHACOVERAGE /* 213 */
@@ -67,17 +66,26 @@
#define NINE_STATE_BLEND_COLOR (1 << 16)
#define NINE_STATE_STENCIL_REF (1 << 17)
#define NINE_STATE_SAMPLE_MASK (1 << 18)
-#define NINE_STATE_MISC_CONST (1 << 19)
-#define NINE_STATE_FF (0x1f << 20)
-#define NINE_STATE_FF_VS (0x17 << 20)
-#define NINE_STATE_FF_PS (0x18 << 20)
-#define NINE_STATE_FF_LIGHTING (1 << 20)
-#define NINE_STATE_FF_MATERIAL (1 << 21)
-#define NINE_STATE_FF_VSTRANSF (1 << 22)
-#define NINE_STATE_FF_PSSTAGES (1 << 23)
-#define NINE_STATE_FF_OTHER (1 << 24)
-#define NINE_STATE_ALL 0x1ffffff
-#define NINE_STATE_UNHANDLED (1 << 25)
+#define NINE_STATE_FF (0x1f << 19)
+#define NINE_STATE_FF_VS (0x17 << 19)
+#define NINE_STATE_FF_PS (0x18 << 19)
+#define NINE_STATE_FF_LIGHTING (1 << 19)
+#define NINE_STATE_FF_MATERIAL (1 << 20)
+#define NINE_STATE_FF_VSTRANSF (1 << 21)
+#define NINE_STATE_FF_PSSTAGES (1 << 22)
+#define NINE_STATE_FF_OTHER (1 << 23)
+#define NINE_STATE_FOG_SHADER (1 << 24)
+#define NINE_STATE_PS1X_SHADER (1 << 25)
+#define NINE_STATE_ALL 0x3ffffff
+#define NINE_STATE_UNHANDLED (1 << 26)
+
+#define NINE_STATE_COMMIT_DSA (1 << 0)
+#define NINE_STATE_COMMIT_RASTERIZER (1 << 1)
+#define NINE_STATE_COMMIT_BLEND (1 << 2)
+#define NINE_STATE_COMMIT_CONST_VS (1 << 3)
+#define NINE_STATE_COMMIT_CONST_PS (1 << 4)
+#define NINE_STATE_COMMIT_VS (1 << 5)
+#define NINE_STATE_COMMIT_PS (1 << 6)
#define NINE_MAX_SIMULTANEOUS_RENDERTARGETS 4
@@ -94,6 +102,8 @@
NINE_MAX_CONST_I * 4 * sizeof(int))
+#define NINE_MAX_TEXTURE_STAGES 8
+
#define NINE_MAX_LIGHTS 65536
#define NINE_MAX_LIGHTS_ACTIVE 8
@@ -124,7 +134,6 @@ struct nine_state
uint16_t vs_const_b; /* NINE_MAX_CONST_B == 16 */
uint16_t ps_const_b;
uint8_t ucp;
- boolean srgb;
} changed;
struct NineSurface9 *rt[NINE_MAX_SIMULTANEOUS_RENDERTARGETS];
@@ -143,13 +152,13 @@ struct nine_state
int vs_const_i[NINE_MAX_CONST_I][4];
BOOL vs_const_b[NINE_MAX_CONST_B];
float *vs_lconstf_temp;
- uint32_t vs_key;
struct NinePixelShader9 *ps;
float *ps_const_f;
int ps_const_i[NINE_MAX_CONST_I][4];
BOOL ps_const_b[NINE_MAX_CONST_B];
- uint32_t ps_key;
+ float *ps_lconstf_temp;
+ uint32_t bumpmap_vars[6 * NINE_MAX_TEXTURE_STAGES];
struct {
void *vs;
@@ -184,13 +193,9 @@ struct nine_state
struct {
struct {
uint32_t group;
- uint32_t tex_stage[NINE_MAX_SAMPLERS][(NINED3DTSS_COUNT + 31) / 32];
+ uint32_t tex_stage[NINE_MAX_TEXTURE_STAGES][(NINED3DTSS_COUNT + 31) / 32];
uint32_t transform[(NINED3DTS_COUNT + 31) / 32];
} changed;
- struct {
- boolean vs_const;
- boolean ps_const;
- } clobber;
D3DMATRIX *transform; /* access only via nine_state_access_transform */
unsigned num_transforms;
@@ -205,8 +210,19 @@ struct nine_state
D3DMATERIAL9 material;
- DWORD tex_stage[NINE_MAX_SAMPLERS][NINED3DTSS_COUNT];
+ DWORD tex_stage[NINE_MAX_TEXTURE_STAGES][NINED3DTSS_COUNT];
} ff;
+
+ uint32_t commit;
+ struct {
+ struct pipe_depth_stencil_alpha_state dsa;
+ struct pipe_rasterizer_state rast;
+ struct pipe_blend_state blend;
+ struct pipe_constant_buffer cb_vs;
+ struct pipe_constant_buffer cb_ps;
+ struct pipe_constant_buffer cb_vs_ff;
+ struct pipe_constant_buffer cb_ps_ff;
+ } pipe;
};
/* map D3DRS -> NINE_STATE_x
@@ -220,8 +236,10 @@ extern const uint32_t nine_render_states_vertex[(NINED3DRS_COUNT + 31) / 32];
struct NineDevice9;
-boolean nine_update_state(struct NineDevice9 *, uint32_t group_mask);
+void nine_update_state_framebuffer(struct NineDevice9 *);
+boolean nine_update_state(struct NineDevice9 *);
+void nine_state_restore_non_cso(struct NineDevice9 *device);
void nine_state_set_defaults(struct NineDevice9 *, const D3DCAPS9 *,
boolean is_reset);
void nine_state_clear(struct nine_state *, const boolean device);
diff --git a/src/gallium/state_trackers/nine/pixelshader9.c b/src/gallium/state_trackers/nine/pixelshader9.c
index 3f176a312bf..42bc349c2cc 100644
--- a/src/gallium/state_trackers/nine/pixelshader9.c
+++ b/src/gallium/state_trackers/nine/pixelshader9.c
@@ -46,7 +46,7 @@ NinePixelShader9_ctor( struct NinePixelShader9 *This,
return hr;
if (cso) {
- This->variant.cso = cso;
+ This->ff_cso = cso;
return D3D_OK;
}
device = This->base.device;
@@ -57,6 +57,8 @@ NinePixelShader9_ctor( struct NinePixelShader9 *This,
info.const_b_base = NINE_CONST_B_BASE(device->max_ps_const_f) / 16;
info.sampler_mask_shadow = 0x0;
info.sampler_ps1xtypes = 0x0;
+ info.fog_enable = 0;
+ info.projected = 0;
hr = nine_translate_shader(device, &info);
if (FAILED(hr))
@@ -69,9 +71,13 @@ NinePixelShader9_ctor( struct NinePixelShader9 *This,
This->byte_code.size = info.byte_size;
This->variant.cso = info.cso;
+ This->last_cso = info.cso;
+ This->last_key = 0;
+
This->sampler_mask = info.sampler_mask;
This->rt_mask = info.rt_mask;
This->const_used_size = info.const_used_size;
+ This->bumpenvmat_needed = info.bumpenvmat_needed;
/* no constant relative addressing for ps */
assert(info.lconstf.data == NULL);
assert(info.lconstf.ranges == NULL);
@@ -82,11 +88,12 @@ NinePixelShader9_ctor( struct NinePixelShader9 *This,
void
NinePixelShader9_dtor( struct NinePixelShader9 *This )
{
- DBG("This=%p cso=%p\n", This, This->variant.cso);
+ DBG("This=%p\n", This);
if (This->base.device) {
struct pipe_context *pipe = This->base.device->pipe;
- struct nine_shader_variant *var = &This->variant;
+ struct nine_shader_variant64 *var = &This->variant;
+
do {
if (var->cso) {
if (This->base.device->state.cso.ps == var->cso)
@@ -95,8 +102,14 @@ NinePixelShader9_dtor( struct NinePixelShader9 *This )
}
var = var->next;
} while (var);
+
+ if (This->ff_cso) {
+ if (This->ff_cso == This->base.device->state.cso.ps)
+ pipe->bind_fs_state(pipe, NULL);
+ pipe->delete_fs_state(pipe, This->ff_cso);
+ }
}
- nine_shader_variants_free(&This->variant);
+ nine_shader_variants_free64(&This->variant);
FREE((void *)This->byte_code.tokens); /* const_cast */
@@ -124,10 +137,16 @@ NinePixelShader9_GetFunction( struct NinePixelShader9 *This,
}
void *
-NinePixelShader9_GetVariant( struct NinePixelShader9 *This,
- uint32_t key )
+NinePixelShader9_GetVariant( struct NinePixelShader9 *This )
{
- void *cso = nine_shader_variant_get(&This->variant, key);
+ void *cso;
+ uint64_t key;
+
+ key = This->next_key;
+ if (key == This->last_key)
+ return This->last_cso;
+
+ cso = nine_shader_variant_get64(&This->variant, key);
if (!cso) {
struct NineDevice9 *device = This->base.device;
struct nine_shader_info info;
@@ -139,13 +158,20 @@ NinePixelShader9_GetVariant( struct NinePixelShader9 *This,
info.byte_code = This->byte_code.tokens;
info.sampler_mask_shadow = key & 0xffff;
info.sampler_ps1xtypes = key;
+ info.fog_enable = device->state.rs[D3DRS_FOGENABLE];
+ info.fog_mode = device->state.rs[D3DRS_FOGTABLEMODE];
+ info.projected = (key >> 48) & 0xffff;
hr = nine_translate_shader(This->base.device, &info);
if (FAILED(hr))
return NULL;
- nine_shader_variant_add(&This->variant, key, info.cso);
+ nine_shader_variant_add64(&This->variant, key, info.cso);
cso = info.cso;
}
+
+ This->last_key = key;
+ This->last_cso = cso;
+
return cso;
}
diff --git a/src/gallium/state_trackers/nine/pixelshader9.h b/src/gallium/state_trackers/nine/pixelshader9.h
index 6dad1d1ee76..e09009f6621 100644
--- a/src/gallium/state_trackers/nine/pixelshader9.h
+++ b/src/gallium/state_trackers/nine/pixelshader9.h
@@ -25,13 +25,16 @@
#include "iunknown.h"
#include "nine_shader.h"
+#include "nine_state.h"
+#include "basetexture9.h"
+#include "nine_ff.h"
struct nine_lconstf;
struct NinePixelShader9
{
struct NineUnknown base;
- struct nine_shader_variant variant;
+ struct nine_shader_variant64 variant;
struct {
const DWORD *tokens;
@@ -41,11 +44,17 @@ struct NinePixelShader9
unsigned const_used_size; /* in bytes */
+ uint8_t bumpenvmat_needed;
uint16_t sampler_mask;
- uint16_t sampler_mask_shadow;
uint8_t rt_mask;
uint64_t ff_key[6];
+ void *ff_cso;
+
+ uint64_t last_key;
+ void *last_cso;
+
+ uint64_t next_key;
};
static inline struct NinePixelShader9 *
NinePixelShader9( void *data )
@@ -53,9 +62,49 @@ NinePixelShader9( void *data )
return (struct NinePixelShader9 *)data;
}
+static inline BOOL
+NinePixelShader9_UpdateKey( struct NinePixelShader9 *ps,
+ struct nine_state *state )
+{
+ uint16_t samplers_shadow;
+ uint32_t samplers_ps1_types;
+ uint16_t projected;
+ uint64_t key;
+ BOOL res;
+
+ if (unlikely(ps->byte_code.version < 0x20)) {
+ /* no depth textures, but variable targets */
+ uint32_t m = ps->sampler_mask;
+ samplers_ps1_types = 0;
+ while (m) {
+ int s = ffs(m) - 1;
+ m &= ~(1 << s);
+ samplers_ps1_types |= (state->texture[s] ? state->texture[s]->pstype : 1) << (s * 2);
+ }
+ key = samplers_ps1_types;
+ } else {
+ samplers_shadow = (uint16_t)((state->samplers_shadow & NINE_PS_SAMPLERS_MASK) >> NINE_SAMPLER_PS(0));
+ key = samplers_shadow & ps->sampler_mask;
+ }
+
+ if (ps->byte_code.version < 0x30) {
+ key |= ((uint64_t)state->rs[D3DRS_FOGENABLE]) << 32;
+ key |= ((uint64_t)state->rs[D3DRS_FOGTABLEMODE]) << 33;
+ }
+
+ if (unlikely(ps->byte_code.version < 0x14)) {
+ projected = nine_ff_get_projected_key(state);
+ key |= ((uint64_t) projected) << 48;
+ }
+
+ res = ps->last_key != key;
+ if (res)
+ ps->next_key = key;
+ return res;
+}
+
void *
-NinePixelShader9_GetVariant( struct NinePixelShader9 *vs,
- uint32_t key );
+NinePixelShader9_GetVariant( struct NinePixelShader9 *ps );
/*** public ***/
diff --git a/src/gallium/state_trackers/nine/resource9.c b/src/gallium/state_trackers/nine/resource9.c
index bbc8320071b..6d915338b24 100644
--- a/src/gallium/state_trackers/nine/resource9.c
+++ b/src/gallium/state_trackers/nine/resource9.c
@@ -161,20 +161,22 @@ NineResource9_GetPrivateData( struct NineResource9 *This,
DWORD *pSizeOfData )
{
struct pheader *header;
+ DWORD sizeofdata;
DBG("This=%p refguid=%p pData=%p pSizeOfData=%p\n",
This, refguid, pData, pSizeOfData);
- user_assert(pSizeOfData, E_POINTER);
-
header = util_hash_table_get(This->pdata, refguid);
if (!header) { return D3DERR_NOTFOUND; }
+ user_assert(pSizeOfData, E_POINTER);
+ sizeofdata = *pSizeOfData;
+ *pSizeOfData = header->size;
+
if (!pData) {
- *pSizeOfData = header->size;
return D3D_OK;
}
- if (*pSizeOfData < header->size) {
+ if (sizeofdata < header->size) {
return D3DERR_MOREDATA;
}
@@ -206,10 +208,13 @@ DWORD WINAPI
NineResource9_SetPriority( struct NineResource9 *This,
DWORD PriorityNew )
{
- DWORD prev = This->priority;
-
+ DWORD prev;
DBG("This=%p, PriorityNew=%d\n", This, PriorityNew);
+ if (This->pool != D3DPOOL_MANAGED || This->type == D3DRTYPE_SURFACE)
+ return 0;
+
+ prev = This->priority;
This->priority = PriorityNew;
return prev;
}
@@ -217,6 +222,9 @@ NineResource9_SetPriority( struct NineResource9 *This,
DWORD WINAPI
NineResource9_GetPriority( struct NineResource9 *This )
{
+ if (This->pool != D3DPOOL_MANAGED || This->type == D3DRTYPE_SURFACE)
+ return 0;
+
return This->priority;
}
diff --git a/src/gallium/state_trackers/nine/stateblock9.c b/src/gallium/state_trackers/nine/stateblock9.c
index 032b9ffcbf0..6d6e1be0b7f 100644
--- a/src/gallium/state_trackers/nine/stateblock9.c
+++ b/src/gallium/state_trackers/nine/stateblock9.c
@@ -251,7 +251,7 @@ nine_state_copy_common(struct nine_state *dst,
dst->ff.material = src->ff.material;
if (mask->changed.group & NINE_STATE_FF_PSSTAGES) {
- for (s = 0; s < NINE_MAX_SAMPLERS; ++s) {
+ for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) {
for (i = 0; i < NINED3DTSS_COUNT; ++i)
if (mask->ff.changed.tex_stage[s][i / 32] & (1 << (i % 32)))
dst->ff.tex_stage[s][i] = src->ff.tex_stage[s][i];
diff --git a/src/gallium/state_trackers/nine/surface9.c b/src/gallium/state_trackers/nine/surface9.c
index 7533cb3a454..14c1ce927ad 100644
--- a/src/gallium/state_trackers/nine/surface9.c
+++ b/src/gallium/state_trackers/nine/surface9.c
@@ -104,11 +104,11 @@ NineSurface9_ctor( struct NineSurface9 *This,
/* Ram buffer with no parent. Has to allocate the resource itself */
if (!pResource && !pContainer) {
assert(!user_buffer);
- This->data = MALLOC(
+ This->data = align_malloc(
nine_format_get_level_alloc_size(This->base.info.format,
pDesc->Width,
pDesc->Height,
- 0));
+ 0), 32);
if (!This->data)
return E_OUTOFMEMORY;
}
@@ -273,7 +273,7 @@ NineSurface9_AddDirtyRect( struct NineSurface9 *This,
This->texture == D3DRTYPE_CUBETEXTURE ||
This->texture == D3DRTYPE_TEXTURE);
- if (This->base.pool != D3DPOOL_MANAGED)
+ if (This->base.pool == D3DPOOL_DEFAULT)
return;
/* Add a dirty rect to level 0 of the parent texture */
@@ -287,7 +287,7 @@ NineSurface9_AddDirtyRect( struct NineSurface9 *This,
NineTexture9(This->base.base.container);
NineTexture9_AddDirtyRect(tex, &dirty_rect);
- } else { /* This->texture == D3DRTYPE_CUBETEXTURE */
+ } else if (This->texture == D3DRTYPE_CUBETEXTURE) {
struct NineCubeTexture9 *ctex =
NineCubeTexture9(This->base.base.container);
@@ -323,6 +323,13 @@ NineSurface9_LockRect( struct NineSurface9 *This,
nine_D3DLOCK_to_str(Flags));
NineSurface9_Dump(This);
+ /* check if it's already locked */
+ user_assert(This->lock_count == 0, D3DERR_INVALIDCALL);
+
+ /* set pBits to NULL after lock_count check */
+ user_assert(pLockedRect, E_POINTER);
+ pLockedRect->pBits = NULL;
+
#ifdef NINE_STRICT
user_assert(This->base.pool != D3DPOOL_DEFAULT ||
(resource && (resource->flags & NINE_RESOURCE_FLAG_LOCKABLE)),
@@ -337,19 +344,17 @@ NineSurface9_LockRect( struct NineSurface9 *This,
user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)),
D3DERR_INVALIDCALL);
- /* check if it's already locked */
- user_assert(This->lock_count == 0, D3DERR_INVALIDCALL);
- user_assert(pLockedRect, E_POINTER);
-
user_assert(This->desc.MultiSampleType == D3DMULTISAMPLE_NONE,
D3DERR_INVALIDCALL);
- if (pRect && This->base.pool == D3DPOOL_DEFAULT &&
- util_format_is_compressed(This->base.info.format)) {
+ if (pRect && This->desc.Pool == D3DPOOL_DEFAULT &&
+ compressed_format (This->desc.Format)) {
const unsigned w = util_format_get_blockwidth(This->base.info.format);
const unsigned h = util_format_get_blockheight(This->base.info.format);
- user_assert(!(pRect->left % w) && !(pRect->right % w) &&
- !(pRect->top % h) && !(pRect->bottom % h),
+ user_assert((pRect->left == 0 && pRect->right == This->desc.Width &&
+ pRect->top == 0 && pRect->bottom == This->desc.Height) ||
+ (!(pRect->left % w) && !(pRect->right % w) &&
+ !(pRect->top % h) && !(pRect->bottom % h)),
D3DERR_INVALIDCALL);
}
@@ -363,13 +368,9 @@ NineSurface9_LockRect( struct NineSurface9 *This,
usage |= PIPE_TRANSFER_DONTBLOCK;
if (pRect) {
+ /* Windows XP accepts invalid locking rectangles, Windows 7 rejects
+ * them. Use Windows XP behaviour for now. */
rect_to_pipe_box(&box, pRect);
- if (u_box_clip_2d(&box, &box, This->desc.Width,
- This->desc.Height) < 0) {
- DBG("pRect clipped by Width=%u Height=%u\n",
- This->desc.Width, This->desc.Height);
- return D3DERR_INVALIDCALL;
- }
} else {
u_box_origin_2d(This->desc.Width, This->desc.Height, &box);
}
@@ -463,140 +464,92 @@ IDirect3DSurface9Vtbl NineSurface9_vtable = {
(void *)NineSurface9_ReleaseDC
};
-HRESULT
-NineSurface9_CopySurface( struct NineSurface9 *This,
- struct NineSurface9 *From,
- const POINT *pDestPoint,
- const RECT *pSourceRect )
+/* When this function is called, we have already checked
+ * The copy regions fit the surfaces */
+void
+NineSurface9_CopyMemToDefault( struct NineSurface9 *This,
+ struct NineSurface9 *From,
+ const POINT *pDestPoint,
+ const RECT *pSourceRect )
{
struct pipe_context *pipe = This->pipe;
struct pipe_resource *r_dst = This->base.resource;
- struct pipe_resource *r_src = From->base.resource;
- struct pipe_transfer *transfer;
- struct pipe_box src_box;
struct pipe_box dst_box;
- uint8_t *p_dst;
const uint8_t *p_src;
+ int src_x, src_y, dst_x, dst_y, copy_width, copy_height;
- DBG("This=%p From=%p pDestPoint=%p pSourceRect=%p\n",
- This, From, pDestPoint, pSourceRect);
-
- assert(This->base.pool != D3DPOOL_MANAGED &&
- From->base.pool != D3DPOOL_MANAGED);
+ assert(This->base.pool == D3DPOOL_DEFAULT &&
+ From->base.pool == D3DPOOL_SYSTEMMEM);
- user_assert(This->desc.Format == From->desc.Format, D3DERR_INVALIDCALL);
+ if (pDestPoint) {
+ dst_x = pDestPoint->x;
+ dst_y = pDestPoint->y;
+ } else {
+ dst_x = 0;
+ dst_y = 0;
+ }
- dst_box.x = pDestPoint ? pDestPoint->x : 0;
- dst_box.y = pDestPoint ? pDestPoint->y : 0;
+ if (pSourceRect) {
+ src_x = pSourceRect->left;
+ src_y = pSourceRect->top;
+ copy_width = pSourceRect->right - pSourceRect->left;
+ copy_height = pSourceRect->bottom - pSourceRect->top;
+ } else {
+ src_x = 0;
+ src_y = 0;
+ copy_width = From->desc.Width;
+ copy_height = From->desc.Height;
+ }
- user_assert(dst_box.x >= 0 &&
- dst_box.y >= 0, D3DERR_INVALIDCALL);
+ u_box_2d_zslice(dst_x, dst_y, This->layer,
+ copy_width, copy_height, &dst_box);
- dst_box.z = This->layer;
- src_box.z = From->layer;
+ p_src = NineSurface9_GetSystemMemPointer(From, src_x, src_y);
- dst_box.depth = 1;
- src_box.depth = 1;
+ pipe->transfer_inline_write(pipe, r_dst, This->level,
+ 0, /* WRITE|DISCARD are implicit */
+ &dst_box, p_src, From->stride, 0);
- if (pSourceRect) {
- /* make sure it doesn't range outside the source surface */
- user_assert(pSourceRect->left >= 0 &&
- pSourceRect->right <= From->desc.Width &&
- pSourceRect->top >= 0 &&
- pSourceRect->bottom <= From->desc.Height,
- D3DERR_INVALIDCALL);
- if (rect_to_pipe_box_xy_only_clamp(&src_box, pSourceRect))
- return D3D_OK;
- } else {
- src_box.x = 0;
- src_box.y = 0;
- src_box.width = From->desc.Width;
- src_box.height = From->desc.Height;
- }
+ NineSurface9_MarkContainerDirty(This);
+}
- /* limits */
- dst_box.width = This->desc.Width - dst_box.x;
- dst_box.height = This->desc.Height - dst_box.y;
+void
+NineSurface9_CopyDefaultToMem( struct NineSurface9 *This,
+ struct NineSurface9 *From )
+{
+ struct pipe_context *pipe = This->pipe;
+ struct pipe_resource *r_src = From->base.resource;
+ struct pipe_transfer *transfer;
+ struct pipe_box src_box;
+ uint8_t *p_dst;
+ const uint8_t *p_src;
- user_assert(src_box.width <= dst_box.width &&
- src_box.height <= dst_box.height, D3DERR_INVALIDCALL);
+ assert(This->base.pool == D3DPOOL_SYSTEMMEM &&
+ From->base.pool == D3DPOOL_DEFAULT);
- dst_box.width = src_box.width;
- dst_box.height = src_box.height;
+ assert(This->desc.Width == From->desc.Width);
+ assert(This->desc.Height == From->desc.Height);
- /* check source block align for compressed textures */
- if (util_format_is_compressed(From->base.info.format) &&
- ((src_box.width != From->desc.Width) ||
- (src_box.height != From->desc.Height))) {
- const unsigned w = util_format_get_blockwidth(From->base.info.format);
- const unsigned h = util_format_get_blockheight(From->base.info.format);
- user_assert(!(src_box.width % w) &&
- !(src_box.height % h),
- D3DERR_INVALIDCALL);
- }
+ u_box_origin_2d(This->desc.Width, This->desc.Height, &src_box);
+ src_box.z = From->layer;
- /* check destination block align for compressed textures */
- if (util_format_is_compressed(This->base.info.format) &&
- ((dst_box.width != This->desc.Width) ||
- (dst_box.height != This->desc.Height) ||
- dst_box.x != 0 ||
- dst_box.y != 0)) {
- const unsigned w = util_format_get_blockwidth(This->base.info.format);
- const unsigned h = util_format_get_blockheight(This->base.info.format);
- user_assert(!(dst_box.x % w) && !(dst_box.width % w) &&
- !(dst_box.y % h) && !(dst_box.height % h),
- D3DERR_INVALIDCALL);
- }
+ p_src = pipe->transfer_map(pipe, r_src, From->level,
+ PIPE_TRANSFER_READ,
+ &src_box, &transfer);
+ p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0);
- if (r_dst && r_src) {
- pipe->resource_copy_region(pipe,
- r_dst, This->level,
- dst_box.x, dst_box.y, dst_box.z,
- r_src, From->level,
- &src_box);
- } else
- if (r_dst) {
- p_src = NineSurface9_GetSystemMemPointer(From, src_box.x, src_box.y);
-
- pipe->transfer_inline_write(pipe, r_dst, This->level,
- 0, /* WRITE|DISCARD are implicit */
- &dst_box, p_src, From->stride, 0);
- } else
- if (r_src) {
- p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0);
-
- p_src = pipe->transfer_map(pipe, r_src, From->level,
- PIPE_TRANSFER_READ,
- &src_box, &transfer);
- if (!p_src)
- return D3DERR_DRIVERINTERNALERROR;
-
- util_copy_rect(p_dst, This->base.info.format,
- This->stride, dst_box.x, dst_box.y,
- dst_box.width, dst_box.height,
- p_src,
- transfer->stride, src_box.x, src_box.y);
-
- pipe->transfer_unmap(pipe, transfer);
- } else {
- p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0);
- p_src = NineSurface9_GetSystemMemPointer(From, 0, 0);
-
- util_copy_rect(p_dst, This->base.info.format,
- This->stride, dst_box.x, dst_box.y,
- dst_box.width, dst_box.height,
- p_src,
- From->stride, src_box.x, src_box.y);
- }
+ assert (p_src && p_dst);
- if (This->base.pool == D3DPOOL_DEFAULT)
- NineSurface9_MarkContainerDirty(This);
- if (!r_dst && This->base.resource)
- NineSurface9_AddDirtyRect(This, &dst_box);
+ util_copy_rect(p_dst, This->base.info.format,
+ This->stride, 0, 0,
+ This->desc.Width, This->desc.Height,
+ p_src,
+ transfer->stride, 0, 0);
- return D3D_OK;
+ pipe->transfer_unmap(pipe, transfer);
}
+
/* Gladly, rendering to a MANAGED surface is not permitted, so we will
* never have to do the reverse, i.e. download the surface.
*/
diff --git a/src/gallium/state_trackers/nine/surface9.h b/src/gallium/state_trackers/nine/surface9.h
index 73092ab8cf5..76156ae699c 100644
--- a/src/gallium/state_trackers/nine/surface9.h
+++ b/src/gallium/state_trackers/nine/surface9.h
@@ -125,11 +125,15 @@ HRESULT
NineSurface9_UploadSelf( struct NineSurface9 *This,
const struct pipe_box *damaged );
-HRESULT
-NineSurface9_CopySurface( struct NineSurface9 *This,
- struct NineSurface9 *From,
- const POINT *pDestPoint,
- const RECT *pSourceRect );
+void
+NineSurface9_CopyMemToDefault( struct NineSurface9 *This,
+ struct NineSurface9 *From,
+ const POINT *pDestPoint,
+ const RECT *pSourceRect );
+
+void
+NineSurface9_CopyDefaultToMem( struct NineSurface9 *This,
+ struct NineSurface9 *From );
static inline boolean
NineSurface9_IsOffscreenPlain (struct NineSurface9 *This )
diff --git a/src/gallium/state_trackers/nine/swapchain9.c b/src/gallium/state_trackers/nine/swapchain9.c
index a62e6ad99d8..3f5be26fed7 100644
--- a/src/gallium/state_trackers/nine/swapchain9.c
+++ b/src/gallium/state_trackers/nine/swapchain9.c
@@ -184,7 +184,9 @@ NineSwapChain9_Resize( struct NineSwapChain9 *This,
/* Note: It is the role of the backend to fill if necessary
* BackBufferWidth and BackBufferHeight */
- ID3DPresent_SetPresentParameters(This->present, pParams, This->mode);
+ hr = ID3DPresent_SetPresentParameters(This->present, pParams, This->mode);
+ if (hr != D3D_OK)
+ return hr;
/* When we have flip behaviour, d3d9 expects we get back the screen buffer when we flip.
* Here we don't get back the initial content of the screen. To emulate the behaviour
@@ -575,9 +577,10 @@ handle_draw_cursor_and_hud( struct NineSwapChain9 *This, struct pipe_resource *r
blit.filter = PIPE_TEX_FILTER_NEAREST;
blit.scissor_enable = FALSE;
- ID3DPresent_GetCursorPos(This->present, &device->cursor.pos);
-
- /* NOTE: blit messes up when box.x + box.width < 0, fix driver */
+ /* NOTE: blit messes up when box.x + box.width < 0, fix driver
+ * NOTE2: device->cursor.pos contains coordinates relative to the screen.
+ * This happens to be also the position of the cursor when we are fullscreen.
+ * We don't use sw cursor for Windowed mode */
blit.dst.box.x = MAX2(device->cursor.pos.x, 0) - device->cursor.hotspot.x;
blit.dst.box.y = MAX2(device->cursor.pos.y, 0) - device->cursor.hotspot.y;
blit.dst.box.width = blit.src.box.width;
@@ -587,13 +590,14 @@ handle_draw_cursor_and_hud( struct NineSwapChain9 *This, struct pipe_resource *r
blit.src.box.width, blit.src.box.height,
blit.dst.box.x, blit.dst.box.y);
+ blit.alpha_blend = TRUE;
This->pipe->blit(This->pipe, &blit);
}
if (device->hud && resource) {
hud_draw(device->hud, resource); /* XXX: no offset */
/* HUD doesn't clobber stipple */
- NineDevice9_RestoreNonCSOState(device, ~0x2);
+ nine_state_restore_non_cso(device);
}
}
@@ -704,6 +708,7 @@ present( struct NineSwapChain9 *This,
blit.mask = PIPE_MASK_RGBA;
blit.filter = PIPE_TEX_FILTER_NEAREST;
blit.scissor_enable = FALSE;
+ blit.alpha_blend = FALSE;
This->pipe->blit(This->pipe, &blit);
}
@@ -835,7 +840,7 @@ NineSwapChain9_Present( struct NineSwapChain9 *This,
ID3DPresent_WaitBufferReleased(This->present, This->present_handles[0]);
This->base.device->state.changed.group |= NINE_STATE_FB;
- nine_update_state(This->base.device, NINE_STATE_FB);
+ nine_update_state_framebuffer(This->base.device);
return hr;
}
@@ -856,6 +861,8 @@ NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This,
DBG("GetFrontBufferData: This=%p pDestSurface=%p\n",
This, pDestSurface);
+ user_assert(dest_surface->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
+
width = dest_surface->desc.Width;
height = dest_surface->desc.Height;
@@ -870,7 +877,7 @@ NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This,
desc.MultiSampleQuality = 0;
desc.Width = width;
desc.Height = height;
- /* NineSurface9_CopySurface needs same format. */
+ /* NineSurface9_CopyDefaultToMem needs same format. */
desc.Format = dest_surface->desc.Format;
desc.Usage = D3DUSAGE_RENDERTARGET;
hr = NineSurface9_new(pDevice, NineUnknown(This), temp_resource, NULL, 0,
@@ -883,7 +890,7 @@ NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This,
ID3DPresent_FrontBufferCopy(This->present, temp_handle);
- NineSurface9_CopySurface(dest_surface, temp_surface, NULL, NULL);
+ NineSurface9_CopyDefaultToMem(dest_surface, temp_surface);
ID3DPresent_DestroyD3DWindowBuffer(This->present, temp_handle);
NineUnknown_Destroy(NineUnknown(temp_surface));
diff --git a/src/gallium/state_trackers/nine/texture9.c b/src/gallium/state_trackers/nine/texture9.c
index 5900e76e52c..bc325c1335e 100644
--- a/src/gallium/state_trackers/nine/texture9.c
+++ b/src/gallium/state_trackers/nine/texture9.c
@@ -101,6 +101,13 @@ NineTexture9_ctor( struct NineTexture9 *This,
if (Format != D3DFMT_NULL && pf == PIPE_FORMAT_NONE)
return D3DERR_INVALIDCALL;
+ if (compressed_format(Format)) {
+ const unsigned w = util_format_get_blockwidth(pf);
+ const unsigned h = util_format_get_blockheight(pf);
+
+ user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL);
+ }
+
info->screen = screen;
info->target = PIPE_TEXTURE_2D;
info->format = pf;
@@ -152,10 +159,10 @@ NineTexture9_ctor( struct NineTexture9 *This,
* apps access sublevels of texture even if they locked only first
* level) */
level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1));
- user_buffer = MALLOC(
+ user_buffer = align_malloc(
nine_format_get_size_and_offsets(pf, level_offsets,
Width, Height,
- info->last_level));
+ info->last_level), 32);
This->managed_buffer = user_buffer;
if (!This->managed_buffer)
return E_OUTOFMEMORY;
@@ -202,6 +209,9 @@ NineTexture9_ctor( struct NineTexture9 *This,
return hr;
}
+ /* Textures start initially dirty */
+ This->dirty_rect.width = Width;
+ This->dirty_rect.height = Height;
This->dirty_rect.depth = 1; /* widht == 0 means empty, depth stays 1 */
if (pSharedHandle && !*pSharedHandle) {/* Pool == D3DPOOL_SYSTEMMEM */
@@ -219,7 +229,8 @@ NineTexture9_dtor( struct NineTexture9 *This )
if (This->surfaces) {
/* The surfaces should have 0 references and be unbound now. */
for (l = 0; l <= This->base.base.info.last_level; ++l)
- NineUnknown_Destroy(&This->surfaces[l]->base.base);
+ if (This->surfaces[l])
+ NineUnknown_Destroy(&This->surfaces[l]->base.base);
FREE(This->surfaces);
}
@@ -295,18 +306,22 @@ NineTexture9_AddDirtyRect( struct NineTexture9 *This,
pDirtyRect ? pDirtyRect->left : 0, pDirtyRect ? pDirtyRect->top : 0,
pDirtyRect ? pDirtyRect->right : 0, pDirtyRect ? pDirtyRect->bottom : 0);
- /* Tracking dirty regions on DEFAULT or SYSTEMMEM resources is pointless,
+ /* Tracking dirty regions on DEFAULT resources is pointless,
* because we always write to the final storage. Just marked it dirty in
* case we need to generate mip maps.
*/
- if (This->base.base.pool != D3DPOOL_MANAGED) {
- if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP)
+ if (This->base.base.pool == D3DPOOL_DEFAULT) {
+ if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP) {
This->base.dirty_mip = TRUE;
+ BASETEX_REGISTER_UPDATE(&This->base);
+ }
return D3D_OK;
}
- This->base.managed.dirty = TRUE;
- BASETEX_REGISTER_UPDATE(&This->base);
+ if (This->base.base.pool == D3DPOOL_MANAGED) {
+ This->base.managed.dirty = TRUE;
+ BASETEX_REGISTER_UPDATE(&This->base);
+ }
if (!pDirtyRect) {
u_box_origin_2d(This->base.base.info.width0,
diff --git a/src/gallium/state_trackers/nine/vertexshader9.c b/src/gallium/state_trackers/nine/vertexshader9.c
index bbd5ce99d9a..fdfb79a138e 100644
--- a/src/gallium/state_trackers/nine/vertexshader9.c
+++ b/src/gallium/state_trackers/nine/vertexshader9.c
@@ -48,9 +48,10 @@ NineVertexShader9_ctor( struct NineVertexShader9 *This,
return hr;
if (cso) {
- This->variant.cso = cso;
+ This->ff_cso = cso;
return D3D_OK;
}
+
device = This->base.device;
info.type = PIPE_SHADER_VERTEX;
@@ -59,6 +60,7 @@ NineVertexShader9_ctor( struct NineVertexShader9 *This,
info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16;
info.sampler_mask_shadow = 0x0;
info.sampler_ps1xtypes = 0x0;
+ info.fog_enable = 0;
hr = nine_translate_shader(device, &info);
if (FAILED(hr))
@@ -71,6 +73,9 @@ NineVertexShader9_ctor( struct NineVertexShader9 *This,
This->byte_code.size = info.byte_size;
This->variant.cso = info.cso;
+ This->last_cso = info.cso;
+ This->last_key = 0;
+
This->const_used_size = info.const_used_size;
This->lconstf = info.lconstf;
This->sampler_mask = info.sampler_mask;
@@ -87,11 +92,12 @@ NineVertexShader9_ctor( struct NineVertexShader9 *This,
void
NineVertexShader9_dtor( struct NineVertexShader9 *This )
{
- DBG("This=%p cso=%p\n", This, This->variant.cso);
+ DBG("This=%p\n", This);
if (This->base.device) {
struct pipe_context *pipe = This->base.device->pipe;
struct nine_shader_variant *var = &This->variant;
+
do {
if (var->cso) {
if (This->base.device->state.cso.vs == var->cso)
@@ -100,6 +106,12 @@ NineVertexShader9_dtor( struct NineVertexShader9 *This )
}
var = var->next;
} while (var);
+
+ if (This->ff_cso) {
+ if (This->ff_cso == This->base.device->state.cso.vs)
+ pipe->bind_vs_state(pipe, NULL);
+ pipe->delete_vs_state(pipe, This->ff_cso);
+ }
}
nine_shader_variants_free(&This->variant);
@@ -130,10 +142,16 @@ NineVertexShader9_GetFunction( struct NineVertexShader9 *This,
}
void *
-NineVertexShader9_GetVariant( struct NineVertexShader9 *This,
- uint32_t key )
+NineVertexShader9_GetVariant( struct NineVertexShader9 *This )
{
- void *cso = nine_shader_variant_get(&This->variant, key);
+ void *cso;
+ uint32_t key;
+
+ key = This->next_key;
+ if (key == This->last_key)
+ return This->last_cso;
+
+ cso = nine_shader_variant_get(&This->variant, key);
if (!cso) {
struct NineDevice9 *device = This->base.device;
struct nine_shader_info info;
@@ -144,6 +162,7 @@ NineVertexShader9_GetVariant( struct NineVertexShader9 *This,
info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16;
info.byte_code = This->byte_code.tokens;
info.sampler_mask_shadow = key & 0xf;
+ info.fog_enable = device->state.rs[D3DRS_FOGENABLE];
hr = nine_translate_shader(This->base.device, &info);
if (FAILED(hr))
@@ -151,6 +170,10 @@ NineVertexShader9_GetVariant( struct NineVertexShader9 *This,
nine_shader_variant_add(&This->variant, key, info.cso);
cso = info.cso;
}
+
+ This->last_key = key;
+ This->last_cso = cso;
+
return cso;
}
diff --git a/src/gallium/state_trackers/nine/vertexshader9.h b/src/gallium/state_trackers/nine/vertexshader9.h
index 66c602c7b3c..15c3f4ff041 100644
--- a/src/gallium/state_trackers/nine/vertexshader9.h
+++ b/src/gallium/state_trackers/nine/vertexshader9.h
@@ -25,6 +25,7 @@
#include "iunknown.h"
#include "nine_shader.h"
+#include "nine_state.h"
struct NineVertexShader9
{
@@ -43,7 +44,6 @@ struct NineVertexShader9
} byte_code;
uint8_t sampler_mask;
- uint8_t sampler_mask_shadow;
boolean position_t; /* if true, disable vport transform */
boolean point_size; /* if true, set rasterizer.point_size_per_vertex to 1 */
@@ -54,7 +54,13 @@ struct NineVertexShader9
const struct pipe_stream_output_info *so;
- uint64_t ff_key[2];
+ uint64_t ff_key[3];
+ void *ff_cso;
+
+ uint32_t last_key;
+ void *last_cso;
+
+ uint32_t next_key;
};
static inline struct NineVertexShader9 *
NineVertexShader9( void *data )
@@ -62,9 +68,29 @@ NineVertexShader9( void *data )
return (struct NineVertexShader9 *)data;
}
+static inline BOOL
+NineVertexShader9_UpdateKey( struct NineVertexShader9 *vs,
+ struct nine_state *state )
+{
+ uint8_t samplers_shadow;
+ uint32_t key;
+ BOOL res;
+
+ samplers_shadow = (uint8_t)((state->samplers_shadow & NINE_VS_SAMPLERS_MASK) >> NINE_SAMPLER_VS(0));
+ samplers_shadow &= vs->sampler_mask;
+ key = samplers_shadow;
+
+ if (vs->byte_code.version < 0x30)
+ key |= state->rs[D3DRS_FOGENABLE] << 8;
+
+ res = vs->last_key != key;
+ if (res)
+ vs->next_key = key;
+ return res;
+}
+
void *
-NineVertexShader9_GetVariant( struct NineVertexShader9 *vs,
- uint32_t key );
+NineVertexShader9_GetVariant( struct NineVertexShader9 *vs );
/*** public ***/
diff --git a/src/gallium/state_trackers/nine/volume9.c b/src/gallium/state_trackers/nine/volume9.c
index 4dfc5599a8e..0b9005685a9 100644
--- a/src/gallium/state_trackers/nine/volume9.c
+++ b/src/gallium/state_trackers/nine/volume9.c
@@ -23,6 +23,7 @@
#include "device9.h"
#include "volume9.h"
#include "basetexture9.h" /* for marking dirty */
+#include "volumetexture9.h"
#include "nine_helpers.h"
#include "nine_pipe.h"
#include "nine_dump.h"
@@ -43,7 +44,7 @@ NineVolume9_AllocateData( struct NineVolume9 *This )
DBG("(%p(This=%p),level=%u) Allocating 0x%x bytes of system memory.\n",
This->base.container, This, This->level, size);
- This->data = (uint8_t *)MALLOC(size);
+ This->data = (uint8_t *)align_malloc(size, 32);
if (!This->data)
return E_OUTOFMEMORY;
return D3D_OK;
@@ -182,47 +183,23 @@ NineVolume9_GetDesc( struct NineVolume9 *This,
return D3D_OK;
}
-static inline boolean
-NineVolume9_IsDirty(struct NineVolume9 *This)
-{
- return This->dirty_box[0].width != 0;
-}
-
inline void
NineVolume9_AddDirtyRegion( struct NineVolume9 *This,
const struct pipe_box *box )
{
- struct pipe_box cover_a, cover_b;
- float vol[2];
+ D3DBOX dirty_region;
+ struct NineVolumeTexture9 *tex = NineVolumeTexture9(This->base.container);
if (!box) {
- u_box_3d(0, 0, 0, This->desc.Width, This->desc.Height,
- This->desc.Depth, &This->dirty_box[0]);
- memset(&This->dirty_box[1], 0, sizeof(This->dirty_box[1]));
- return;
- }
- if (!This->dirty_box[0].width) {
- This->dirty_box[0] = *box;
- return;
- }
-
- u_box_union_3d(&cover_a, &This->dirty_box[0], box);
- vol[0] = u_box_volume_3d(&cover_a);
-
- if (This->dirty_box[1].width == 0) {
- vol[1] = u_box_volume_3d(&This->dirty_box[0]);
- if (vol[0] > (vol[1] * 1.5f))
- This->dirty_box[1] = *box;
- else
- This->dirty_box[0] = cover_a;
+ NineVolumeTexture9_AddDirtyBox(tex, NULL);
} else {
- u_box_union_3d(&cover_b, &This->dirty_box[1], box);
- vol[1] = u_box_volume_3d(&cover_b);
-
- if (vol[0] > vol[1])
- This->dirty_box[1] = cover_b;
- else
- This->dirty_box[0] = cover_a;
+ dirty_region.Left = box->x << This->level_actual;
+ dirty_region.Top = box->y << This->level_actual;
+ dirty_region.Front = box->z << This->level_actual;
+ dirty_region.Right = dirty_region.Left + (box->width << This->level_actual);
+ dirty_region.Bottom = dirty_region.Top + (box->height << This->level_actual);
+ dirty_region.Back = dirty_region.Front + (box->depth << This->level_actual);
+ NineVolumeTexture9_AddDirtyBox(tex, &dirty_region);
}
}
@@ -254,21 +231,26 @@ NineVolume9_LockBox( struct NineVolume9 *This,
pBox ? pBox->Front : 0, pBox ? pBox->Back : 0,
nine_D3DLOCK_to_str(Flags));
+ /* check if it's already locked */
+ user_assert(This->lock_count == 0, D3DERR_INVALIDCALL);
+
+ /* set pBits to NULL after lock_count check */
+ user_assert(pLockedVolume, E_POINTER);
+ pLockedVolume->pBits = NULL;
+
user_assert(This->desc.Pool != D3DPOOL_DEFAULT ||
(This->desc.Usage & D3DUSAGE_DYNAMIC), D3DERR_INVALIDCALL);
user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)),
D3DERR_INVALIDCALL);
- user_assert(This->lock_count == 0, D3DERR_INVALIDCALL);
- user_assert(pLockedVolume, E_POINTER);
-
- if (pBox && This->desc.Pool == D3DPOOL_DEFAULT &&
- util_format_is_compressed(This->info.format)) {
+ if (pBox && compressed_format (This->desc.Format)) { /* For volume all pools are checked */
const unsigned w = util_format_get_blockwidth(This->info.format);
const unsigned h = util_format_get_blockheight(This->info.format);
- user_assert(!(pBox->Left % w) && !(pBox->Right % w) &&
- !(pBox->Top % h) && !(pBox->Bottom % h),
+ user_assert((pBox->Left == 0 && pBox->Right == This->desc.Width &&
+ pBox->Top == 0 && pBox->Bottom == This->desc.Height) ||
+ (!(pBox->Left % w) && !(pBox->Right % w) &&
+ !(pBox->Top % h) && !(pBox->Bottom % h)),
D3DERR_INVALIDCALL);
}
@@ -312,8 +294,7 @@ NineVolume9_LockBox( struct NineVolume9 *This,
if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) {
NineVolume9_MarkContainerDirty(This);
- if (This->desc.Pool == D3DPOOL_MANAGED)
- NineVolume9_AddDirtyRegion(This, &box);
+ NineVolume9_AddDirtyRegion(This, &box);
}
++This->lock_count;
@@ -333,42 +314,31 @@ NineVolume9_UnlockBox( struct NineVolume9 *This )
return D3D_OK;
}
-
+/* When this function is called, we have already checked
+ * The copy regions fit the volumes */
HRESULT
-NineVolume9_CopyVolume( struct NineVolume9 *This,
- struct NineVolume9 *From,
- unsigned dstx, unsigned dsty, unsigned dstz,
- struct pipe_box *pSrcBox )
+NineVolume9_CopyMemToDefault( struct NineVolume9 *This,
+ struct NineVolume9 *From,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_box *pSrcBox )
{
struct pipe_context *pipe = This->pipe;
struct pipe_resource *r_dst = This->resource;
- struct pipe_resource *r_src = From->resource;
- struct pipe_transfer *transfer;
struct pipe_box src_box;
struct pipe_box dst_box;
- uint8_t *p_dst;
const uint8_t *p_src;
DBG("This=%p From=%p dstx=%u dsty=%u dstz=%u pSrcBox=%p\n",
This, From, dstx, dsty, dstz, pSrcBox);
- assert(This->desc.Pool != D3DPOOL_MANAGED &&
- From->desc.Pool != D3DPOOL_MANAGED);
- user_assert(This->desc.Format == From->desc.Format, D3DERR_INVALIDCALL);
+ assert(This->desc.Pool == D3DPOOL_DEFAULT &&
+ From->desc.Pool == D3DPOOL_SYSTEMMEM);
dst_box.x = dstx;
dst_box.y = dsty;
dst_box.z = dstz;
if (pSrcBox) {
- /* make sure it doesn't range outside the source volume */
- user_assert(pSrcBox->x >= 0 &&
- (pSrcBox->width - pSrcBox->x) <= From->desc.Width &&
- pSrcBox->y >= 0 &&
- (pSrcBox->height - pSrcBox->y) <= From->desc.Height &&
- pSrcBox->z >= 0 &&
- (pSrcBox->depth - pSrcBox->z) <= From->desc.Depth,
- D3DERR_INVALIDCALL);
src_box = *pSrcBox;
} else {
src_box.x = 0;
@@ -378,101 +348,54 @@ NineVolume9_CopyVolume( struct NineVolume9 *This,
src_box.height = From->desc.Height;
src_box.depth = From->desc.Depth;
}
- /* limits */
- dst_box.width = This->desc.Width - dst_box.x;
- dst_box.height = This->desc.Height - dst_box.y;
- dst_box.depth = This->desc.Depth - dst_box.z;
-
- user_assert(src_box.width <= dst_box.width &&
- src_box.height <= dst_box.height &&
- src_box.depth <= dst_box.depth, D3DERR_INVALIDCALL);
dst_box.width = src_box.width;
dst_box.height = src_box.height;
dst_box.depth = src_box.depth;
- if (r_dst && r_src) {
- pipe->resource_copy_region(pipe,
- r_dst, This->level,
- dst_box.x, dst_box.y, dst_box.z,
- r_src, From->level,
- &src_box);
- } else
- if (r_dst) {
- p_src = NineVolume9_GetSystemMemPointer(From,
- src_box.x, src_box.y, src_box.z);
-
- pipe->transfer_inline_write(pipe, r_dst, This->level,
- 0, /* WRITE|DISCARD are implicit */
- &dst_box, p_src,
- From->stride, From->layer_stride);
- } else
- if (r_src) {
- p_dst = NineVolume9_GetSystemMemPointer(This, 0, 0, 0);
- p_src = pipe->transfer_map(pipe, r_src, From->level,
- PIPE_TRANSFER_READ,
- &src_box, &transfer);
- if (!p_src)
- return D3DERR_DRIVERINTERNALERROR;
-
- util_copy_box(p_dst, This->info.format,
- This->stride, This->layer_stride,
- dst_box.x, dst_box.y, dst_box.z,
- dst_box.width, dst_box.height, dst_box.depth,
- p_src,
- transfer->stride, transfer->layer_stride,
- src_box.x, src_box.y, src_box.z);
+ p_src = NineVolume9_GetSystemMemPointer(From,
+ src_box.x, src_box.y, src_box.z);
- pipe->transfer_unmap(pipe, transfer);
- } else {
- p_dst = NineVolume9_GetSystemMemPointer(This, 0, 0, 0);
- p_src = NineVolume9_GetSystemMemPointer(From, 0, 0, 0);
-
- util_copy_box(p_dst, This->info.format,
- This->stride, This->layer_stride,
- dst_box.x, dst_box.y, dst_box.z,
- dst_box.width, dst_box.height, dst_box.depth,
- p_src,
- From->stride, From->layer_stride,
- src_box.x, src_box.y, src_box.z);
- }
+ pipe->transfer_inline_write(pipe, r_dst, This->level,
+ 0, /* WRITE|DISCARD are implicit */
+ &dst_box, p_src,
+ From->stride, From->layer_stride);
- if (This->desc.Pool == D3DPOOL_DEFAULT)
- NineVolume9_MarkContainerDirty(This);
- if (!r_dst && This->resource)
- NineVolume9_AddDirtyRegion(This, &dst_box);
+ NineVolume9_MarkContainerDirty(This);
return D3D_OK;
}
HRESULT
-NineVolume9_UploadSelf( struct NineVolume9 *This )
+NineVolume9_UploadSelf( struct NineVolume9 *This,
+ const struct pipe_box *damaged )
{
struct pipe_context *pipe = This->pipe;
struct pipe_resource *res = This->resource;
+ struct pipe_box box;
uint8_t *ptr;
- unsigned i;
- DBG("This=%p dirty=%i data=%p res=%p\n", This, NineVolume9_IsDirty(This),
+ DBG("This=%p damaged=%p data=%p res=%p\n", This, damaged,
This->data, res);
assert(This->desc.Pool == D3DPOOL_MANAGED);
-
- if (!NineVolume9_IsDirty(This))
- return D3D_OK;
assert(res);
- for (i = 0; i < Elements(This->dirty_box); ++i) {
- const struct pipe_box *box = &This->dirty_box[i];
- if (box->width == 0)
- break;
- ptr = NineVolume9_GetSystemMemPointer(This, box->x, box->y, box->z);
-
- pipe->transfer_inline_write(pipe, res, This->level,
- 0,
- box, ptr, This->stride, This->layer_stride);
+ if (damaged) {
+ box = *damaged;
+ } else {
+ box.x = 0;
+ box.y = 0;
+ box.z = 0;
+ box.width = This->desc.Width;
+ box.height = This->desc.Height;
+ box.depth = This->desc.Depth;
}
- NineVolume9_ClearDirtyRegion(This);
+
+ ptr = NineVolume9_GetSystemMemPointer(This, box.x, box.y, box.z);
+
+ pipe->transfer_inline_write(pipe, res, This->level, 0, &box,
+ ptr, This->stride, This->layer_stride);
return D3D_OK;
}
diff --git a/src/gallium/state_trackers/nine/volume9.h b/src/gallium/state_trackers/nine/volume9.h
index fae24310a50..26ca8a32605 100644
--- a/src/gallium/state_trackers/nine/volume9.h
+++ b/src/gallium/state_trackers/nine/volume9.h
@@ -50,8 +50,6 @@ struct NineVolume9
struct pipe_transfer *transfer;
unsigned lock_count;
- struct pipe_box dirty_box[2];
-
struct pipe_context *pipe;
/* for [GS]etPrivateData/FreePrivateData */
@@ -85,20 +83,15 @@ void
NineVolume9_AddDirtyRegion( struct NineVolume9 *This,
const struct pipe_box *box );
-static inline void
-NineVolume9_ClearDirtyRegion( struct NineVolume9 *This )
-{
- memset(&This->dirty_box, 0, sizeof(This->dirty_box));
-}
-
HRESULT
-NineVolume9_CopyVolume( struct NineVolume9 *This,
- struct NineVolume9 *From,
- unsigned dstx, unsigned dsty, unsigned dstz,
- struct pipe_box *pSrcBox );
+NineVolume9_CopyMemToDefault( struct NineVolume9 *This,
+ struct NineVolume9 *From,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_box *pSrcBox );
HRESULT
-NineVolume9_UploadSelf( struct NineVolume9 *This );
+NineVolume9_UploadSelf( struct NineVolume9 *This,
+ const struct pipe_box *damaged );
/*** Direct3D public ***/
diff --git a/src/gallium/state_trackers/nine/volumetexture9.c b/src/gallium/state_trackers/nine/volumetexture9.c
index 1193e12f34c..e5b2b53148d 100644
--- a/src/gallium/state_trackers/nine/volumetexture9.c
+++ b/src/gallium/state_trackers/nine/volumetexture9.c
@@ -64,6 +64,13 @@ NineVolumeTexture9_ctor( struct NineVolumeTexture9 *This,
if (Format == D3DFMT_ATI1 || Format == D3DFMT_ATI2)
return D3DERR_INVALIDCALL;
+ if (compressed_format(Format)) {
+ const unsigned w = util_format_get_blockwidth(pf);
+ const unsigned h = util_format_get_blockheight(pf);
+ /* Compressed formats are not compressed on depth component */
+ user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL);
+ }
+
info->screen = pParams->device->screen;
info->target = PIPE_TEXTURE_3D;
info->format = pf;
@@ -116,6 +123,9 @@ NineVolumeTexture9_ctor( struct NineVolumeTexture9 *This,
return hr;
}
+ /* Textures start initially dirty */
+ NineVolumeTexture9_AddDirtyBox(This, NULL);
+
return D3D_OK;
}
@@ -193,12 +203,14 @@ NineVolumeTexture9_AddDirtyBox( struct NineVolumeTexture9 *This,
{
DBG("This=%p pDirtybox=%p\n", This, pDirtyBox);
- if (This->base.base.pool != D3DPOOL_MANAGED) {
+ if (This->base.base.pool == D3DPOOL_DEFAULT) {
return D3D_OK;
}
- This->base.managed.dirty = TRUE;
- BASETEX_REGISTER_UPDATE(&This->base);
+ if (This->base.base.pool == D3DPOOL_MANAGED) {
+ This->base.managed.dirty = TRUE;
+ BASETEX_REGISTER_UPDATE(&This->base);
+ }
if (!pDirtyBox) {
This->dirty_box.x = 0;
diff --git a/src/gallium/targets/d3dadapter9/Makefile.am b/src/gallium/targets/d3dadapter9/Makefile.am
index fe5b0b11679..e26ca33a521 100644
--- a/src/gallium/targets/d3dadapter9/Makefile.am
+++ b/src/gallium/targets/d3dadapter9/Makefile.am
@@ -54,6 +54,7 @@ pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = d3d.pc
d3dadapter9_la_SOURCES = \
+ description.c \
getproc.c \
drm.c
diff --git a/src/gallium/targets/d3dadapter9/description.c b/src/gallium/targets/d3dadapter9/description.c
new file mode 100644
index 00000000000..c0a86782f8e
--- /dev/null
+++ b/src/gallium/targets/d3dadapter9/description.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2015 Patrick Rudolph <[email protected]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+#include <string.h>
+#include "adapter9.h"
+
+#define DBG_CHANNEL DBG_ADAPTER
+
+/* prototypes */
+void
+d3d_match_vendor_id( D3DADAPTER_IDENTIFIER9* drvid,
+ unsigned fallback_ven,
+ unsigned fallback_dev,
+ const char* fallback_name );
+void d3d_fill_driver_version(D3DADAPTER_IDENTIFIER9* drvid);
+void d3d_fill_cardname(D3DADAPTER_IDENTIFIER9* drvid);
+
+enum d3d_vendor_id
+{
+ HW_VENDOR_SOFTWARE = 0x0000,
+ HW_VENDOR_AMD = 0x1002,
+ HW_VENDOR_NVIDIA = 0x10de,
+ HW_VENDOR_VMWARE = 0x15ad,
+ HW_VENDOR_INTEL = 0x8086,
+};
+
+struct card_lookup_table {
+ const char *mesaname;
+ const char *d3d9name;
+}
+cards_amd[] = {
+ {"HAWAII", "AMD Radeon R9 290"},
+ {"KAVERI", "AMD Radeon(TM) R7 Graphics"},
+ {"KABINI", "AMD Radeon HD 8400 / R3 Series"},
+ {"BONAIRE", "AMD Radeon HD 8770"},
+ {"OLAND", "AMD Radeon HD 8670"},
+ {"HAINAN", "AMD Radeon HD 8600M Series"},
+ {"TAHITI", "AMD Radeon HD 7900 Series"},
+ {"PITCAIRN", "AMD Radeon HD 7800 Series"},
+ {"CAPE VERDE", "AMD Radeon HD 7700 Series"},
+ {"ARUBA", "AMD Radeon HD 7660D"},
+ {"CAYMAN", "AMD Radeon HD 6900 Series"},
+ {"BARTS", "AMD Radeon HD 6800 Series"},
+ {"TURKS", "AMD Radeon HD 6600 Series"},
+ {"SUMO2", "AMD Radeon HD 6410D"},
+ {"SUMO", "AMD Radeon HD 6550D"},
+ {"CAICOS", "AMD Radeon HD 6400 Series"},
+ {"PALM", "AMD Radeon HD 6300 series Graphics"},
+ {"HEMLOCK", "ATI Radeon HD 5900 Series"},
+ {"CYPRESS", "ATI Radeon HD 5800 Series"},
+ {"JUNIPER", "ATI Radeon HD 5700 Series"},
+ {"REDWOOD", "ATI Radeon HD 5600 Series"},
+ {"CEDAR", "ATI Radeon HD 5500 Series"},
+ {"R700", "ATI Radeon HD 4800 Series"},
+ {"RV790", "ATI Radeon HD 4800 Series"},
+ {"RV770", "ATI Radeon HD 4800 Series"},
+ {"RV740", "ATI Radeon HD 4700 Series"},
+ {"RV730", "ATI Radeon HD 4600 Series"},
+ {"RV710", "ATI Radeon HD 4350"},
+ {"RS880", "ATI Mobility Radeon HD 4200"},
+ {"RS780", "ATI Radeon HD 3200 Graphics"},
+ {"R680", "ATI Radeon HD 2900 XT"},
+ {"R600", "ATI Radeon HD 2900 XT"},
+ {"RV670", "ATI Radeon HD 2900 XT"},
+ {"RV635", "ATI Mobility Radeon HD 2600"},
+ {"RV630", "ATI Mobility Radeon HD 2600"},
+ {"RV620", "ATI Mobility Radeon HD 2350"},
+ {"RV610", "ATI Mobility Radeon HD 2350"},
+ {"R580", "ATI Radeon X1600 Series"},
+ {"R520", "ATI Radeon X1600 Series"},
+ {"RV570", "ATI Radeon X1600 Series"},
+ {"RV560", "ATI Radeon X1600 Series"},
+ {"RV535", "ATI Radeon X1600 Series"},
+ {"RV530", "ATI Radeon X1600 Series"},
+ {"RV516", "ATI Radeon X700 SE"},
+ {"RV515", "ATI Radeon X700 SE"},
+ {"R481", "ATI Radeon X700 SE"},
+ {"R480", "ATI Radeon X700 SE"},
+ {"R430", "ATI Radeon X700 SE"},
+ {"R423", "ATI Radeon X700 SE"},
+ {"R420", "ATI Radeon X700 SE"},
+ {"R410", "ATI Radeon X700 SE"},
+ {"RV410", "ATI Radeon X700 SE"},
+ {"RS740", "ATI RADEON XPRESS 200M Series"},
+ {"RS690", "ATI RADEON XPRESS 200M Series"},
+ {"RS600", "ATI RADEON XPRESS 200M Series"},
+ {"RS485", "ATI RADEON XPRESS 200M Series"},
+ {"RS482", "ATI RADEON XPRESS 200M Series"},
+ {"RS480", "ATI RADEON XPRESS 200M Series"},
+ {"RS400", "ATI RADEON XPRESS 200M Series"},
+ {"R360", "ATI Radeon 9500"},
+ {"R350", "ATI Radeon 9500"},
+ {"R300", "ATI Radeon 9500"},
+ {"RV370", "ATI Radeon 9500"},
+ {"RV360", "ATI Radeon 9500"},
+ {"RV351", "ATI Radeon 9500"},
+ {"RV350", "ATI Radeon 9500"},
+},
+cards_nvidia[] =
+{
+ {"NV124", "NVIDIA GeForce GTX 970"},
+ {"NV117", "NVIDIA GeForce GTX 750"},
+ {"NVF1", "NVIDIA GeForce GTX 780 Ti"},
+ {"NVF0", "NVIDIA GeForce GTX 780"},
+ {"NVE6", "NVIDIA GeForce GTX 770M"},
+ {"NVE4", "NVIDIA GeForce GTX 680"},
+ {"NVD9", "NVIDIA GeForce GT 520"},
+ {"NVCF", "NVIDIA GeForce GTX 550 Ti"},
+ {"NVCE", "NVIDIA GeForce GTX 560"},
+ {"NVC8", "NVIDIA GeForce GTX 570"},
+ {"NVC4", "NVIDIA GeForce GTX 460"},
+ {"NVC3", "NVIDIA GeForce GT 440"},
+ {"NVC1", "NVIDIA GeForce GT 420"},
+ {"NVC0", "NVIDIA GeForce GTX 480"},
+ {"NVAF", "NVIDIA GeForce GT 320M"},
+ {"NVAC", "NVIDIA GeForce 8200"},
+ {"NVAA", "NVIDIA GeForce 8200"},
+ {"NVA8", "NVIDIA GeForce 210"},
+ {"NVA5", "NVIDIA GeForce GT 220"},
+ {"NVA3", "NVIDIA GeForce GT 240"},
+ {"NVA0", "NVIDIA GeForce GTX 280"},
+ {"NV98", "NVIDIA GeForce 9200"},
+ {"NV96", "NVIDIA GeForce 9400 GT"},
+ {"NV94", "NVIDIA GeForce 9600 GT"},
+ {"NV92", "NVIDIA GeForce 9800 GT"},
+ {"NV86", "NVIDIA GeForce 8500 GT"},
+ {"NV84", "NVIDIA GeForce 8600 GT"},
+ {"NV50", "NVIDIA GeForce 8800 GTX"},
+ {"NV68", "NVIDIA GeForce 6200"},
+ {"NV67", "NVIDIA GeForce 6200"},
+ {"NV63", "NVIDIA GeForce 6200"},
+ {"NV4E", "NVIDIA GeForce 6200"},
+ {"NV4C", "NVIDIA GeForce 6200"},
+ {"NV4B", "NVIDIA GeForce 7600 GT"},
+ {"NV4A", "NVIDIA GeForce 6200"},
+ {"NV49", "NVIDIA GeForce 7800 GT"},
+ {"NV47", "NVIDIA GeForce 7800 GT"},
+ {"NV46", "NVIDIA GeForce Go 7400",},
+ {"NV45", "NVIDIA GeForce 6800"},
+ {"NV44", "NVIDIA GeForce 6200"},
+ {"NV43", "NVIDIA GeForce 6600 GT"},
+ {"NV42", "NVIDIA GeForce 6800"},
+ {"NV41", "NVIDIA GeForce 6800"},
+ {"NV40", "NVIDIA GeForce 6800"},
+ {"NV38", "NVIDIA GeForce FX 5800"},
+ {"NV36", "NVIDIA GeForce FX 5800"},
+ {"NV35", "NVIDIA GeForce FX 5800"},
+ {"NV34", "NVIDIA GeForce FX 5200"},
+ {"NV31", "NVIDIA GeForce FX 5600"},
+ {"NV30", "NVIDIA GeForce FX 5800"},
+ {"nv28", "NVIDIA GeForce4 Ti 4200"},
+ {"nv25", "NVIDIA GeForce4 Ti 4200"},
+ {"nv20", "NVIDIA GeForce3"},
+ {"nv1F", "NVIDIA GeForce4 MX 460"},
+ {"nv1A", "NVIDIA GeForce2 GTS/GeForce2 Pro"},
+ {"nv18", "NVIDIA GeForce4 MX 460"},
+ {"nv17", "NVIDIA GeForce4 MX 460"},
+ {"nv16", "NVIDIA GeForce2 GTS/GeForce2 Pro"},
+ {"nv15", "NVIDIA GeForce2 GTS/GeForce2 Pro"},
+ {"nv11", "NVIDIA GeForce2 MX/MX 400"},
+ {"nv10", "NVIDIA GeForce 256"},
+},
+cards_vmware[] =
+{
+ {"SVGA3D", "VMware SVGA 3D (Microsoft Corporation - WDDM)"},
+},
+cards_intel[] =
+{
+ {"Haswell Mobile", "Intel(R) Haswell Mobile"},
+ {"Ivybridge Server", "Intel(R) Ivybridge Server"},
+ {"Ivybridge Mobile", "Intel(R) Ivybridge Mobile"},
+ {"Ivybridge Desktop", "Intel(R) Ivybridge Desktop"},
+ {"Sandybridge Server", "Intel(R) Sandybridge Server"},
+ {"Sandybridge Mobile", "Intel(R) Sandybridge Mobile"},
+ {"Sandybridge Desktop", "Intel(R) Sandybridge Desktop"},
+ {"Ironlake Mobile", "Intel(R) Ironlake Mobile"},
+ {"Ironlake Desktop", "Intel(R) Ironlake Desktop"},
+ {"B43", "Intel(R) B43"},
+ {"G41", "Intel(R) G41"},
+ {"G45", "Intel(R) G45/G43"},
+ {"Q45", "Intel(R) Q45/Q43"},
+ {"Integrated Graphics Device", "Intel(R) Integrated Graphics Device"},
+ {"GM45", "Mobile Intel(R) GM45 Express Chipset Family"},
+ {"965GME", "Intel(R) 965GME"},
+ {"965GM", "Mobile Intel(R) 965 Express Chipset Family"},
+ {"946GZ", "Intel(R) 946GZ"},
+ {"965G", "Intel(R) 965G"},
+ {"965Q", "Intel(R) 965Q"},
+ {"Pineview M", "Intel(R) IGD"},
+ {"Pineview G", "Intel(R) IGD"},
+ {"IGD", "Intel(R) IGD"},
+ {"Q33", "Intel(R) Q33"},
+ {"G33", "Intel(R) G33"},
+ {"Q35", "Intel(R) Q35"},
+ {"945GME", "Intel(R) 945GME"},
+ {"945GM", "Mobile Intel(R) 945GM Express Chipset Family"},
+ {"945G", "Intel(R) 945G"},
+ {"915GM", "Mobile Intel(R) 915GM/GMS,910GML Express Chipset Family"},
+ {"E7221G", "Intel(R) E7221G"},
+ {"915G", "Intel(R) 82915G/GV/910GL Express Chipset Family"},
+ {"865G", "Intel(R) 82865G Graphics Controller"},
+ {"845G", "Intel(R) 845G"},
+ {"855GM", "Intel(R) 82852/82855 GM/GME Graphics Controller"},
+ {"830M", "Intel(R) 82830M Graphics Controller"},
+};
+
+/* override VendorId, DeviceId and Description for unknown vendors */
+void
+d3d_match_vendor_id( D3DADAPTER_IDENTIFIER9* drvid,
+ unsigned fallback_ven,
+ unsigned fallback_dev,
+ const char* fallback_name )
+{
+ if (drvid->VendorId == HW_VENDOR_INTEL ||
+ drvid->VendorId == HW_VENDOR_VMWARE ||
+ drvid->VendorId == HW_VENDOR_AMD ||
+ drvid->VendorId == HW_VENDOR_NVIDIA)
+ return;
+
+ DBG("unknown vendor 0x4%x, emulating 0x4%x\n", drvid->VendorId, fallback_ven);
+ drvid->VendorId = fallback_ven;
+ drvid->DeviceId = fallback_dev;
+ strncpy(drvid->Description, fallback_name, sizeof(drvid->Description));
+}
+
+/* fill in driver name and version */
+void d3d_fill_driver_version(D3DADAPTER_IDENTIFIER9* drvid) {
+ switch (drvid->VendorId) {
+ case HW_VENDOR_INTEL:
+ drvid->DriverVersionLowPart = 0x000A0682;
+ drvid->DriverVersionHighPart = 0x0006000F;
+ strncpy(drvid->Driver, "igdumd32.dll", sizeof(drvid->Driver));
+ break;
+ case HW_VENDOR_VMWARE:
+ drvid->DriverVersionLowPart = 0x0001046E;
+ drvid->DriverVersionHighPart = 0x0006000E;
+ strncpy(drvid->Driver, "vm3dum.dll", sizeof(drvid->Driver));
+ break;
+ case HW_VENDOR_AMD:
+ drvid->DriverVersionLowPart = 0x000A0500;
+ drvid->DriverVersionHighPart = 0x00060011;
+ strncpy(drvid->Driver, "atiumdag.dll", sizeof(drvid->Driver));
+ break;
+ case HW_VENDOR_NVIDIA:
+ drvid->DriverVersionLowPart = 0x000D0FD4;
+ drvid->DriverVersionHighPart = 0x00060012;
+ strncpy(drvid->Driver, "nvd3dum.dll", sizeof(drvid->Driver));
+ break;
+ default:
+ break;
+ }
+}
+
+/* try to match the device name and override it with Windows like device names */
+void d3d_fill_cardname(D3DADAPTER_IDENTIFIER9* drvid) {
+ unsigned i;
+ switch (drvid->VendorId) {
+ case HW_VENDOR_INTEL:
+ for (i = 0; i < sizeof(cards_intel) / sizeof(cards_intel[0]); i++) {
+ if (strstr(drvid->Description, cards_intel[i].mesaname)) {
+ strncpy(drvid->Description, cards_intel[i].d3d9name, sizeof(drvid->Description));
+ return;
+ }
+ }
+ /* use a fall-back if nothing matches */
+ DBG("Unknown card name %s!\n", drvid->DeviceName);
+ strncpy(drvid->Description, cards_intel[0].d3d9name, sizeof(drvid->Description));
+ break;
+ case HW_VENDOR_VMWARE:
+ for (i = 0; i < sizeof(cards_vmware) / sizeof(cards_vmware[0]); i++) {
+ if (strstr(drvid->Description, cards_vmware[i].mesaname)) {
+ strncpy(drvid->Description, cards_vmware[i].d3d9name, sizeof(drvid->Description));
+ return;
+ }
+ }
+ /* use a fall-back if nothing matches */
+ DBG("Unknown card name %s!\n", drvid->DeviceName);
+ strncpy(drvid->Description, cards_vmware[0].d3d9name, sizeof(drvid->Description));
+ break;
+ case HW_VENDOR_AMD:
+ for (i = 0; i < sizeof(cards_amd) / sizeof(cards_amd[0]); i++) {
+ if (strstr(drvid->Description, cards_amd[i].mesaname)) {
+ strncpy(drvid->Description, cards_amd[i].d3d9name, sizeof(drvid->Description));
+ return;
+ }
+ }
+ /* use a fall-back if nothing matches */
+ DBG("Unknown card name %s!\n", drvid->DeviceName);
+ strncpy(drvid->Description, cards_amd[0].d3d9name, sizeof(drvid->Description));
+ break;
+ case HW_VENDOR_NVIDIA:
+ for (i = 0; i < sizeof(cards_nvidia) / sizeof(cards_nvidia[0]); i++) {
+ if (strstr(drvid->Description, cards_nvidia[i].mesaname)) {
+ strncpy(drvid->Description, cards_nvidia[i].d3d9name, sizeof(drvid->Description));
+ return;
+ }
+ }
+ /* use a fall-back if nothing matches */
+ DBG("Unknown card name %s!\n", drvid->DeviceName);
+ strncpy(drvid->Description, cards_nvidia[0].d3d9name, sizeof(drvid->Description));
+ break;
+ default:
+ break;
+ }
+}
diff --git a/src/gallium/targets/d3dadapter9/drm.c b/src/gallium/targets/d3dadapter9/drm.c
index 680f5164e60..fabc820f268 100644
--- a/src/gallium/targets/d3dadapter9/drm.c
+++ b/src/gallium/targets/d3dadapter9/drm.c
@@ -46,12 +46,6 @@
#define DBG_CHANNEL DBG_ADAPTER
-#define VERSION_DWORD(hi, lo) \
- ((DWORD)( \
- ((DWORD)((hi) & 0xFFFF) << 16) | \
- (DWORD)((lo) & 0xFFFF) \
- ))
-
const char __driConfigOptionsNine[] =
DRI_CONF_BEGIN
DRI_CONF_SECTION_PERFORMANCE
@@ -63,12 +57,21 @@ DRI_CONF_BEGIN
DRI_CONF_SECTION_END
DRI_CONF_END;
-/* Regarding os versions, we should not define our own as that would simply be
- * weird. Defaulting to Win2k/XP seems sane considering the origin of D3D9. The
- * driver also defaults to being a generic D3D9 driver, which of course only
- * matters if you're actually using the DDI. */
-#define VERSION_HIGH VERSION_DWORD(0x0006, 0x000E) /* winxp, d3d9 */
-#define VERSION_LOW VERSION_DWORD(0x0000, 0x0001) /* version, build */
+/* define fallback value here: NVIDIA GeForce GTX 970 */
+#define FALLBACK_NAME "NV124"
+#define FALLBACK_DEVID 0x13C2
+#define FALLBACK_VENID 0x10de
+
+/* prototypes */
+void
+d3d_match_vendor_id( D3DADAPTER_IDENTIFIER9* drvid,
+ unsigned fallback_ven,
+ unsigned fallback_dev,
+ const char* fallback_name );
+
+void d3d_fill_driver_version(D3DADAPTER_IDENTIFIER9* drvid);
+
+void d3d_fill_cardname(D3DADAPTER_IDENTIFIER9* drvid);
struct d3dadapter9drm_context
{
@@ -152,9 +155,9 @@ get_bus_info( int fd,
*subsysid = 0;
*revision = 0;
} else {
- DBG("Unable to detect card. Fake GTX 680.\n");
- *vendorid = 0x10de; /* NV GTX 680 */
- *deviceid = 0x1180;
+ DBG("Unable to detect card. Faking %s\n", FALLBACK_NAME);
+ *vendorid = FALLBACK_VENID;
+ *deviceid = FALLBACK_DEVID;
*subsysid = 0;
*revision = 0;
}
@@ -169,33 +172,23 @@ read_descriptor( struct d3dadapter9_context *ctx,
memset(drvid, 0, sizeof(*drvid));
get_bus_info(fd, &drvid->VendorId, &drvid->DeviceId,
&drvid->SubSysId, &drvid->Revision);
+ snprintf(drvid->DeviceName, sizeof(drvid->DeviceName),
+ "Gallium 0.4 with %s", ctx->hal->get_vendor(ctx->hal));
+ strncpy(drvid->Description, ctx->hal->get_name(ctx->hal),
+ sizeof(drvid->Description));
+
+ /* choose fall-back vendor if necessary to allow
+ * the following functions to return sane results */
+ d3d_match_vendor_id(drvid, FALLBACK_VENID, FALLBACK_DEVID, FALLBACK_NAME);
+ /* fill in driver name and version info */
+ d3d_fill_driver_version(drvid);
+ /* override Description field with Windows like names */
+ d3d_fill_cardname(drvid);
+
+ /* this driver isn't WHQL certified */
+ drvid->WHQLLevel = 0;
- strncpy(drvid->Driver, "libd3dadapter9.so", sizeof(drvid->Driver));
- strncpy(drvid->DeviceName, ctx->hal->get_name(ctx->hal), 32);
- snprintf(drvid->Description, sizeof(drvid->Description),
- "Gallium 0.4 with %s", ctx->hal->get_vendor(ctx->hal));
-
- drvid->DriverVersionLowPart = VERSION_LOW;
- drvid->DriverVersionHighPart = VERSION_HIGH;
-
- /* To make a pseudo-real GUID we use the PCI bus data and some string */
- drvid->DeviceIdentifier.Data1 = drvid->VendorId;
- drvid->DeviceIdentifier.Data2 = drvid->DeviceId;
- drvid->DeviceIdentifier.Data3 = drvid->SubSysId;
- memcpy(drvid->DeviceIdentifier.Data4, "Gallium3D", 8);
-
- drvid->WHQLLevel = 1; /* This fakes WHQL validaion */
-
- /* XXX Fake NVIDIA binary driver on Windows.
- *
- * OS version: 4=95/98/NT4, 5=2000, 6=2000/XP, 7=Vista, 8=Win7
- */
- strncpy(drvid->Driver, "nvd3dum.dll", sizeof(drvid->Driver));
- strncpy(drvid->Description, "NVIDIA GeForce GTX 680", sizeof(drvid->Description));
- drvid->DriverVersionLowPart = VERSION_DWORD(12, 6658); /* minor, build */
- drvid->DriverVersionHighPart = VERSION_DWORD(6, 15); /* OS, major */
- drvid->SubSysId = 0;
- drvid->Revision = 0;
+ /* this value is fixed */
drvid->DeviceIdentifier.Data1 = 0xaeb2cdd4;
drvid->DeviceIdentifier.Data2 = 0x6e41;
drvid->DeviceIdentifier.Data3 = 0x43ea;
@@ -207,7 +200,6 @@ read_descriptor( struct d3dadapter9_context *ctx,
drvid->DeviceIdentifier.Data4[5] = 0x76;
drvid->DeviceIdentifier.Data4[6] = 0x07;
drvid->DeviceIdentifier.Data4[7] = 0x81;
- drvid->WHQLLevel = 0;
}
static HRESULT WINAPI
diff --git a/src/gallium/targets/dri/Android.mk b/src/gallium/targets/dri/Android.mk
index 7168e1dbfb3..a33d7f83671 100644
--- a/src/gallium/targets/dri/Android.mk
+++ b/src/gallium/targets/dri/Android.mk
@@ -77,8 +77,8 @@ gallium_DRIVERS += libmesa_pipe_r600
LOCAL_CFLAGS += -DGALLIUM_R600
endif
ifneq ($(filter radeonsi,$(MESA_GPU_DRIVERS)),)
-gallium_DRIVERS += libmesa_pipe_radeonsi
-LOCAL_SHARED_LIBRARIES += libLLVM
+gallium_DRIVERS += libmesa_pipe_radeonsi libmesa_winsys_amdgpu
+LOCAL_SHARED_LIBRARIES += libLLVM libdrm_amdgpu
LOCAL_CFLAGS += -DGALLIUM_RADEONSI
endif
gallium_DRIVERS += libmesa_winsys_radeon libmesa_pipe_radeon
diff --git a/src/gallium/winsys/amdgpu/drm/Android.mk b/src/gallium/winsys/amdgpu/drm/Android.mk
index 7d507aa79c6..57732347eea 100644
--- a/src/gallium/winsys/amdgpu/drm/Android.mk
+++ b/src/gallium/winsys/amdgpu/drm/Android.mk
@@ -30,6 +30,16 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(C_SOURCES)
+LOCAL_CFLAGS := \
+ $(AMDGPU_CFLAGS) \
+ -DBRAHMA_BUILD=1
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/addrlib \
+ $(LOCAL_PATH)/addrlib/core \
+ $(LOCAL_PATH)/addrlib/inc/chip/r800 \
+ $(LOCAL_PATH)/addrlib/r800/chip
+
LOCAL_SHARED_LIBRARIES := libdrm libdrm_amdgpu
LOCAL_MODULE := libmesa_winsys_amdgpu
diff --git a/src/gallium/winsys/amdgpu/drm/Makefile.sources b/src/gallium/winsys/amdgpu/drm/Makefile.sources
index 6b33841b204..23630044ab3 100644
--- a/src/gallium/winsys/amdgpu/drm/Makefile.sources
+++ b/src/gallium/winsys/amdgpu/drm/Makefile.sources
@@ -11,9 +11,7 @@ C_SOURCES := \
addrlib/core/addrobject.h \
addrlib/inc/chip/r800/si_gb_reg.h \
addrlib/inc/lnx_common_defs.h \
- addrlib/r800/chip/si_ci_merged_enum.h \
addrlib/r800/chip/si_ci_vi_merged_enum.h \
- addrlib/r800/chip/si_enum.h \
addrlib/r800/ciaddrlib.cpp \
addrlib/r800/ciaddrlib.h \
addrlib/r800/egbaddrlib.cpp \
diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_cs.h b/src/gallium/winsys/amdgpu/drm/amdgpu_cs.h
index 0842259044b..12c6b624b03 100644
--- a/src/gallium/winsys/amdgpu/drm/amdgpu_cs.h
+++ b/src/gallium/winsys/amdgpu/drm/amdgpu_cs.h
@@ -77,8 +77,8 @@ struct amdgpu_cs {
int buffer_indices_hashlist[512];
- unsigned used_vram;
- unsigned used_gart;
+ uint64_t used_vram;
+ uint64_t used_gart;
unsigned max_dependencies;
};
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
index 7a267f9acbf..f04a696988a 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
@@ -97,22 +97,17 @@ static boolean radeon_init_cs_context(struct radeon_cs_context *csc,
{
int i;
- csc->buf = MALLOC(ws->ib_max_size);
- if (!csc->buf)
- return FALSE;
csc->fd = ws->fd;
csc->nrelocs = 512;
csc->relocs_bo = (struct radeon_bo**)
CALLOC(1, csc->nrelocs * sizeof(struct radeon_bo*));
if (!csc->relocs_bo) {
- FREE(csc->buf);
return FALSE;
}
csc->relocs = (struct drm_radeon_cs_reloc*)
CALLOC(1, csc->nrelocs * sizeof(struct drm_radeon_cs_reloc));
if (!csc->relocs) {
- FREE(csc->buf);
FREE(csc->relocs_bo);
return FALSE;
}
@@ -165,7 +160,6 @@ static void radeon_destroy_cs_context(struct radeon_cs_context *csc)
radeon_cs_context_cleanup(csc);
FREE(csc->relocs_bo);
FREE(csc->relocs);
- FREE(csc->buf);
}
@@ -206,7 +200,7 @@ radeon_drm_cs_create(struct radeon_winsys_ctx *ctx,
cs->cst = &cs->csc2;
cs->base.buf = cs->csc->buf;
cs->base.ring_type = ring_type;
- cs->base.max_dw = ws->ib_max_size / 4;
+ cs->base.max_dw = ARRAY_SIZE(cs->csc->buf);
p_atomic_inc(&ws->num_cs);
return &cs->base;
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
index ab154945880..6ceb8e98ee7 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
@@ -30,7 +30,7 @@
#include "radeon_drm_bo.h"
struct radeon_cs_context {
- uint32_t *buf;
+ uint32_t buf[16 * 1024];
int fd;
struct drm_radeon_cs cs;
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
index b70bbaa54a3..f7784fb795e 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
@@ -395,20 +395,16 @@ static boolean do_winsys_init(struct radeon_drm_winsys *ws)
}
ws->info.r600_virtual_address = FALSE;
- ws->ib_max_size = 64 * 1024;
-
if (ws->info.drm_minor >= 13) {
+ uint32_t ib_vm_max_size;
+
ws->info.r600_virtual_address = TRUE;
if (!radeon_get_drm_value(ws->fd, RADEON_INFO_VA_START, NULL,
&ws->va_start))
ws->info.r600_virtual_address = FALSE;
-
- if (radeon_get_drm_value(ws->fd, RADEON_INFO_IB_VM_MAX_SIZE, NULL,
- &ws->ib_max_size))
- ws->ib_max_size *= 4; /* the kernel returns the size in dwords */
- else
+ if (!radeon_get_drm_value(ws->fd, RADEON_INFO_IB_VM_MAX_SIZE, NULL,
+ &ib_vm_max_size))
ws->info.r600_virtual_address = FALSE;
-
radeon_get_drm_value(ws->fd, RADEON_INFO_VA_UNMAP_WORKING, NULL,
&ws->va_unmap_working);
}
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h
index c1a8d6ae564..308b5bd976d 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h
@@ -73,7 +73,6 @@ struct radeon_drm_winsys {
enum radeon_generation gen;
struct radeon_info info;
- uint32_t ib_max_size;
uint32_t va_start;
uint32_t va_unmap_working;
uint32_t accel_working2;
diff --git a/src/gallium/winsys/sw/kms-dri/Makefile.am b/src/gallium/winsys/sw/kms-dri/Makefile.am
index 7f26b1b2f19..8162553289d 100644
--- a/src/gallium/winsys/sw/kms-dri/Makefile.am
+++ b/src/gallium/winsys/sw/kms-dri/Makefile.am
@@ -31,5 +31,3 @@ AM_CFLAGS = \
noinst_LTLIBRARIES = libswkmsdri.la
libswkmsdri_la_SOURCES = $(C_SOURCES)
-
-EXTRA_DIST = SConscript
diff --git a/src/gbm/main/backend.c b/src/gbm/main/backend.c
index 4929d732b44..37ec9c16f40 100644
--- a/src/gbm/main/backend.c
+++ b/src/gbm/main/backend.c
@@ -65,7 +65,7 @@ static const struct backend_desc *
find_backend(const char *name)
{
const struct backend_desc *backend = NULL;
- int i;
+ unsigned i;
for (i = 0; i < ARRAY_SIZE(backends); ++i) {
if (strcmp(backends[i].name, name) == 0) {
@@ -82,7 +82,7 @@ _gbm_create_device(int fd)
{
const struct gbm_backend *backend = NULL;
struct gbm_device *dev = NULL;
- int i;
+ unsigned i;
const char *b;
b = getenv("GBM_BACKEND");
diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources
index b491ad4d36f..da38e3576bd 100644
--- a/src/glsl/Makefile.sources
+++ b/src/glsl/Makefile.sources
@@ -25,6 +25,9 @@ NIR_FILES = \
nir/nir_array.h \
nir/nir_builder.h \
nir/nir_constant_expressions.h \
+ nir/nir_control_flow.c \
+ nir/nir_control_flow.h \
+ nir/nir_control_flow_private.h \
nir/nir_dominance.c \
nir/nir_from_ssa.c \
nir/nir_intrinsics.c \
diff --git a/src/glsl/ast_array_index.cpp b/src/glsl/ast_array_index.cpp
index 27e84d101ec..ae399f03a9b 100644
--- a/src/glsl/ast_array_index.cpp
+++ b/src/glsl/ast_array_index.cpp
@@ -290,6 +290,21 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
"1.30 and later");
}
}
+
+ /* From page 27 of the GLSL ES 3.1 specification:
+ *
+ * "When aggregated into arrays within a shader, images can only be
+ * indexed with a constant integral expression."
+ *
+ * On the other hand the desktop GL specification extension allows
+ * non-constant indexing of image arrays, but behavior is left undefined
+ * in cases where the indexing expression is not dynamically uniform.
+ */
+ if (state->es_shader && array->type->without_array()->is_image()) {
+ _mesa_glsl_error(&loc, state,
+ "image arrays indexed with non-constant "
+ "expressions are forbidden in GLSL ES.");
+ }
}
/* After performing all of the error checking, generate the IR for the
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index fa2c09d2697..981438de597 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -2099,10 +2099,10 @@ validate_matrix_layout_for_type(struct _mesa_glsl_parse_state *state,
static bool
validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
YYLTYPE *loc,
- ir_variable *var,
+ const glsl_type *type,
const ast_type_qualifier *qual)
{
- if (var->data.mode != ir_var_uniform && var->data.mode != ir_var_shader_storage) {
+ if (!qual->flags.q.uniform && !qual->flags.q.buffer) {
_mesa_glsl_error(loc, state,
"the \"binding\" qualifier only applies to uniforms and "
"shader storage buffer objects");
@@ -2115,10 +2115,11 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
}
const struct gl_context *const ctx = state->ctx;
- unsigned elements = var->type->is_array() ? var->type->length : 1;
+ unsigned elements = type->is_array() ? type->length : 1;
unsigned max_index = qual->binding + elements - 1;
+ const glsl_type *base_type = type->without_array();
- if (var->type->is_interface()) {
+ if (base_type->is_interface()) {
/* UBOs. From page 60 of the GLSL 4.20 specification:
* "If the binding point for any uniform block instance is less than zero,
* or greater than or equal to the implementation-dependent maximum
@@ -2129,7 +2130,7 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
*
* The implementation-dependent maximum is GL_MAX_UNIFORM_BUFFER_BINDINGS.
*/
- if (var->data.mode == ir_var_uniform &&
+ if (qual->flags.q.uniform &&
max_index >= ctx->Const.MaxUniformBufferBindings) {
_mesa_glsl_error(loc, state, "layout(binding = %d) for %d UBOs exceeds "
"the maximum number of UBO binding points (%d)",
@@ -2137,6 +2138,7 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
ctx->Const.MaxUniformBufferBindings);
return false;
}
+
/* SSBOs. From page 67 of the GLSL 4.30 specification:
* "If the binding point for any uniform or shader storage block instance
* is less than zero, or greater than or equal to the
@@ -2146,7 +2148,7 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
* N, all elements of the array from binding through binding + N – 1 must
* be within this range."
*/
- if (var->data.mode == ir_var_shader_storage &&
+ if (qual->flags.q.buffer &&
max_index >= ctx->Const.MaxShaderStorageBufferBindings) {
_mesa_glsl_error(loc, state, "layout(binding = %d) for %d SSBOs exceeds "
"the maximum number of SSBO binding points (%d)",
@@ -2154,8 +2156,7 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
ctx->Const.MaxShaderStorageBufferBindings);
return false;
}
- } else if (var->type->is_sampler() ||
- (var->type->is_array() && var->type->fields.array->is_sampler())) {
+ } else if (base_type->is_sampler()) {
/* Samplers. From page 63 of the GLSL 4.20 specification:
* "If the binding is less than zero, or greater than or equal to the
* implementation-dependent maximum supported number of units, a
@@ -2172,7 +2173,7 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
return false;
}
- } else if (var->type->contains_atomic()) {
+ } else if (base_type->contains_atomic()) {
assert(ctx->Const.MaxAtomicBufferBindings <= MAX_COMBINED_ATOMIC_BUFFERS);
if (unsigned(qual->binding) >= ctx->Const.MaxAtomicBufferBindings) {
_mesa_glsl_error(loc, state, "layout(binding = %d) exceeds the "
@@ -2182,10 +2183,19 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
return false;
}
+ } else if (state->is_version(420, 310) && base_type->is_image()) {
+ assert(ctx->Const.MaxImageUnits <= MAX_IMAGE_UNITS);
+ if (max_index >= ctx->Const.MaxImageUnits) {
+ _mesa_glsl_error(loc, state, "Image binding %d exceeds the "
+ " maximum number of image units (%d)", max_index,
+ ctx->Const.MaxImageUnits);
+ return false;
+ }
+
} else {
_mesa_glsl_error(loc, state,
"the \"binding\" qualifier only applies to uniform "
- "blocks, samplers, atomic counters, or arrays thereof");
+ "blocks, opaque variables, or arrays thereof");
return false;
}
@@ -2446,14 +2456,38 @@ apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual,
var->data.image_format = qual->image_format;
} else {
- if (var->data.mode == ir_var_uniform && !qual->flags.q.write_only) {
- _mesa_glsl_error(loc, state, "uniforms not qualified with "
- "`writeonly' must have a format layout "
- "qualifier");
+ if (var->data.mode == ir_var_uniform) {
+ if (state->es_shader) {
+ _mesa_glsl_error(loc, state, "all image uniforms "
+ "must have a format layout qualifier");
+
+ } else if (!qual->flags.q.write_only) {
+ _mesa_glsl_error(loc, state, "image uniforms not qualified with "
+ "`writeonly' must have a format layout "
+ "qualifier");
+ }
}
var->data.image_format = GL_NONE;
}
+
+ /* From page 70 of the GLSL ES 3.1 specification:
+ *
+ * "Except for image variables qualified with the format qualifiers
+ * r32f, r32i, and r32ui, image variables must specify either memory
+ * qualifier readonly or the memory qualifier writeonly."
+ */
+ if (state->es_shader &&
+ var->data.image_format != GL_R32F &&
+ var->data.image_format != GL_R32I &&
+ var->data.image_format != GL_R32UI &&
+ !var->data.image_read_only &&
+ !var->data.image_write_only) {
+ _mesa_glsl_error(loc, state, "image variables of format other than "
+ "r32f, r32i or r32ui must be qualified `readonly' or "
+ "`writeonly'");
+ }
+
} else if (qual->flags.q.read_only ||
qual->flags.q.write_only ||
qual->flags.q.coherent ||
@@ -2759,7 +2793,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
}
if (qual->flags.q.explicit_binding &&
- validate_binding_qualifier(state, loc, var, qual)) {
+ validate_binding_qualifier(state, loc, var->type, qual)) {
var->data.explicit_binding = true;
var->data.binding = qual->binding;
}
@@ -3293,7 +3327,7 @@ handle_tess_ctrl_shader_output_decl(struct _mesa_glsl_parse_state *state,
validate_layout_qualifier_vertex_count(state, loc, var, num_vertices,
&state->tcs_output_size,
- "geometry shader input");
+ "tessellation control shader output");
}
/**
@@ -3390,7 +3424,7 @@ validate_identifier(const char *identifier, YYLTYPE loc,
static bool
precision_qualifier_allowed(const glsl_type *type)
{
- /* Precision qualifiers apply to floating point, integer and sampler
+ /* Precision qualifiers apply to floating point, integer and opaque
* types.
*
* Section 4.5.2 (Precision Qualifiers) of the GLSL 1.30 spec says:
@@ -3420,7 +3454,7 @@ precision_qualifier_allowed(const glsl_type *type)
return type->is_float()
|| type->is_integer()
|| type->is_record()
- || type->is_sampler();
+ || type->contains_opaque();
}
ir_rvalue *
@@ -4131,7 +4165,7 @@ ast_declarator_list::hir(exec_list *instructions,
_mesa_glsl_error(&loc, state,
"precision qualifiers apply only to floating point"
- ", integer and sampler types");
+ ", integer and opaque types");
}
/* From section 4.1.7 of the GLSL 4.40 spec:
@@ -5439,6 +5473,8 @@ is_valid_default_precision_type(const struct glsl_type *const type)
/* "int" and "float" are valid, but vectors and matrices are not. */
return type->vector_elements == 1 && type->matrix_columns == 1;
case GLSL_TYPE_SAMPLER:
+ case GLSL_TYPE_IMAGE:
+ case GLSL_TYPE_ATOMIC_UINT:
return true;
default:
return false;
@@ -5487,7 +5523,7 @@ ast_type_specifier::hir(exec_list *instructions,
if (!is_valid_default_precision_type(type)) {
_mesa_glsl_error(&loc, state,
"default precision statements apply only to "
- "float, int, and sampler types");
+ "float, int, and opaque types");
return NULL;
}
@@ -6067,6 +6103,8 @@ ast_interface_block::hir(exec_list *instructions,
num_variables,
packing,
this->block_name);
+ if (this->layout.flags.q.explicit_binding)
+ validate_binding_qualifier(state, &loc, block_type, &this->layout);
if (!state->symbols->add_interface(block_type->name, block_type, var_mode)) {
YYLTYPE loc = this->get_location();
@@ -6197,6 +6235,10 @@ ast_interface_block::hir(exec_list *instructions,
"not allowed");
}
+ if (this->layout.flags.q.explicit_binding)
+ validate_binding_qualifier(state, &loc, block_array_type,
+ &this->layout);
+
var = new(state) ir_variable(block_array_type,
this->instance_name,
var_mode);
diff --git a/src/glsl/builtin_functions.cpp b/src/glsl/builtin_functions.cpp
index 2175c66cbd7..1bc3de4aec5 100644
--- a/src/glsl/builtin_functions.cpp
+++ b/src/glsl/builtin_functions.cpp
@@ -136,6 +136,13 @@ v140(const _mesa_glsl_parse_state *state)
}
static bool
+v400_fs_only(const _mesa_glsl_parse_state *state)
+{
+ return state->is_version(400, 0) &&
+ state->stage == MESA_SHADER_FRAGMENT;
+}
+
+static bool
es31(const _mesa_glsl_parse_state *state)
{
return state->is_version(0, 310);
@@ -270,6 +277,13 @@ texture_array(const _mesa_glsl_parse_state *state)
static bool
texture_multisample(const _mesa_glsl_parse_state *state)
{
+ return state->is_version(150, 310) ||
+ state->ARB_texture_multisample_enable;
+}
+
+static bool
+texture_multisample_array(const _mesa_glsl_parse_state *state)
+{
return state->is_version(150, 0) ||
state->ARB_texture_multisample_enable;
}
@@ -394,11 +408,25 @@ shader_trinary_minmax(const _mesa_glsl_parse_state *state)
static bool
shader_image_load_store(const _mesa_glsl_parse_state *state)
{
+ return (state->is_version(420, 310) ||
+ state->ARB_shader_image_load_store_enable);
+}
+
+static bool
+shader_image_atomic(const _mesa_glsl_parse_state *state)
+{
return (state->is_version(420, 0) ||
state->ARB_shader_image_load_store_enable);
}
static bool
+shader_image_size(const _mesa_glsl_parse_state *state)
+{
+ return state->is_version(430, 310) ||
+ state->ARB_shader_image_size_enable;
+}
+
+static bool
gs_streams(const _mesa_glsl_parse_state *state)
{
return gpu_shader5(state) && gs_only(state);
@@ -492,13 +520,19 @@ private:
/** Create a new function and add the given signatures. */
void add_function(const char *name, ...);
+ typedef ir_function_signature *(builtin_builder::*image_prototype_ctr)(const glsl_type *image_type,
+ const char *intrinsic_name,
+ unsigned num_arguments,
+ unsigned flags);
+
enum image_function_flags {
IMAGE_FUNCTION_EMIT_STUB = (1 << 0),
IMAGE_FUNCTION_RETURNS_VOID = (1 << 1),
IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE = (1 << 2),
IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE = (1 << 3),
IMAGE_FUNCTION_READ_ONLY = (1 << 4),
- IMAGE_FUNCTION_WRITE_ONLY = (1 << 5)
+ IMAGE_FUNCTION_WRITE_ONLY = (1 << 5),
+ IMAGE_FUNCTION_AVAIL_ATOMIC = (1 << 6)
};
/**
@@ -507,6 +541,7 @@ private:
*/
void add_image_function(const char *name,
const char *intrinsic_name,
+ image_prototype_ctr prototype,
unsigned num_arguments,
unsigned flags);
@@ -663,7 +698,7 @@ private:
const glsl_type *stream_type);
B0(barrier)
- B2(textureQueryLod);
+ BA2(textureQueryLod);
B1(textureQueryLevels);
B1(dFdx);
B1(dFdy);
@@ -708,7 +743,12 @@ private:
const char *intrinsic_name,
unsigned num_arguments,
unsigned flags);
- ir_function_signature *_image(const glsl_type *image_type,
+ ir_function_signature *_image_size_prototype(const glsl_type *image_type,
+ const char *intrinsic_name,
+ unsigned num_arguments,
+ unsigned flags);
+ ir_function_signature *_image(image_prototype_ctr prototype,
+ const glsl_type *image_type,
const char *intrinsic_name,
unsigned num_arguments,
unsigned flags);
@@ -1367,9 +1407,9 @@ builtin_builder::create_builtins()
_textureSize(texture_multisample, glsl_type::ivec2_type, glsl_type::isampler2DMS_type),
_textureSize(texture_multisample, glsl_type::ivec2_type, glsl_type::usampler2DMS_type),
- _textureSize(texture_multisample, glsl_type::ivec3_type, glsl_type::sampler2DMSArray_type),
- _textureSize(texture_multisample, glsl_type::ivec3_type, glsl_type::isampler2DMSArray_type),
- _textureSize(texture_multisample, glsl_type::ivec3_type, glsl_type::usampler2DMSArray_type),
+ _textureSize(texture_multisample_array, glsl_type::ivec3_type, glsl_type::sampler2DMSArray_type),
+ _textureSize(texture_multisample_array, glsl_type::ivec3_type, glsl_type::isampler2DMSArray_type),
+ _textureSize(texture_multisample_array, glsl_type::ivec3_type, glsl_type::usampler2DMSArray_type),
NULL);
add_function("texture",
@@ -1632,9 +1672,9 @@ builtin_builder::create_builtins()
_texelFetch(texture_multisample, glsl_type::ivec4_type, glsl_type::isampler2DMS_type, glsl_type::ivec2_type),
_texelFetch(texture_multisample, glsl_type::uvec4_type, glsl_type::usampler2DMS_type, glsl_type::ivec2_type),
- _texelFetch(texture_multisample, glsl_type::vec4_type, glsl_type::sampler2DMSArray_type, glsl_type::ivec3_type),
- _texelFetch(texture_multisample, glsl_type::ivec4_type, glsl_type::isampler2DMSArray_type, glsl_type::ivec3_type),
- _texelFetch(texture_multisample, glsl_type::uvec4_type, glsl_type::usampler2DMSArray_type, glsl_type::ivec3_type),
+ _texelFetch(texture_multisample_array, glsl_type::vec4_type, glsl_type::sampler2DMSArray_type, glsl_type::ivec3_type),
+ _texelFetch(texture_multisample_array, glsl_type::ivec4_type, glsl_type::isampler2DMSArray_type, glsl_type::ivec3_type),
+ _texelFetch(texture_multisample_array, glsl_type::uvec4_type, glsl_type::usampler2DMSArray_type, glsl_type::ivec3_type),
NULL);
add_function("texelFetchOffset",
@@ -1944,40 +1984,77 @@ builtin_builder::create_builtins()
add_function("barrier", _barrier(), NULL);
add_function("textureQueryLOD",
- _textureQueryLod(glsl_type::sampler1D_type, glsl_type::float_type),
- _textureQueryLod(glsl_type::isampler1D_type, glsl_type::float_type),
- _textureQueryLod(glsl_type::usampler1D_type, glsl_type::float_type),
-
- _textureQueryLod(glsl_type::sampler2D_type, glsl_type::vec2_type),
- _textureQueryLod(glsl_type::isampler2D_type, glsl_type::vec2_type),
- _textureQueryLod(glsl_type::usampler2D_type, glsl_type::vec2_type),
-
- _textureQueryLod(glsl_type::sampler3D_type, glsl_type::vec3_type),
- _textureQueryLod(glsl_type::isampler3D_type, glsl_type::vec3_type),
- _textureQueryLod(glsl_type::usampler3D_type, glsl_type::vec3_type),
-
- _textureQueryLod(glsl_type::samplerCube_type, glsl_type::vec3_type),
- _textureQueryLod(glsl_type::isamplerCube_type, glsl_type::vec3_type),
- _textureQueryLod(glsl_type::usamplerCube_type, glsl_type::vec3_type),
-
- _textureQueryLod(glsl_type::sampler1DArray_type, glsl_type::float_type),
- _textureQueryLod(glsl_type::isampler1DArray_type, glsl_type::float_type),
- _textureQueryLod(glsl_type::usampler1DArray_type, glsl_type::float_type),
-
- _textureQueryLod(glsl_type::sampler2DArray_type, glsl_type::vec2_type),
- _textureQueryLod(glsl_type::isampler2DArray_type, glsl_type::vec2_type),
- _textureQueryLod(glsl_type::usampler2DArray_type, glsl_type::vec2_type),
-
- _textureQueryLod(glsl_type::samplerCubeArray_type, glsl_type::vec3_type),
- _textureQueryLod(glsl_type::isamplerCubeArray_type, glsl_type::vec3_type),
- _textureQueryLod(glsl_type::usamplerCubeArray_type, glsl_type::vec3_type),
-
- _textureQueryLod(glsl_type::sampler1DShadow_type, glsl_type::float_type),
- _textureQueryLod(glsl_type::sampler2DShadow_type, glsl_type::vec2_type),
- _textureQueryLod(glsl_type::samplerCubeShadow_type, glsl_type::vec3_type),
- _textureQueryLod(glsl_type::sampler1DArrayShadow_type, glsl_type::float_type),
- _textureQueryLod(glsl_type::sampler2DArrayShadow_type, glsl_type::vec2_type),
- _textureQueryLod(glsl_type::samplerCubeArrayShadow_type, glsl_type::vec3_type),
+ _textureQueryLod(texture_query_lod, glsl_type::sampler1D_type, glsl_type::float_type),
+ _textureQueryLod(texture_query_lod, glsl_type::isampler1D_type, glsl_type::float_type),
+ _textureQueryLod(texture_query_lod, glsl_type::usampler1D_type, glsl_type::float_type),
+
+ _textureQueryLod(texture_query_lod, glsl_type::sampler2D_type, glsl_type::vec2_type),
+ _textureQueryLod(texture_query_lod, glsl_type::isampler2D_type, glsl_type::vec2_type),
+ _textureQueryLod(texture_query_lod, glsl_type::usampler2D_type, glsl_type::vec2_type),
+
+ _textureQueryLod(texture_query_lod, glsl_type::sampler3D_type, glsl_type::vec3_type),
+ _textureQueryLod(texture_query_lod, glsl_type::isampler3D_type, glsl_type::vec3_type),
+ _textureQueryLod(texture_query_lod, glsl_type::usampler3D_type, glsl_type::vec3_type),
+
+ _textureQueryLod(texture_query_lod, glsl_type::samplerCube_type, glsl_type::vec3_type),
+ _textureQueryLod(texture_query_lod, glsl_type::isamplerCube_type, glsl_type::vec3_type),
+ _textureQueryLod(texture_query_lod, glsl_type::usamplerCube_type, glsl_type::vec3_type),
+
+ _textureQueryLod(texture_query_lod, glsl_type::sampler1DArray_type, glsl_type::float_type),
+ _textureQueryLod(texture_query_lod, glsl_type::isampler1DArray_type, glsl_type::float_type),
+ _textureQueryLod(texture_query_lod, glsl_type::usampler1DArray_type, glsl_type::float_type),
+
+ _textureQueryLod(texture_query_lod, glsl_type::sampler2DArray_type, glsl_type::vec2_type),
+ _textureQueryLod(texture_query_lod, glsl_type::isampler2DArray_type, glsl_type::vec2_type),
+ _textureQueryLod(texture_query_lod, glsl_type::usampler2DArray_type, glsl_type::vec2_type),
+
+ _textureQueryLod(texture_query_lod, glsl_type::samplerCubeArray_type, glsl_type::vec3_type),
+ _textureQueryLod(texture_query_lod, glsl_type::isamplerCubeArray_type, glsl_type::vec3_type),
+ _textureQueryLod(texture_query_lod, glsl_type::usamplerCubeArray_type, glsl_type::vec3_type),
+
+ _textureQueryLod(texture_query_lod, glsl_type::sampler1DShadow_type, glsl_type::float_type),
+ _textureQueryLod(texture_query_lod, glsl_type::sampler2DShadow_type, glsl_type::vec2_type),
+ _textureQueryLod(texture_query_lod, glsl_type::samplerCubeShadow_type, glsl_type::vec3_type),
+ _textureQueryLod(texture_query_lod, glsl_type::sampler1DArrayShadow_type, glsl_type::float_type),
+ _textureQueryLod(texture_query_lod, glsl_type::sampler2DArrayShadow_type, glsl_type::vec2_type),
+ _textureQueryLod(texture_query_lod, glsl_type::samplerCubeArrayShadow_type, glsl_type::vec3_type),
+ NULL);
+
+ add_function("textureQueryLod",
+ _textureQueryLod(v400_fs_only, glsl_type::sampler1D_type, glsl_type::float_type),
+ _textureQueryLod(v400_fs_only, glsl_type::isampler1D_type, glsl_type::float_type),
+ _textureQueryLod(v400_fs_only, glsl_type::usampler1D_type, glsl_type::float_type),
+
+ _textureQueryLod(v400_fs_only, glsl_type::sampler2D_type, glsl_type::vec2_type),
+ _textureQueryLod(v400_fs_only, glsl_type::isampler2D_type, glsl_type::vec2_type),
+ _textureQueryLod(v400_fs_only, glsl_type::usampler2D_type, glsl_type::vec2_type),
+
+ _textureQueryLod(v400_fs_only, glsl_type::sampler3D_type, glsl_type::vec3_type),
+ _textureQueryLod(v400_fs_only, glsl_type::isampler3D_type, glsl_type::vec3_type),
+ _textureQueryLod(v400_fs_only, glsl_type::usampler3D_type, glsl_type::vec3_type),
+
+ _textureQueryLod(v400_fs_only, glsl_type::samplerCube_type, glsl_type::vec3_type),
+ _textureQueryLod(v400_fs_only, glsl_type::isamplerCube_type, glsl_type::vec3_type),
+ _textureQueryLod(v400_fs_only, glsl_type::usamplerCube_type, glsl_type::vec3_type),
+
+ _textureQueryLod(v400_fs_only, glsl_type::sampler1DArray_type, glsl_type::float_type),
+ _textureQueryLod(v400_fs_only, glsl_type::isampler1DArray_type, glsl_type::float_type),
+ _textureQueryLod(v400_fs_only, glsl_type::usampler1DArray_type, glsl_type::float_type),
+
+ _textureQueryLod(v400_fs_only, glsl_type::sampler2DArray_type, glsl_type::vec2_type),
+ _textureQueryLod(v400_fs_only, glsl_type::isampler2DArray_type, glsl_type::vec2_type),
+ _textureQueryLod(v400_fs_only, glsl_type::usampler2DArray_type, glsl_type::vec2_type),
+
+ _textureQueryLod(v400_fs_only, glsl_type::samplerCubeArray_type, glsl_type::vec3_type),
+ _textureQueryLod(v400_fs_only, glsl_type::isamplerCubeArray_type, glsl_type::vec3_type),
+ _textureQueryLod(v400_fs_only, glsl_type::usamplerCubeArray_type, glsl_type::vec3_type),
+
+ _textureQueryLod(v400_fs_only, glsl_type::sampler1DShadow_type, glsl_type::float_type),
+ _textureQueryLod(v400_fs_only, glsl_type::sampler2DShadow_type, glsl_type::vec2_type),
+ _textureQueryLod(v400_fs_only, glsl_type::samplerCubeShadow_type, glsl_type::vec3_type),
+ _textureQueryLod(v400_fs_only, glsl_type::sampler1DArrayShadow_type, glsl_type::float_type),
+ _textureQueryLod(v400_fs_only, glsl_type::sampler2DArrayShadow_type, glsl_type::vec2_type),
+ _textureQueryLod(v400_fs_only, glsl_type::samplerCubeArrayShadow_type, glsl_type::vec3_type),
NULL);
add_function("textureQueryLevels",
@@ -2552,6 +2629,7 @@ builtin_builder::add_function(const char *name, ...)
void
builtin_builder::add_image_function(const char *name,
const char *intrinsic_name,
+ image_prototype_ctr prototype,
unsigned num_arguments,
unsigned flags)
{
@@ -2590,12 +2668,13 @@ builtin_builder::add_image_function(const char *name,
glsl_type::uimage2DMS_type,
glsl_type::uimage2DMSArray_type
};
+
ir_function *f = new(mem_ctx) ir_function(name);
for (unsigned i = 0; i < ARRAY_SIZE(types); ++i) {
if (types[i]->sampler_type != GLSL_TYPE_FLOAT ||
(flags & IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE))
- f->add_signature(_image(types[i], intrinsic_name,
+ f->add_signature(_image(prototype, types[i], intrinsic_name,
num_arguments, flags));
}
@@ -2608,43 +2687,60 @@ builtin_builder::add_image_functions(bool glsl)
const unsigned flags = (glsl ? IMAGE_FUNCTION_EMIT_STUB : 0);
add_image_function(glsl ? "imageLoad" : "__intrinsic_image_load",
- "__intrinsic_image_load", 0,
- (flags | IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE |
+ "__intrinsic_image_load",
+ &builtin_builder::_image_prototype, 0,
+ (flags | IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE |
IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE |
IMAGE_FUNCTION_READ_ONLY));
add_image_function(glsl ? "imageStore" : "__intrinsic_image_store",
- "__intrinsic_image_store", 1,
+ "__intrinsic_image_store",
+ &builtin_builder::_image_prototype, 1,
(flags | IMAGE_FUNCTION_RETURNS_VOID |
IMAGE_FUNCTION_HAS_VECTOR_DATA_TYPE |
IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE |
IMAGE_FUNCTION_WRITE_ONLY));
+ const unsigned atom_flags = flags | IMAGE_FUNCTION_AVAIL_ATOMIC;
+
add_image_function(glsl ? "imageAtomicAdd" : "__intrinsic_image_atomic_add",
- "__intrinsic_image_atomic_add", 1, flags);
+ "__intrinsic_image_atomic_add",
+ &builtin_builder::_image_prototype, 1, atom_flags);
add_image_function(glsl ? "imageAtomicMin" : "__intrinsic_image_atomic_min",
- "__intrinsic_image_atomic_min", 1, flags);
+ "__intrinsic_image_atomic_min",
+ &builtin_builder::_image_prototype, 1, atom_flags);
add_image_function(glsl ? "imageAtomicMax" : "__intrinsic_image_atomic_max",
- "__intrinsic_image_atomic_max", 1, flags);
+ "__intrinsic_image_atomic_max",
+ &builtin_builder::_image_prototype, 1, atom_flags);
add_image_function(glsl ? "imageAtomicAnd" : "__intrinsic_image_atomic_and",
- "__intrinsic_image_atomic_and", 1, flags);
+ "__intrinsic_image_atomic_and",
+ &builtin_builder::_image_prototype, 1, atom_flags);
add_image_function(glsl ? "imageAtomicOr" : "__intrinsic_image_atomic_or",
- "__intrinsic_image_atomic_or", 1, flags);
+ "__intrinsic_image_atomic_or",
+ &builtin_builder::_image_prototype, 1, atom_flags);
add_image_function(glsl ? "imageAtomicXor" : "__intrinsic_image_atomic_xor",
- "__intrinsic_image_atomic_xor", 1, flags);
+ "__intrinsic_image_atomic_xor",
+ &builtin_builder::_image_prototype, 1, atom_flags);
add_image_function((glsl ? "imageAtomicExchange" :
"__intrinsic_image_atomic_exchange"),
- "__intrinsic_image_atomic_exchange", 1, flags);
+ "__intrinsic_image_atomic_exchange",
+ &builtin_builder::_image_prototype, 1, atom_flags);
add_image_function((glsl ? "imageAtomicCompSwap" :
"__intrinsic_image_atomic_comp_swap"),
- "__intrinsic_image_atomic_comp_swap", 2, flags);
+ "__intrinsic_image_atomic_comp_swap",
+ &builtin_builder::_image_prototype, 2, atom_flags);
+
+ add_image_function(glsl ? "imageSize" : "__intrinsic_image_size",
+ "__intrinsic_image_size",
+ &builtin_builder::_image_size_prototype, 1,
+ flags | IMAGE_FUNCTION_SUPPORTS_FLOAT_DATA_TYPE);
}
ir_variable *
@@ -4314,13 +4410,14 @@ builtin_builder::_barrier()
}
ir_function_signature *
-builtin_builder::_textureQueryLod(const glsl_type *sampler_type,
+builtin_builder::_textureQueryLod(builtin_available_predicate avail,
+ const glsl_type *sampler_type,
const glsl_type *coord_type)
{
ir_variable *s = in_var(sampler_type, "sampler");
ir_variable *coord = in_var(coord_type, "coord");
/* The sampler and coordinate always exist; add optional parameters later. */
- MAKE_SIG(glsl_type::vec2_type, texture_query_lod, 2, s, coord);
+ MAKE_SIG(glsl_type::vec2_type, avail, 2, s, coord);
ir_texture *tex = new(mem_ctx) ir_texture(ir_lod);
tex->coordinate = var_ref(coord);
@@ -4787,8 +4884,10 @@ builtin_builder::_image_prototype(const glsl_type *image_type,
ir_variable *coord = in_var(
glsl_type::ivec(image_type->coordinate_components()), "coord");
- ir_function_signature *sig = new_sig(
- ret_type, shader_image_load_store, 2, image, coord);
+ const builtin_available_predicate avail =
+ (flags & IMAGE_FUNCTION_AVAIL_ATOMIC ? shader_image_atomic :
+ shader_image_load_store);
+ ir_function_signature *sig = new_sig(ret_type, avail, 2, image, coord);
/* Sample index for multisample images. */
if (image_type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS)
@@ -4818,13 +4917,55 @@ builtin_builder::_image_prototype(const glsl_type *image_type,
}
ir_function_signature *
-builtin_builder::_image(const glsl_type *image_type,
+builtin_builder::_image_size_prototype(const glsl_type *image_type,
+ const char *intrinsic_name,
+ unsigned num_arguments,
+ unsigned flags)
+{
+ const glsl_type *ret_type;
+ unsigned num_components = image_type->coordinate_components();
+
+ /* From the ARB_shader_image_size extension:
+ * "Cube images return the dimensions of one face."
+ */
+ if (image_type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE &&
+ !image_type->sampler_array) {
+ num_components = 2;
+ }
+
+ /* FIXME: Add the highp precision qualifier for GLES 3.10 when it is
+ * supported by mesa.
+ */
+ ret_type = glsl_type::get_instance(GLSL_TYPE_INT, num_components, 1);
+
+ ir_variable *image = in_var(image_type, "image");
+ ir_function_signature *sig = new_sig(ret_type, shader_image_size, 1, image);
+
+ /* Set the maximal set of qualifiers allowed for this image
+ * built-in. Function calls with arguments having fewer
+ * qualifiers than present in the prototype are allowed by the
+ * spec, but not with more, i.e. this will make the compiler
+ * accept everything that needs to be accepted, and reject cases
+ * like loads from write-only or stores to read-only images.
+ */
+ image->data.image_read_only = true;
+ image->data.image_write_only = true;
+ image->data.image_coherent = true;
+ image->data.image_volatile = true;
+ image->data.image_restrict = true;
+
+ return sig;
+}
+
+ir_function_signature *
+builtin_builder::_image(image_prototype_ctr prototype,
+ const glsl_type *image_type,
const char *intrinsic_name,
unsigned num_arguments,
unsigned flags)
{
- ir_function_signature *sig = _image_prototype(image_type, intrinsic_name,
- num_arguments, flags);
+ ir_function_signature *sig = (this->*prototype)(image_type, intrinsic_name,
+ num_arguments, flags);
if (flags & IMAGE_FUNCTION_EMIT_STUB) {
ir_factory body(&sig->body, mem_ctx);
diff --git a/src/glsl/builtin_types.cpp b/src/glsl/builtin_types.cpp
index ffbc5e6fdbc..9cf198fd127 100644
--- a/src/glsl/builtin_types.cpp
+++ b/src/glsl/builtin_types.cpp
@@ -182,7 +182,7 @@ const static struct builtin_type_versions {
T(samplerCubeArray, 400, 999)
T(sampler2DRect, 140, 999)
T(samplerBuffer, 140, 999)
- T(sampler2DMS, 150, 999)
+ T(sampler2DMS, 150, 310)
T(sampler2DMSArray, 150, 999)
T(isampler1D, 130, 999)
@@ -194,7 +194,7 @@ const static struct builtin_type_versions {
T(isamplerCubeArray, 400, 999)
T(isampler2DRect, 140, 999)
T(isamplerBuffer, 140, 999)
- T(isampler2DMS, 150, 999)
+ T(isampler2DMS, 150, 310)
T(isampler2DMSArray, 150, 999)
T(usampler1D, 130, 999)
@@ -206,7 +206,7 @@ const static struct builtin_type_versions {
T(usamplerCubeArray, 400, 999)
T(usampler2DRect, 140, 999)
T(usamplerBuffer, 140, 999)
- T(usampler2DMS, 150, 999)
+ T(usampler2DMS, 150, 310)
T(usampler2DMSArray, 150, 999)
T(sampler1DShadow, 110, 999)
@@ -220,40 +220,40 @@ const static struct builtin_type_versions {
T(struct_gl_DepthRangeParameters, 110, 100)
T(image1D, 420, 999)
- T(image2D, 420, 999)
- T(image3D, 420, 999)
+ T(image2D, 420, 310)
+ T(image3D, 420, 310)
T(image2DRect, 420, 999)
- T(imageCube, 420, 999)
+ T(imageCube, 420, 310)
T(imageBuffer, 420, 999)
T(image1DArray, 420, 999)
- T(image2DArray, 420, 999)
+ T(image2DArray, 420, 310)
T(imageCubeArray, 420, 999)
T(image2DMS, 420, 999)
T(image2DMSArray, 420, 999)
T(iimage1D, 420, 999)
- T(iimage2D, 420, 999)
- T(iimage3D, 420, 999)
+ T(iimage2D, 420, 310)
+ T(iimage3D, 420, 310)
T(iimage2DRect, 420, 999)
- T(iimageCube, 420, 999)
+ T(iimageCube, 420, 310)
T(iimageBuffer, 420, 999)
T(iimage1DArray, 420, 999)
- T(iimage2DArray, 420, 999)
+ T(iimage2DArray, 420, 310)
T(iimageCubeArray, 420, 999)
T(iimage2DMS, 420, 999)
T(iimage2DMSArray, 420, 999)
T(uimage1D, 420, 999)
- T(uimage2D, 420, 999)
- T(uimage3D, 420, 999)
+ T(uimage2D, 420, 310)
+ T(uimage3D, 420, 310)
T(uimage2DRect, 420, 999)
- T(uimageCube, 420, 999)
+ T(uimageCube, 420, 310)
T(uimageBuffer, 420, 999)
T(uimage1DArray, 420, 999)
- T(uimage2DArray, 420, 999)
+ T(uimage2DArray, 420, 310)
T(uimageCubeArray, 420, 999)
T(uimage2DMS, 420, 999)
T(uimage2DMSArray, 420, 999)
- T(atomic_uint, 420, 999)
+ T(atomic_uint, 420, 310)
};
static const glsl_type *const deprecated_types[] = {
diff --git a/src/glsl/builtin_variables.cpp b/src/glsl/builtin_variables.cpp
index 53d3500b1f4..dd7804f7b8c 100644
--- a/src/glsl/builtin_variables.cpp
+++ b/src/glsl/builtin_variables.cpp
@@ -744,25 +744,31 @@ builtin_variable_generator::generate_constants()
*/
}
- if (state->is_version(420, 0) ||
+ if (state->is_version(420, 310) ||
state->ARB_shader_image_load_store_enable) {
add_const("gl_MaxImageUnits",
state->Const.MaxImageUnits);
- add_const("gl_MaxCombinedImageUnitsAndFragmentOutputs",
- state->Const.MaxCombinedImageUnitsAndFragmentOutputs);
- add_const("gl_MaxImageSamples",
- state->Const.MaxImageSamples);
add_const("gl_MaxVertexImageUniforms",
state->Const.MaxVertexImageUniforms);
- add_const("gl_MaxTessControlImageUniforms", 0);
- add_const("gl_MaxTessEvaluationImageUniforms", 0);
- add_const("gl_MaxGeometryImageUniforms",
- state->Const.MaxGeometryImageUniforms);
add_const("gl_MaxFragmentImageUniforms",
state->Const.MaxFragmentImageUniforms);
add_const("gl_MaxCombinedImageUniforms",
state->Const.MaxCombinedImageUniforms);
+ if (!state->es_shader) {
+ add_const("gl_MaxCombinedImageUnitsAndFragmentOutputs",
+ state->Const.MaxCombinedShaderOutputResources);
+ add_const("gl_MaxImageSamples",
+ state->Const.MaxImageSamples);
+ add_const("gl_MaxGeometryImageUniforms",
+ state->Const.MaxGeometryImageUniforms);
+ }
+
+ if (state->is_version(450, 310)) {
+ add_const("gl_MaxCombinedShaderOutputResources",
+ state->Const.MaxCombinedShaderOutputResources);
+ }
+
if (state->is_version(400, 0) ||
state->ARB_tessellation_shader_enable) {
add_const("gl_MaxTessControlImageUniforms",
diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y
index dd5ec2a30b5..18e50afe476 100644
--- a/src/glsl/glcpp/glcpp-parse.y
+++ b/src/glsl/glcpp/glcpp-parse.y
@@ -2478,6 +2478,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
if (extensions->ARB_shader_image_load_store)
add_builtin_define(parser, "GL_ARB_shader_image_load_store", 1);
+ if (extensions->ARB_shader_image_size)
+ add_builtin_define(parser, "GL_ARB_shader_image_size", 1);
+
if (extensions->ARB_derivative_control)
add_builtin_define(parser, "GL_ARB_derivative_control", 1);
diff --git a/src/glsl/glsl_lexer.ll b/src/glsl/glsl_lexer.ll
index efa0bb68099..24998c19467 100644
--- a/src/glsl/glsl_lexer.ll
+++ b/src/glsl/glsl_lexer.ll
@@ -343,9 +343,10 @@ usampler2DArray KEYWORD(130, 300, 130, 300, USAMPLER2DARRAY);
/* additional keywords in ARB_texture_multisample, included in GLSL 1.50 */
/* these are reserved but not defined in GLSL 3.00 */
-sampler2DMS KEYWORD_WITH_ALT(150, 300, 150, 0, yyextra->ARB_texture_multisample_enable, SAMPLER2DMS);
-isampler2DMS KEYWORD_WITH_ALT(150, 300, 150, 0, yyextra->ARB_texture_multisample_enable, ISAMPLER2DMS);
-usampler2DMS KEYWORD_WITH_ALT(150, 300, 150, 0, yyextra->ARB_texture_multisample_enable, USAMPLER2DMS);
+ /* [iu]sampler2DMS are defined in GLSL ES 3.10 */
+sampler2DMS KEYWORD_WITH_ALT(150, 300, 150, 310, yyextra->ARB_texture_multisample_enable, SAMPLER2DMS);
+isampler2DMS KEYWORD_WITH_ALT(150, 300, 150, 310, yyextra->ARB_texture_multisample_enable, ISAMPLER2DMS);
+usampler2DMS KEYWORD_WITH_ALT(150, 300, 150, 310, yyextra->ARB_texture_multisample_enable, USAMPLER2DMS);
sampler2DMSArray KEYWORD_WITH_ALT(150, 300, 150, 0, yyextra->ARB_texture_multisample_enable, SAMPLER2DMSARRAY);
isampler2DMSArray KEYWORD_WITH_ALT(150, 300, 150, 0, yyextra->ARB_texture_multisample_enable, ISAMPLER2DMSARRAY);
usampler2DMSArray KEYWORD_WITH_ALT(150, 300, 150, 0, yyextra->ARB_texture_multisample_enable, USAMPLER2DMSARRAY);
@@ -368,35 +369,35 @@ precise KEYWORD_WITH_ALT(400, 0, 400, 0, yyextra->ARB_gpu_shader5_enable, PRECI
/* keywords available with ARB_shader_image_load_store */
image1D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE1D);
-image2D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2D);
-image3D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE3D);
+image2D KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IMAGE2D);
+image3D KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IMAGE3D);
image2DRect KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DRECT);
-imageCube KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGECUBE);
+imageCube KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IMAGECUBE);
imageBuffer KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGEBUFFER);
image1DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE1DARRAY);
-image2DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DARRAY);
+image2DArray KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IMAGE2DARRAY);
imageCubeArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGECUBEARRAY);
image2DMS KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DMS);
image2DMSArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2DMSARRAY);
iimage1D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE1D);
-iimage2D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2D);
-iimage3D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE3D);
+iimage2D KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IIMAGE2D);
+iimage3D KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IIMAGE3D);
iimage2DRect KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DRECT);
-iimageCube KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGECUBE);
+iimageCube KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IIMAGECUBE);
iimageBuffer KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGEBUFFER);
iimage1DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE1DARRAY);
-iimage2DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DARRAY);
+iimage2DArray KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DARRAY);
iimageCubeArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGECUBEARRAY);
iimage2DMS KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DMS);
iimage2DMSArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IIMAGE2DMSARRAY);
uimage1D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE1D);
-uimage2D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2D);
-uimage3D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE3D);
+uimage2D KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, UIMAGE2D);
+uimage3D KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, UIMAGE3D);
uimage2DRect KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DRECT);
-uimageCube KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGECUBE);
+uimageCube KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, UIMAGECUBE);
uimageBuffer KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGEBUFFER);
uimage1DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE1DARRAY);
-uimage2DArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DARRAY);
+uimage2DArray KEYWORD_WITH_ALT(130, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DARRAY);
uimageCubeArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGECUBEARRAY);
uimage2DMS KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DMS);
uimage2DMSArray KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, UIMAGE2DMSARRAY);
@@ -405,11 +406,11 @@ image2DShadow KEYWORD(130, 300, 0, 0, IMAGE2DSHADOW);
image1DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE1DARRAYSHADOW);
image2DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE2DARRAYSHADOW);
-coherent KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, COHERENT);
-volatile KEYWORD_WITH_ALT(110, 100, 420, 0, yyextra->ARB_shader_image_load_store_enable, VOLATILE);
-restrict KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, RESTRICT);
-readonly KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, READONLY);
-writeonly KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, WRITEONLY);
+coherent KEYWORD_WITH_ALT(420, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, COHERENT);
+volatile KEYWORD_WITH_ALT(110, 100, 420, 310, yyextra->ARB_shader_image_load_store_enable, VOLATILE);
+restrict KEYWORD_WITH_ALT(420, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, RESTRICT);
+readonly KEYWORD_WITH_ALT(420, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, READONLY);
+writeonly KEYWORD_WITH_ALT(420, 300, 420, 310, yyextra->ARB_shader_image_load_store_enable, WRITEONLY);
atomic_uint KEYWORD_WITH_ALT(420, 300, 420, 310, yyextra->ARB_shader_atomic_counters_enable, ATOMIC_UINT);
diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
index 97648c15ccc..e1b390844d3 100644
--- a/src/glsl/glsl_parser.yy
+++ b/src/glsl/glsl_parser.yy
@@ -1258,56 +1258,65 @@ layout_qualifier_id:
/* Layout qualifiers for ARB_shader_image_load_store. */
if (state->ARB_shader_image_load_store_enable ||
- state->is_version(420, 0)) {
+ state->is_version(420, 310)) {
if (!$$.flags.i) {
static const struct {
const char *name;
GLenum format;
glsl_base_type base_type;
+ /** Minimum desktop GLSL version required for the image
+ * format. Use 130 if already present in the original
+ * ARB extension.
+ */
+ unsigned required_glsl;
+ /** Minimum GLSL ES version required for the image format. */
+ unsigned required_essl;
} map[] = {
- { "rgba32f", GL_RGBA32F, GLSL_TYPE_FLOAT },
- { "rgba16f", GL_RGBA16F, GLSL_TYPE_FLOAT },
- { "rg32f", GL_RG32F, GLSL_TYPE_FLOAT },
- { "rg16f", GL_RG16F, GLSL_TYPE_FLOAT },
- { "r11f_g11f_b10f", GL_R11F_G11F_B10F, GLSL_TYPE_FLOAT },
- { "r32f", GL_R32F, GLSL_TYPE_FLOAT },
- { "r16f", GL_R16F, GLSL_TYPE_FLOAT },
- { "rgba32ui", GL_RGBA32UI, GLSL_TYPE_UINT },
- { "rgba16ui", GL_RGBA16UI, GLSL_TYPE_UINT },
- { "rgb10_a2ui", GL_RGB10_A2UI, GLSL_TYPE_UINT },
- { "rgba8ui", GL_RGBA8UI, GLSL_TYPE_UINT },
- { "rg32ui", GL_RG32UI, GLSL_TYPE_UINT },
- { "rg16ui", GL_RG16UI, GLSL_TYPE_UINT },
- { "rg8ui", GL_RG8UI, GLSL_TYPE_UINT },
- { "r32ui", GL_R32UI, GLSL_TYPE_UINT },
- { "r16ui", GL_R16UI, GLSL_TYPE_UINT },
- { "r8ui", GL_R8UI, GLSL_TYPE_UINT },
- { "rgba32i", GL_RGBA32I, GLSL_TYPE_INT },
- { "rgba16i", GL_RGBA16I, GLSL_TYPE_INT },
- { "rgba8i", GL_RGBA8I, GLSL_TYPE_INT },
- { "rg32i", GL_RG32I, GLSL_TYPE_INT },
- { "rg16i", GL_RG16I, GLSL_TYPE_INT },
- { "rg8i", GL_RG8I, GLSL_TYPE_INT },
- { "r32i", GL_R32I, GLSL_TYPE_INT },
- { "r16i", GL_R16I, GLSL_TYPE_INT },
- { "r8i", GL_R8I, GLSL_TYPE_INT },
- { "rgba16", GL_RGBA16, GLSL_TYPE_FLOAT },
- { "rgb10_a2", GL_RGB10_A2, GLSL_TYPE_FLOAT },
- { "rgba8", GL_RGBA8, GLSL_TYPE_FLOAT },
- { "rg16", GL_RG16, GLSL_TYPE_FLOAT },
- { "rg8", GL_RG8, GLSL_TYPE_FLOAT },
- { "r16", GL_R16, GLSL_TYPE_FLOAT },
- { "r8", GL_R8, GLSL_TYPE_FLOAT },
- { "rgba16_snorm", GL_RGBA16_SNORM, GLSL_TYPE_FLOAT },
- { "rgba8_snorm", GL_RGBA8_SNORM, GLSL_TYPE_FLOAT },
- { "rg16_snorm", GL_RG16_SNORM, GLSL_TYPE_FLOAT },
- { "rg8_snorm", GL_RG8_SNORM, GLSL_TYPE_FLOAT },
- { "r16_snorm", GL_R16_SNORM, GLSL_TYPE_FLOAT },
- { "r8_snorm", GL_R8_SNORM, GLSL_TYPE_FLOAT }
+ { "rgba32f", GL_RGBA32F, GLSL_TYPE_FLOAT, 130, 310 },
+ { "rgba16f", GL_RGBA16F, GLSL_TYPE_FLOAT, 130, 310 },
+ { "rg32f", GL_RG32F, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rg16f", GL_RG16F, GLSL_TYPE_FLOAT, 130, 0 },
+ { "r11f_g11f_b10f", GL_R11F_G11F_B10F, GLSL_TYPE_FLOAT, 130, 0 },
+ { "r32f", GL_R32F, GLSL_TYPE_FLOAT, 130, 310 },
+ { "r16f", GL_R16F, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rgba32ui", GL_RGBA32UI, GLSL_TYPE_UINT, 130, 310 },
+ { "rgba16ui", GL_RGBA16UI, GLSL_TYPE_UINT, 130, 310 },
+ { "rgb10_a2ui", GL_RGB10_A2UI, GLSL_TYPE_UINT, 130, 0 },
+ { "rgba8ui", GL_RGBA8UI, GLSL_TYPE_UINT, 130, 310 },
+ { "rg32ui", GL_RG32UI, GLSL_TYPE_UINT, 130, 0 },
+ { "rg16ui", GL_RG16UI, GLSL_TYPE_UINT, 130, 0 },
+ { "rg8ui", GL_RG8UI, GLSL_TYPE_UINT, 130, 0 },
+ { "r32ui", GL_R32UI, GLSL_TYPE_UINT, 130, 310 },
+ { "r16ui", GL_R16UI, GLSL_TYPE_UINT, 130, 0 },
+ { "r8ui", GL_R8UI, GLSL_TYPE_UINT, 130, 0 },
+ { "rgba32i", GL_RGBA32I, GLSL_TYPE_INT, 130, 310 },
+ { "rgba16i", GL_RGBA16I, GLSL_TYPE_INT, 130, 310 },
+ { "rgba8i", GL_RGBA8I, GLSL_TYPE_INT, 130, 310 },
+ { "rg32i", GL_RG32I, GLSL_TYPE_INT, 130, 0 },
+ { "rg16i", GL_RG16I, GLSL_TYPE_INT, 130, 0 },
+ { "rg8i", GL_RG8I, GLSL_TYPE_INT, 130, 0 },
+ { "r32i", GL_R32I, GLSL_TYPE_INT, 130, 310 },
+ { "r16i", GL_R16I, GLSL_TYPE_INT, 130, 0 },
+ { "r8i", GL_R8I, GLSL_TYPE_INT, 130, 0 },
+ { "rgba16", GL_RGBA16, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rgb10_a2", GL_RGB10_A2, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rgba8", GL_RGBA8, GLSL_TYPE_FLOAT, 130, 310 },
+ { "rg16", GL_RG16, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rg8", GL_RG8, GLSL_TYPE_FLOAT, 130, 0 },
+ { "r16", GL_R16, GLSL_TYPE_FLOAT, 130, 0 },
+ { "r8", GL_R8, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rgba16_snorm", GL_RGBA16_SNORM, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rgba8_snorm", GL_RGBA8_SNORM, GLSL_TYPE_FLOAT, 130, 310 },
+ { "rg16_snorm", GL_RG16_SNORM, GLSL_TYPE_FLOAT, 130, 0 },
+ { "rg8_snorm", GL_RG8_SNORM, GLSL_TYPE_FLOAT, 130, 0 },
+ { "r16_snorm", GL_R16_SNORM, GLSL_TYPE_FLOAT, 130, 0 },
+ { "r8_snorm", GL_R8_SNORM, GLSL_TYPE_FLOAT, 130, 0 }
};
for (unsigned i = 0; i < ARRAY_SIZE(map); i++) {
- if (match_layout_qualifier($1, map[i].name, state) == 0) {
+ if (state->is_version(map[i].required_glsl,
+ map[i].required_essl) &&
+ match_layout_qualifier($1, map[i].name, state) == 0) {
$$.flags.q.explicit_image_format = 1;
$$.image_format = map[i].format;
$$.image_base_type = map[i].base_type;
@@ -1521,11 +1530,10 @@ layout_qualifier_id:
"invalid %s of %d specified",
local_size_qualifiers[i], $3);
YYERROR;
- } else if (!state->is_version(430, 0) &&
- !state->ARB_compute_shader_enable) {
+ } else if (!state->has_compute_shader()) {
_mesa_glsl_error(& @3, state,
"%s qualifier requires GLSL 4.30 or "
- "ARB_compute_shader",
+ "GLSL ES 3.10 or ARB_compute_shader",
local_size_qualifiers[i]);
YYERROR;
} else {
diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
index ae2f35697fb..ca772e8ab33 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -143,7 +143,7 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->Const.MaxComputeWorkGroupSize[i] = ctx->Const.MaxComputeWorkGroupSize[i];
this->Const.MaxImageUnits = ctx->Const.MaxImageUnits;
- this->Const.MaxCombinedImageUnitsAndFragmentOutputs = ctx->Const.MaxCombinedImageUnitsAndFragmentOutputs;
+ this->Const.MaxCombinedShaderOutputResources = ctx->Const.MaxCombinedShaderOutputResources;
this->Const.MaxImageSamples = ctx->Const.MaxImageSamples;
this->Const.MaxVertexImageUniforms = ctx->Const.Program[MESA_SHADER_VERTEX].MaxImageUniforms;
this->Const.MaxTessControlImageUniforms = ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxImageUniforms;
@@ -601,6 +601,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters),
EXT(ARB_shader_bit_encoding, true, false, ARB_shader_bit_encoding),
EXT(ARB_shader_image_load_store, true, false, ARB_shader_image_load_store),
+ EXT(ARB_shader_image_size, true, false, ARB_shader_image_size),
EXT(ARB_shader_precision, true, false, ARB_shader_precision),
EXT(ARB_shader_stencil_export, true, false, ARB_shader_stencil_export),
EXT(ARB_shader_storage_buffer_object, true, false, ARB_shader_storage_buffer_object),
diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h
index eb325f04eed..e2145bea5fa 100644
--- a/src/glsl/glsl_parser_extras.h
+++ b/src/glsl/glsl_parser_extras.h
@@ -236,6 +236,11 @@ struct _mesa_glsl_parse_state {
return ARB_shading_language_420pack_enable || is_version(420, 0);
}
+ bool has_compute_shader() const
+ {
+ return ARB_compute_shader_enable || is_version(430, 310);
+ }
+
void process_version_directive(YYLTYPE *locp, int version,
const char *ident);
@@ -390,7 +395,7 @@ struct _mesa_glsl_parse_state {
/* ARB_shader_image_load_store */
unsigned MaxImageUnits;
- unsigned MaxCombinedImageUnitsAndFragmentOutputs;
+ unsigned MaxCombinedShaderOutputResources;
unsigned MaxImageSamples;
unsigned MaxVertexImageUniforms;
unsigned MaxTessControlImageUniforms;
@@ -495,6 +500,8 @@ struct _mesa_glsl_parse_state {
bool ARB_shader_bit_encoding_warn;
bool ARB_shader_image_load_store_enable;
bool ARB_shader_image_load_store_warn;
+ bool ARB_shader_image_size_enable;
+ bool ARB_shader_image_size_warn;
bool ARB_shader_precision_enable;
bool ARB_shader_precision_warn;
bool ARB_shader_stencil_export_enable;
diff --git a/src/glsl/link_uniform_initializers.cpp b/src/glsl/link_uniform_initializers.cpp
index c482fbfdfb2..f238513f174 100644
--- a/src/glsl/link_uniform_initializers.cpp
+++ b/src/glsl/link_uniform_initializers.cpp
@@ -101,8 +101,13 @@ copy_constant_to_storage(union gl_constant_value *storage,
}
}
+/**
+ * Initialize an opaque uniform from the value of an explicit binding
+ * qualifier specified in the shader. Atomic counters are different because
+ * they have no storage and should be handled elsewhere.
+ */
void
-set_sampler_binding(gl_shader_program *prog, const char *name, int binding)
+set_opaque_binding(gl_shader_program *prog, const char *name, int binding)
{
struct gl_uniform_storage *const storage =
get_storage(prog->UniformStorage, prog->NumUniformStorage, name);
@@ -128,11 +133,20 @@ set_sampler_binding(gl_shader_program *prog, const char *name, int binding)
for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
gl_shader *shader = prog->_LinkedShaders[sh];
- if (shader && storage->sampler[sh].active) {
- for (unsigned i = 0; i < elements; i++) {
- unsigned index = storage->sampler[sh].index + i;
+ if (shader) {
+ if (storage->type->base_type == GLSL_TYPE_SAMPLER &&
+ storage->sampler[sh].active) {
+ for (unsigned i = 0; i < elements; i++) {
+ const unsigned index = storage->sampler[sh].index + i;
+ shader->SamplerUnits[index] = storage->storage[i].i;
+ }
- shader->SamplerUnits[index] = storage->storage[i].i;
+ } else if (storage->type->base_type == GLSL_TYPE_IMAGE &&
+ storage->image[sh].active) {
+ for (unsigned i = 0; i < elements; i++) {
+ const unsigned index = storage->image[sh].index + i;
+ shader->ImageUnits[index] = storage->storage[i].i;
+ }
}
}
}
@@ -268,8 +282,9 @@ link_set_uniform_initializers(struct gl_shader_program *prog,
if (var->data.explicit_binding) {
const glsl_type *const type = var->type;
- if (type->without_array()->is_sampler()) {
- linker::set_sampler_binding(prog, var->name, var->data.binding);
+ if (type->without_array()->is_sampler() ||
+ type->without_array()->is_image()) {
+ linker::set_opaque_binding(prog, var->name, var->data.binding);
} else if (var->is_in_buffer_block()) {
const glsl_type *const iface_type = var->get_interface_type();
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index a7cd82049bd..47f7d2574dd 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -2900,7 +2900,7 @@ check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog)
linker_error(prog, "Too many combined image uniforms\n");
if (total_image_units + fragment_outputs >
- ctx->Const.MaxCombinedImageUnitsAndFragmentOutputs)
+ ctx->Const.MaxCombinedShaderOutputResources)
linker_error(prog, "Too many combined image uniforms and fragment outputs\n");
}
diff --git a/src/glsl/lower_subroutine.cpp b/src/glsl/lower_subroutine.cpp
index b29912ad150..c1aed61a36a 100644
--- a/src/glsl/lower_subroutine.cpp
+++ b/src/glsl/lower_subroutine.cpp
@@ -98,7 +98,7 @@ lower_subroutine_visitor::visit_leave(ir_call *ir)
else
last_branch = if_tree(equal(subr_to_int(var), lc), new_call, last_branch);
- if (s > 0)
+ if (return_deref && s > 0)
return_deref = return_deref->clone(mem_ctx, NULL);
}
if (last_branch)
diff --git a/src/glsl/nir/glsl_to_nir.cpp b/src/glsl/nir/glsl_to_nir.cpp
index 27dabd3b8f2..af97da9cc21 100644
--- a/src/glsl/nir/glsl_to_nir.cpp
+++ b/src/glsl/nir/glsl_to_nir.cpp
@@ -26,6 +26,7 @@
*/
#include "glsl_to_nir.h"
+#include "nir_control_flow.h"
#include "ir_visitor.h"
#include "ir_hierarchical_visitor.h"
#include "ir.h"
@@ -43,7 +44,7 @@ namespace {
class nir_visitor : public ir_visitor
{
public:
- nir_visitor(nir_shader *shader, struct gl_shader *sh, gl_shader_stage stage);
+ nir_visitor(nir_shader *shader, gl_shader *sh);
~nir_visitor();
virtual void visit(ir_variable *);
@@ -86,7 +87,6 @@ private:
struct gl_shader *sh;
nir_shader *shader;
- gl_shader_stage stage;
nir_function_impl *impl;
exec_list *cf_node_list;
nir_instr *result; /* result of the expression tree last visited */
@@ -133,9 +133,9 @@ private:
nir_shader *
glsl_to_nir(struct gl_shader *sh, const nir_shader_compiler_options *options)
{
- nir_shader *shader = nir_shader_create(NULL, options);
+ nir_shader *shader = nir_shader_create(NULL, sh->Stage, options);
- nir_visitor v1(shader, sh, sh->Stage);
+ nir_visitor v1(shader, sh);
nir_function_visitor v2(&v1);
v2.run(sh->ir);
visit_exec_list(sh->ir, &v1);
@@ -143,13 +143,11 @@ glsl_to_nir(struct gl_shader *sh, const nir_shader_compiler_options *options)
return shader;
}
-nir_visitor::nir_visitor(nir_shader *shader, struct gl_shader *sh,
- gl_shader_stage stage)
+nir_visitor::nir_visitor(nir_shader *shader, gl_shader *sh)
{
this->supports_ints = shader->options->native_integers;
this->shader = shader;
this->sh = sh;
- this->stage = stage;
this->is_global = true;
this->var_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
_mesa_key_pointer_equal);
@@ -266,7 +264,7 @@ nir_visitor::visit(ir_variable *ir)
break;
case ir_var_shader_in:
- if (stage == MESA_SHADER_FRAGMENT &&
+ if (shader->stage == MESA_SHADER_FRAGMENT &&
ir->data.location == VARYING_SLOT_FACE) {
/* For whatever reason, GLSL IR makes gl_FrontFacing an input */
var->data.location = SYSTEM_VALUE_FRONT_FACE;
@@ -646,6 +644,8 @@ nir_visitor::visit(ir_call *ir)
op = nir_intrinsic_image_atomic_comp_swap;
} else if (strcmp(ir->callee_name(), "__intrinsic_memory_barrier") == 0) {
op = nir_intrinsic_memory_barrier;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_size") == 0) {
+ op = nir_intrinsic_image_size;
} else {
unreachable("not reached");
}
@@ -671,7 +671,8 @@ nir_visitor::visit(ir_call *ir)
case nir_intrinsic_image_atomic_or:
case nir_intrinsic_image_atomic_xor:
case nir_intrinsic_image_atomic_exchange:
- case nir_intrinsic_image_atomic_comp_swap: {
+ case nir_intrinsic_image_atomic_comp_swap:
+ case nir_intrinsic_image_size: {
nir_ssa_undef_instr *instr_undef =
nir_ssa_undef_instr_create(shader, 1);
nir_instr_insert_after_cf_list(this->cf_node_list,
@@ -686,6 +687,17 @@ nir_visitor::visit(ir_call *ir)
instr->variables[0] = evaluate_deref(&instr->instr, image);
param = param->get_next();
+ /* Set the intrinsic destination. */
+ if (ir->return_deref) {
+ const nir_intrinsic_info *info =
+ &nir_intrinsic_infos[instr->intrinsic];
+ nir_ssa_dest_init(&instr->instr, &instr->dest,
+ info->dest_components, NULL);
+ }
+
+ if (op == nir_intrinsic_image_size)
+ break;
+
/* Set the address argument, extending the coordinate vector to four
* components.
*/
@@ -726,11 +738,6 @@ nir_visitor::visit(ir_call *ir)
instr->src[3] = evaluate_rvalue((ir_dereference *)param);
param = param->get_next();
}
-
- /* Set the intrinsic destination. */
- if (ir->return_deref)
- nir_ssa_dest_init(&instr->instr, &instr->dest,
- ir->return_deref->type->vector_elements, NULL);
break;
}
case nir_intrinsic_memory_barrier:
diff --git a/src/glsl/nir/nir.c b/src/glsl/nir/nir.c
index 2f7cbae42be..77cc4f078a3 100644
--- a/src/glsl/nir/nir.c
+++ b/src/glsl/nir/nir.c
@@ -26,10 +26,13 @@
*/
#include "nir.h"
+#include "nir_control_flow_private.h"
#include <assert.h>
nir_shader *
-nir_shader_create(void *mem_ctx, const nir_shader_compiler_options *options)
+nir_shader_create(void *mem_ctx,
+ gl_shader_stage stage,
+ const nir_shader_compiler_options *options)
{
nir_shader *shader = ralloc(mem_ctx, nir_shader);
@@ -49,6 +52,8 @@ nir_shader_create(void *mem_ctx, const nir_shader_compiler_options *options)
shader->num_outputs = 0;
shader->num_uniforms = 0;
+ shader->stage = stage;
+
return shader;
}
@@ -180,11 +185,6 @@ nir_alu_dest_copy(nir_alu_dest *dest, const nir_alu_dest *src, void *mem_ctx)
dest->saturate = src->saturate;
}
-static inline void
-block_add_pred(nir_block *block, nir_block *pred)
-{
- _mesa_set_add(block->predecessors, pred);
-}
static void
cf_init(nir_cf_node *node, nir_cf_node_type type)
@@ -194,45 +194,6 @@ cf_init(nir_cf_node *node, nir_cf_node_type type)
node->type = type;
}
-static void
-link_blocks(nir_block *pred, nir_block *succ1, nir_block *succ2)
-{
- pred->successors[0] = succ1;
- block_add_pred(succ1, pred);
-
- pred->successors[1] = succ2;
- if (succ2 != NULL)
- block_add_pred(succ2, pred);
-}
-
-static void
-unlink_blocks(nir_block *pred, nir_block *succ)
-{
- if (pred->successors[0] == succ) {
- pred->successors[0] = pred->successors[1];
- pred->successors[1] = NULL;
- } else {
- assert(pred->successors[1] == succ);
- pred->successors[1] = NULL;
- }
-
- struct set_entry *entry = _mesa_set_search(succ->predecessors, pred);
-
- assert(entry);
-
- _mesa_set_remove(succ->predecessors, entry);
-}
-
-static void
-unlink_block_successors(nir_block *block)
-{
- if (block->successors[0] != NULL)
- unlink_blocks(block, block->successors[0]);
- if (block->successors[1] != NULL)
- unlink_blocks(block, block->successors[1]);
-}
-
-
nir_function_impl *
nir_function_impl_create(nir_function_overload *overload)
{
@@ -262,14 +223,12 @@ nir_function_impl_create(nir_function_overload *overload)
nir_block *end_block = nir_block_create(mem_ctx);
start_block->cf_node.parent = &impl->cf_node;
end_block->cf_node.parent = &impl->cf_node;
- impl->start_block = start_block;
impl->end_block = end_block;
exec_list_push_tail(&impl->body, &start_block->cf_node.node);
start_block->successors[0] = end_block;
- block_add_pred(end_block, start_block);
-
+ _mesa_set_add(end_block->predecessors, start_block);
return impl;
}
@@ -335,7 +294,7 @@ nir_loop_create(void *mem_ctx)
body->cf_node.parent = &loop->cf_node;
body->successors[0] = body;
- block_add_pred(body, body);
+ _mesa_set_add(body->predecessors, body);
return loop;
}
@@ -646,250 +605,6 @@ nir_deref_get_const_initializer_load(nir_shader *shader, nir_deref_var *deref)
return load;
}
-/**
- * \name Control flow modification
- *
- * These functions modify the control flow tree while keeping the control flow
- * graph up-to-date. The invariants respected are:
- * 1. Each then statement, else statement, or loop body must have at least one
- * control flow node.
- * 2. Each if-statement and loop must have one basic block before it and one
- * after.
- * 3. Two basic blocks cannot be directly next to each other.
- * 4. If a basic block has a jump instruction, there must be only one and it
- * must be at the end of the block.
- * 5. The CFG must always be connected - this means that we must insert a fake
- * CFG edge for loops with no break statement.
- *
- * The purpose of the second one is so that we have places to insert code during
- * GCM, as well as eliminating the possibility of critical edges.
- */
-/*@{*/
-
-static void
-link_non_block_to_block(nir_cf_node *node, nir_block *block)
-{
- if (node->type == nir_cf_node_if) {
- /*
- * We're trying to link an if to a block after it; this just means linking
- * the last block of the then and else branches.
- */
-
- nir_if *if_stmt = nir_cf_node_as_if(node);
-
- nir_cf_node *last_then = nir_if_last_then_node(if_stmt);
- assert(last_then->type == nir_cf_node_block);
- nir_block *last_then_block = nir_cf_node_as_block(last_then);
-
- nir_cf_node *last_else = nir_if_last_else_node(if_stmt);
- assert(last_else->type == nir_cf_node_block);
- nir_block *last_else_block = nir_cf_node_as_block(last_else);
-
- if (exec_list_is_empty(&last_then_block->instr_list) ||
- nir_block_last_instr(last_then_block)->type != nir_instr_type_jump) {
- unlink_block_successors(last_then_block);
- link_blocks(last_then_block, block, NULL);
- }
-
- if (exec_list_is_empty(&last_else_block->instr_list) ||
- nir_block_last_instr(last_else_block)->type != nir_instr_type_jump) {
- unlink_block_successors(last_else_block);
- link_blocks(last_else_block, block, NULL);
- }
- } else {
- assert(node->type == nir_cf_node_loop);
-
- /*
- * We can only get to this codepath if we're inserting a new loop, or
- * at least a loop with no break statements; we can't insert break
- * statements into a loop when we haven't inserted it into the CFG
- * because we wouldn't know which block comes after the loop
- * and therefore, which block should be the successor of the block with
- * the break). Therefore, we need to insert a fake edge (see invariant
- * #5).
- */
-
- nir_loop *loop = nir_cf_node_as_loop(node);
-
- nir_cf_node *last = nir_loop_last_cf_node(loop);
- assert(last->type == nir_cf_node_block);
- nir_block *last_block = nir_cf_node_as_block(last);
-
- last_block->successors[1] = block;
- block_add_pred(block, last_block);
- }
-}
-
-static void
-link_block_to_non_block(nir_block *block, nir_cf_node *node)
-{
- if (node->type == nir_cf_node_if) {
- /*
- * We're trying to link a block to an if after it; this just means linking
- * the block to the first block of the then and else branches.
- */
-
- nir_if *if_stmt = nir_cf_node_as_if(node);
-
- nir_cf_node *first_then = nir_if_first_then_node(if_stmt);
- assert(first_then->type == nir_cf_node_block);
- nir_block *first_then_block = nir_cf_node_as_block(first_then);
-
- nir_cf_node *first_else = nir_if_first_else_node(if_stmt);
- assert(first_else->type == nir_cf_node_block);
- nir_block *first_else_block = nir_cf_node_as_block(first_else);
-
- unlink_block_successors(block);
- link_blocks(block, first_then_block, first_else_block);
- } else {
- /*
- * For similar reasons as the corresponding case in
- * link_non_block_to_block(), don't worry about if the loop header has
- * any predecessors that need to be unlinked.
- */
-
- assert(node->type == nir_cf_node_loop);
-
- nir_loop *loop = nir_cf_node_as_loop(node);
-
- nir_cf_node *loop_header = nir_loop_first_cf_node(loop);
- assert(loop_header->type == nir_cf_node_block);
- nir_block *loop_header_block = nir_cf_node_as_block(loop_header);
-
- unlink_block_successors(block);
- link_blocks(block, loop_header_block, NULL);
- }
-
-}
-
-/**
- * Takes a basic block and inserts a new empty basic block before it, making its
- * predecessors point to the new block. This essentially splits the block into
- * an empty header and a body so that another non-block CF node can be inserted
- * between the two. Note that this does *not* link the two basic blocks, so
- * some kind of cleanup *must* be performed after this call.
- */
-
-static nir_block *
-split_block_beginning(nir_block *block)
-{
- nir_block *new_block = nir_block_create(ralloc_parent(block));
- new_block->cf_node.parent = block->cf_node.parent;
- exec_node_insert_node_before(&block->cf_node.node, &new_block->cf_node.node);
-
- struct set_entry *entry;
- set_foreach(block->predecessors, entry) {
- nir_block *pred = (nir_block *) entry->key;
-
- unlink_blocks(pred, block);
- link_blocks(pred, new_block, NULL);
- }
-
- return new_block;
-}
-
-static void
-rewrite_phi_preds(nir_block *block, nir_block *old_pred, nir_block *new_pred)
-{
- nir_foreach_instr_safe(block, instr) {
- if (instr->type != nir_instr_type_phi)
- break;
-
- nir_phi_instr *phi = nir_instr_as_phi(instr);
- nir_foreach_phi_src(phi, src) {
- if (src->pred == old_pred) {
- src->pred = new_pred;
- break;
- }
- }
- }
-}
-
-/**
- * Moves the successors of source to the successors of dest, leaving both
- * successors of source NULL.
- */
-
-static void
-move_successors(nir_block *source, nir_block *dest)
-{
- nir_block *succ1 = source->successors[0];
- nir_block *succ2 = source->successors[1];
-
- if (succ1) {
- unlink_blocks(source, succ1);
- rewrite_phi_preds(succ1, source, dest);
- }
-
- if (succ2) {
- unlink_blocks(source, succ2);
- rewrite_phi_preds(succ2, source, dest);
- }
-
- unlink_block_successors(dest);
- link_blocks(dest, succ1, succ2);
-}
-
-static nir_block *
-split_block_end(nir_block *block)
-{
- nir_block *new_block = nir_block_create(ralloc_parent(block));
- new_block->cf_node.parent = block->cf_node.parent;
- exec_node_insert_after(&block->cf_node.node, &new_block->cf_node.node);
-
- move_successors(block, new_block);
-
- return new_block;
-}
-
-/**
- * Inserts a non-basic block between two basic blocks and links them together.
- */
-
-static void
-insert_non_block(nir_block *before, nir_cf_node *node, nir_block *after)
-{
- node->parent = before->cf_node.parent;
- exec_node_insert_after(&before->cf_node.node, &node->node);
- link_block_to_non_block(before, node);
- link_non_block_to_block(node, after);
-}
-
-/**
- * Inserts a non-basic block before a basic block.
- */
-
-static void
-insert_non_block_before_block(nir_cf_node *node, nir_block *block)
-{
- /* split off the beginning of block into new_block */
- nir_block *new_block = split_block_beginning(block);
-
- /* insert our node in between new_block and block */
- insert_non_block(new_block, node, block);
-}
-
-static void
-insert_non_block_after_block(nir_block *block, nir_cf_node *node)
-{
- /* split off the end of block into new_block */
- nir_block *new_block = split_block_end(block);
-
- /* insert our node in between block and new_block */
- insert_non_block(block, node, new_block);
-}
-
-/* walk up the control flow tree to find the innermost enclosed loop */
-static nir_loop *
-nearest_loop(nir_cf_node *node)
-{
- while (node->type != nir_cf_node_loop) {
- node = node->parent;
- }
-
- return nir_cf_node_as_loop(node);
-}
-
nir_function_impl *
nir_cf_node_get_function(nir_cf_node *node)
{
@@ -900,384 +615,6 @@ nir_cf_node_get_function(nir_cf_node *node)
return nir_cf_node_as_function(node);
}
-/*
- * update the CFG after a jump instruction has been added to the end of a block
- */
-
-static void
-handle_jump(nir_block *block)
-{
- nir_instr *instr = nir_block_last_instr(block);
- nir_jump_instr *jump_instr = nir_instr_as_jump(instr);
-
- unlink_block_successors(block);
-
- nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
- nir_metadata_preserve(impl, nir_metadata_none);
-
- if (jump_instr->type == nir_jump_break ||
- jump_instr->type == nir_jump_continue) {
- nir_loop *loop = nearest_loop(&block->cf_node);
-
- if (jump_instr->type == nir_jump_continue) {
- nir_cf_node *first_node = nir_loop_first_cf_node(loop);
- assert(first_node->type == nir_cf_node_block);
- nir_block *first_block = nir_cf_node_as_block(first_node);
- link_blocks(block, first_block, NULL);
- } else {
- nir_cf_node *after = nir_cf_node_next(&loop->cf_node);
- assert(after->type == nir_cf_node_block);
- nir_block *after_block = nir_cf_node_as_block(after);
- link_blocks(block, after_block, NULL);
-
- /* If we inserted a fake link, remove it */
- nir_cf_node *last = nir_loop_last_cf_node(loop);
- assert(last->type == nir_cf_node_block);
- nir_block *last_block = nir_cf_node_as_block(last);
- if (last_block->successors[1] != NULL)
- unlink_blocks(last_block, after_block);
- }
- } else {
- assert(jump_instr->type == nir_jump_return);
- link_blocks(block, impl->end_block, NULL);
- }
-}
-
-static void
-handle_remove_jump(nir_block *block, nir_jump_type type)
-{
- unlink_block_successors(block);
-
- if (exec_node_is_tail_sentinel(block->cf_node.node.next)) {
- nir_cf_node *parent = block->cf_node.parent;
- if (parent->type == nir_cf_node_if) {
- nir_cf_node *next = nir_cf_node_next(parent);
- assert(next->type == nir_cf_node_block);
- nir_block *next_block = nir_cf_node_as_block(next);
-
- link_blocks(block, next_block, NULL);
- } else {
- assert(parent->type == nir_cf_node_loop);
- nir_loop *loop = nir_cf_node_as_loop(parent);
-
- nir_cf_node *head = nir_loop_first_cf_node(loop);
- assert(head->type == nir_cf_node_block);
- nir_block *head_block = nir_cf_node_as_block(head);
-
- link_blocks(block, head_block, NULL);
- }
- } else {
- nir_cf_node *next = nir_cf_node_next(&block->cf_node);
- if (next->type == nir_cf_node_if) {
- nir_if *next_if = nir_cf_node_as_if(next);
-
- nir_cf_node *first_then = nir_if_first_then_node(next_if);
- assert(first_then->type == nir_cf_node_block);
- nir_block *first_then_block = nir_cf_node_as_block(first_then);
-
- nir_cf_node *first_else = nir_if_first_else_node(next_if);
- assert(first_else->type == nir_cf_node_block);
- nir_block *first_else_block = nir_cf_node_as_block(first_else);
-
- link_blocks(block, first_then_block, first_else_block);
- } else {
- assert(next->type == nir_cf_node_loop);
- nir_loop *next_loop = nir_cf_node_as_loop(next);
-
- nir_cf_node *first = nir_loop_first_cf_node(next_loop);
- assert(first->type == nir_cf_node_block);
- nir_block *first_block = nir_cf_node_as_block(first);
-
- link_blocks(block, first_block, NULL);
- }
- }
-
- if (type == nir_jump_break) {
- nir_loop *loop = nearest_loop(&block->cf_node);
-
- nir_cf_node *next = nir_cf_node_next(&loop->cf_node);
- assert(next->type == nir_cf_node_block);
- nir_block *next_block = nir_cf_node_as_block(next);
-
- if (next_block->predecessors->entries == 0) {
- /* insert fake link */
- nir_cf_node *last = nir_loop_last_cf_node(loop);
- assert(last->type == nir_cf_node_block);
- nir_block *last_block = nir_cf_node_as_block(last);
-
- last_block->successors[1] = next_block;
- block_add_pred(next_block, last_block);
- }
- }
-
- nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
- nir_metadata_preserve(impl, nir_metadata_none);
-}
-
-/**
- * Inserts a basic block before another by merging the instructions.
- *
- * @param block the target of the insertion
- * @param before the block to be inserted - must not have been inserted before
- * @param has_jump whether \before has a jump instruction at the end
- */
-
-static void
-insert_block_before_block(nir_block *block, nir_block *before, bool has_jump)
-{
- assert(!has_jump || exec_list_is_empty(&block->instr_list));
-
- foreach_list_typed(nir_instr, instr, node, &before->instr_list) {
- instr->block = block;
- }
-
- exec_list_prepend(&block->instr_list, &before->instr_list);
-
- if (has_jump)
- handle_jump(block);
-}
-
-/**
- * Inserts a basic block after another by merging the instructions.
- *
- * @param block the target of the insertion
- * @param after the block to be inserted - must not have been inserted before
- * @param has_jump whether \after has a jump instruction at the end
- */
-
-static void
-insert_block_after_block(nir_block *block, nir_block *after, bool has_jump)
-{
- foreach_list_typed(nir_instr, instr, node, &after->instr_list) {
- instr->block = block;
- }
-
- exec_list_append(&block->instr_list, &after->instr_list);
-
- if (has_jump)
- handle_jump(block);
-}
-
-static void
-update_if_uses(nir_cf_node *node)
-{
- if (node->type != nir_cf_node_if)
- return;
-
- nir_if *if_stmt = nir_cf_node_as_if(node);
-
- if_stmt->condition.parent_if = if_stmt;
- if (if_stmt->condition.is_ssa) {
- list_addtail(&if_stmt->condition.use_link,
- &if_stmt->condition.ssa->if_uses);
- } else {
- list_addtail(&if_stmt->condition.use_link,
- &if_stmt->condition.reg.reg->if_uses);
- }
-}
-
-void
-nir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after)
-{
- update_if_uses(after);
-
- if (after->type == nir_cf_node_block) {
- /*
- * either node or the one after it must be a basic block, by invariant #2;
- * in either case, just merge the blocks together.
- */
- nir_block *after_block = nir_cf_node_as_block(after);
-
- bool has_jump = !exec_list_is_empty(&after_block->instr_list) &&
- nir_block_last_instr(after_block)->type == nir_instr_type_jump;
-
- if (node->type == nir_cf_node_block) {
- insert_block_after_block(nir_cf_node_as_block(node), after_block,
- has_jump);
- } else {
- nir_cf_node *next = nir_cf_node_next(node);
- assert(next->type == nir_cf_node_block);
- nir_block *next_block = nir_cf_node_as_block(next);
-
- insert_block_before_block(next_block, after_block, has_jump);
- }
- } else {
- if (node->type == nir_cf_node_block) {
- insert_non_block_after_block(nir_cf_node_as_block(node), after);
- } else {
- /*
- * We have to insert a non-basic block after a non-basic block. Since
- * every non-basic block has a basic block after it, this is equivalent
- * to inserting a non-basic block before a basic block.
- */
-
- nir_cf_node *next = nir_cf_node_next(node);
- assert(next->type == nir_cf_node_block);
- nir_block *next_block = nir_cf_node_as_block(next);
-
- insert_non_block_before_block(after, next_block);
- }
- }
-
- nir_function_impl *impl = nir_cf_node_get_function(node);
- nir_metadata_preserve(impl, nir_metadata_none);
-}
-
-void
-nir_cf_node_insert_before(nir_cf_node *node, nir_cf_node *before)
-{
- update_if_uses(before);
-
- if (before->type == nir_cf_node_block) {
- nir_block *before_block = nir_cf_node_as_block(before);
-
- bool has_jump = !exec_list_is_empty(&before_block->instr_list) &&
- nir_block_last_instr(before_block)->type == nir_instr_type_jump;
-
- if (node->type == nir_cf_node_block) {
- insert_block_before_block(nir_cf_node_as_block(node), before_block,
- has_jump);
- } else {
- nir_cf_node *prev = nir_cf_node_prev(node);
- assert(prev->type == nir_cf_node_block);
- nir_block *prev_block = nir_cf_node_as_block(prev);
-
- insert_block_after_block(prev_block, before_block, has_jump);
- }
- } else {
- if (node->type == nir_cf_node_block) {
- insert_non_block_before_block(before, nir_cf_node_as_block(node));
- } else {
- /*
- * We have to insert a non-basic block before a non-basic block. This
- * is equivalent to inserting a non-basic block after a basic block.
- */
-
- nir_cf_node *prev_node = nir_cf_node_prev(node);
- assert(prev_node->type == nir_cf_node_block);
- nir_block *prev_block = nir_cf_node_as_block(prev_node);
-
- insert_non_block_after_block(prev_block, before);
- }
- }
-
- nir_function_impl *impl = nir_cf_node_get_function(node);
- nir_metadata_preserve(impl, nir_metadata_none);
-}
-
-void
-nir_cf_node_insert_begin(struct exec_list *list, nir_cf_node *node)
-{
- nir_cf_node *begin = exec_node_data(nir_cf_node, list->head, node);
- nir_cf_node_insert_before(begin, node);
-}
-
-void
-nir_cf_node_insert_end(struct exec_list *list, nir_cf_node *node)
-{
- nir_cf_node *end = exec_node_data(nir_cf_node, list->tail_pred, node);
- nir_cf_node_insert_after(end, node);
-}
-
-/**
- * Stitch two basic blocks together into one. The aggregate must have the same
- * predecessors as the first and the same successors as the second.
- */
-
-static void
-stitch_blocks(nir_block *before, nir_block *after)
-{
- /*
- * We move after into before, so we have to deal with up to 2 successors vs.
- * possibly a large number of predecessors.
- *
- * TODO: special case when before is empty and after isn't?
- */
-
- move_successors(after, before);
-
- foreach_list_typed(nir_instr, instr, node, &after->instr_list) {
- instr->block = before;
- }
-
- exec_list_append(&before->instr_list, &after->instr_list);
- exec_node_remove(&after->cf_node.node);
-}
-
-static void
-remove_defs_uses(nir_instr *instr);
-
-static void
-cleanup_cf_node(nir_cf_node *node)
-{
- switch (node->type) {
- case nir_cf_node_block: {
- nir_block *block = nir_cf_node_as_block(node);
- /* We need to walk the instructions and clean up defs/uses */
- nir_foreach_instr(block, instr)
- remove_defs_uses(instr);
- break;
- }
-
- case nir_cf_node_if: {
- nir_if *if_stmt = nir_cf_node_as_if(node);
- foreach_list_typed(nir_cf_node, child, node, &if_stmt->then_list)
- cleanup_cf_node(child);
- foreach_list_typed(nir_cf_node, child, node, &if_stmt->else_list)
- cleanup_cf_node(child);
-
- list_del(&if_stmt->condition.use_link);
- break;
- }
-
- case nir_cf_node_loop: {
- nir_loop *loop = nir_cf_node_as_loop(node);
- foreach_list_typed(nir_cf_node, child, node, &loop->body)
- cleanup_cf_node(child);
- break;
- }
- case nir_cf_node_function: {
- nir_function_impl *impl = nir_cf_node_as_function(node);
- foreach_list_typed(nir_cf_node, child, node, &impl->body)
- cleanup_cf_node(child);
- break;
- }
- default:
- unreachable("Invalid CF node type");
- }
-}
-
-void
-nir_cf_node_remove(nir_cf_node *node)
-{
- nir_function_impl *impl = nir_cf_node_get_function(node);
- nir_metadata_preserve(impl, nir_metadata_none);
-
- if (node->type == nir_cf_node_block) {
- /*
- * Basic blocks can't really be removed by themselves, since they act as
- * padding between the non-basic blocks. So all we do here is empty the
- * block of instructions.
- *
- * TODO: could we assert here?
- */
- exec_list_make_empty(&nir_cf_node_as_block(node)->instr_list);
- } else {
- nir_cf_node *before = nir_cf_node_prev(node);
- assert(before->type == nir_cf_node_block);
- nir_block *before_block = nir_cf_node_as_block(before);
-
- nir_cf_node *after = nir_cf_node_next(node);
- assert(after->type == nir_cf_node_block);
- nir_block *after_block = nir_cf_node_as_block(after);
-
- exec_node_remove(&node->node);
- stitch_blocks(before_block, after_block);
- }
-
- cleanup_cf_node(node);
-}
-
static bool
add_use_cb(nir_src *src, void *state)
{
@@ -1348,7 +685,7 @@ nir_instr_insert_after(nir_instr *instr, nir_instr *after)
exec_node_insert_after(&instr->node, &after->node);
if (after->type == nir_instr_type_jump)
- handle_jump(after->block);
+ nir_handle_add_jump(after->block);
}
void
@@ -1362,7 +699,7 @@ nir_instr_insert_before_block(nir_block *block, nir_instr *before)
exec_list_push_head(&block->instr_list, &before->node);
if (before->type == nir_instr_type_jump)
- handle_jump(block);
+ nir_handle_add_jump(block);
}
void
@@ -1378,7 +715,7 @@ nir_instr_insert_after_block(nir_block *block, nir_instr *after)
exec_list_push_tail(&block->instr_list, &after->node);
if (after->type == nir_instr_type_jump)
- handle_jump(block);
+ nir_handle_add_jump(block);
}
void
@@ -1456,7 +793,7 @@ void nir_instr_remove(nir_instr *instr)
if (instr->type == nir_instr_type_jump) {
nir_jump_instr *jump_instr = nir_instr_as_jump(instr);
- handle_remove_jump(instr->block, jump_instr->type);
+ nir_handle_remove_jump(instr->block, jump_instr->type);
}
}
diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h
index 70af06e6971..f78596d5cc0 100644
--- a/src/glsl/nir/nir.h
+++ b/src/glsl/nir/nir.h
@@ -1122,6 +1122,8 @@ typedef struct {
#define nir_foreach_phi_src(phi, entry) \
foreach_list_typed(nir_phi_src, entry, node, &(phi)->srcs)
+#define nir_foreach_phi_src_safe(phi, entry) \
+ foreach_list_typed_safe(nir_phi_src, entry, node, &(phi)->srcs)
typedef struct {
nir_instr instr;
@@ -1330,7 +1332,7 @@ typedef struct {
struct exec_list body; /** < list of nir_cf_node */
- nir_block *start_block, *end_block;
+ nir_block *end_block;
/** list for all local variables in the function */
struct exec_list locals;
@@ -1357,6 +1359,12 @@ typedef struct {
nir_metadata valid_metadata;
} nir_function_impl;
+static inline nir_block *
+nir_start_block(nir_function_impl *impl)
+{
+ return (nir_block *) exec_list_get_head(&impl->body);
+}
+
static inline nir_cf_node *
nir_cf_node_next(nir_cf_node *node)
{
@@ -1488,8 +1496,8 @@ typedef struct nir_shader {
*/
unsigned num_inputs, num_uniforms, num_outputs;
- /** the number of uniforms that are only accessed directly */
- unsigned num_direct_uniforms;
+ /** The shader stage, such as MESA_SHADER_VERTEX. */
+ gl_shader_stage stage;
} nir_shader;
#define nir_foreach_overload(shader, overload) \
@@ -1498,6 +1506,7 @@ typedef struct nir_shader {
&(func)->overload_list)
nir_shader *nir_shader_create(void *mem_ctx,
+ gl_shader_stage stage,
const nir_shader_compiler_options *options);
/** creates a register, including assigning it an index and adding it to the list */
@@ -1521,21 +1530,6 @@ nir_loop *nir_loop_create(void *mem_ctx);
nir_function_impl *nir_cf_node_get_function(nir_cf_node *node);
-/** puts a control flow node immediately after another control flow node */
-void nir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after);
-
-/** puts a control flow node immediately before another control flow node */
-void nir_cf_node_insert_before(nir_cf_node *node, nir_cf_node *before);
-
-/** puts a control flow node at the beginning of a list from an if, loop, or function */
-void nir_cf_node_insert_begin(struct exec_list *list, nir_cf_node *node);
-
-/** puts a control flow node at the end of a list from an if, loop, or function */
-void nir_cf_node_insert_end(struct exec_list *list, nir_cf_node *node);
-
-/** removes a control flow node, doing any cleanup necessary */
-void nir_cf_node_remove(nir_cf_node *node);
-
/** requests that the given pieces of metadata be generated */
void nir_metadata_require(nir_function_impl *impl, nir_metadata required);
/** dirties all but the preserved metadata */
@@ -1660,15 +1654,10 @@ void nir_lower_locals_to_regs(nir_shader *shader);
void nir_assign_var_locations(struct exec_list *var_list,
unsigned *size,
- bool is_scalar);
-void nir_assign_var_locations_direct_first(nir_shader *shader,
- struct exec_list *var_list,
- unsigned *direct_size,
- unsigned *size,
- bool is_scalar);
-
-void nir_lower_io(nir_shader *shader, bool is_scalar);
+ int (*type_size)(const struct glsl_type *));
+void nir_lower_io(nir_shader *shader,
+ int (*type_size)(const struct glsl_type *));
void nir_lower_vars_to_ssa(nir_shader *shader);
void nir_remove_dead_variables(nir_shader *shader);
@@ -1680,8 +1669,7 @@ void nir_lower_load_const_to_scalar(nir_shader *shader);
void nir_lower_phis_to_scalar(nir_shader *shader);
void nir_lower_samplers(nir_shader *shader,
- const struct gl_shader_program *shader_program,
- gl_shader_stage stage);
+ const struct gl_shader_program *shader_program);
void nir_lower_samplers_for_vk(nir_shader *shader);
void nir_lower_system_values(nir_shader *shader);
diff --git a/src/glsl/nir/nir_control_flow.c b/src/glsl/nir/nir_control_flow.c
new file mode 100644
index 00000000000..5c03375ac77
--- /dev/null
+++ b/src/glsl/nir/nir_control_flow.c
@@ -0,0 +1,769 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Connor Abbott ([email protected])
+ *
+ */
+
+#include "nir_control_flow_private.h"
+
+/**
+ * \name Control flow modification
+ *
+ * These functions modify the control flow tree while keeping the control flow
+ * graph up-to-date. The invariants respected are:
+ * 1. Each then statement, else statement, or loop body must have at least one
+ * control flow node.
+ * 2. Each if-statement and loop must have one basic block before it and one
+ * after.
+ * 3. Two basic blocks cannot be directly next to each other.
+ * 4. If a basic block has a jump instruction, there must be only one and it
+ * must be at the end of the block.
+ * 5. The CFG must always be connected - this means that we must insert a fake
+ * CFG edge for loops with no break statement.
+ *
+ * The purpose of the second one is so that we have places to insert code during
+ * GCM, as well as eliminating the possibility of critical edges.
+ */
+/*@{*/
+
+static bool
+block_ends_in_jump(nir_block *block)
+{
+ return !exec_list_is_empty(&block->instr_list) &&
+ nir_block_last_instr(block)->type == nir_instr_type_jump;
+}
+
+static inline void
+block_add_pred(nir_block *block, nir_block *pred)
+{
+ _mesa_set_add(block->predecessors, pred);
+}
+
+static void
+link_blocks(nir_block *pred, nir_block *succ1, nir_block *succ2)
+{
+ pred->successors[0] = succ1;
+ if (succ1 != NULL)
+ block_add_pred(succ1, pred);
+
+ pred->successors[1] = succ2;
+ if (succ2 != NULL)
+ block_add_pred(succ2, pred);
+}
+
+static void
+unlink_blocks(nir_block *pred, nir_block *succ)
+{
+ if (pred->successors[0] == succ) {
+ pred->successors[0] = pred->successors[1];
+ pred->successors[1] = NULL;
+ } else {
+ assert(pred->successors[1] == succ);
+ pred->successors[1] = NULL;
+ }
+
+ struct set_entry *entry = _mesa_set_search(succ->predecessors, pred);
+
+ assert(entry);
+
+ _mesa_set_remove(succ->predecessors, entry);
+}
+
+static void
+unlink_block_successors(nir_block *block)
+{
+ if (block->successors[0] != NULL)
+ unlink_blocks(block, block->successors[0]);
+ if (block->successors[1] != NULL)
+ unlink_blocks(block, block->successors[1]);
+}
+
+static void
+link_non_block_to_block(nir_cf_node *node, nir_block *block)
+{
+ if (node->type == nir_cf_node_if) {
+ /*
+ * We're trying to link an if to a block after it; this just means linking
+ * the last block of the then and else branches.
+ */
+
+ nir_if *if_stmt = nir_cf_node_as_if(node);
+
+ nir_cf_node *last_then = nir_if_last_then_node(if_stmt);
+ assert(last_then->type == nir_cf_node_block);
+ nir_block *last_then_block = nir_cf_node_as_block(last_then);
+
+ nir_cf_node *last_else = nir_if_last_else_node(if_stmt);
+ assert(last_else->type == nir_cf_node_block);
+ nir_block *last_else_block = nir_cf_node_as_block(last_else);
+
+ if (!block_ends_in_jump(last_then_block)) {
+ unlink_block_successors(last_then_block);
+ link_blocks(last_then_block, block, NULL);
+ }
+
+ if (!block_ends_in_jump(last_else_block)) {
+ unlink_block_successors(last_else_block);
+ link_blocks(last_else_block, block, NULL);
+ }
+ } else {
+ assert(node->type == nir_cf_node_loop);
+
+ /*
+ * We can only get to this codepath if we're inserting a new loop, or
+ * at least a loop with no break statements; we can't insert break
+ * statements into a loop when we haven't inserted it into the CFG
+ * because we wouldn't know which block comes after the loop
+ * and therefore, which block should be the successor of the block with
+ * the break). Therefore, we need to insert a fake edge (see invariant
+ * #5).
+ */
+
+ nir_loop *loop = nir_cf_node_as_loop(node);
+
+ nir_cf_node *last = nir_loop_last_cf_node(loop);
+ assert(last->type == nir_cf_node_block);
+ nir_block *last_block = nir_cf_node_as_block(last);
+
+ last_block->successors[1] = block;
+ block_add_pred(block, last_block);
+ }
+}
+
+static void
+link_block_to_non_block(nir_block *block, nir_cf_node *node)
+{
+ if (node->type == nir_cf_node_if) {
+ /*
+ * We're trying to link a block to an if after it; this just means linking
+ * the block to the first block of the then and else branches.
+ */
+
+ nir_if *if_stmt = nir_cf_node_as_if(node);
+
+ nir_cf_node *first_then = nir_if_first_then_node(if_stmt);
+ assert(first_then->type == nir_cf_node_block);
+ nir_block *first_then_block = nir_cf_node_as_block(first_then);
+
+ nir_cf_node *first_else = nir_if_first_else_node(if_stmt);
+ assert(first_else->type == nir_cf_node_block);
+ nir_block *first_else_block = nir_cf_node_as_block(first_else);
+
+ unlink_block_successors(block);
+ link_blocks(block, first_then_block, first_else_block);
+ } else {
+ /*
+ * For similar reasons as the corresponding case in
+ * link_non_block_to_block(), don't worry about if the loop header has
+ * any predecessors that need to be unlinked.
+ */
+
+ assert(node->type == nir_cf_node_loop);
+
+ nir_loop *loop = nir_cf_node_as_loop(node);
+
+ nir_cf_node *loop_header = nir_loop_first_cf_node(loop);
+ assert(loop_header->type == nir_cf_node_block);
+ nir_block *loop_header_block = nir_cf_node_as_block(loop_header);
+
+ unlink_block_successors(block);
+ link_blocks(block, loop_header_block, NULL);
+ }
+
+}
+
+/**
+ * Takes a basic block and inserts a new empty basic block before it, making its
+ * predecessors point to the new block. This essentially splits the block into
+ * an empty header and a body so that another non-block CF node can be inserted
+ * between the two. Note that this does *not* link the two basic blocks, so
+ * some kind of cleanup *must* be performed after this call.
+ */
+
+static nir_block *
+split_block_beginning(nir_block *block)
+{
+ nir_block *new_block = nir_block_create(ralloc_parent(block));
+ new_block->cf_node.parent = block->cf_node.parent;
+ exec_node_insert_node_before(&block->cf_node.node, &new_block->cf_node.node);
+
+ struct set_entry *entry;
+ set_foreach(block->predecessors, entry) {
+ nir_block *pred = (nir_block *) entry->key;
+
+ unlink_blocks(pred, block);
+ link_blocks(pred, new_block, NULL);
+ }
+
+ /* Any phi nodes must stay part of the new block, or else their
+ * sourcse will be messed up. This will reverse the order of the phi's, but
+ * order shouldn't matter.
+ */
+ nir_foreach_instr_safe(block, instr) {
+ if (instr->type != nir_instr_type_phi)
+ break;
+
+ exec_node_remove(&instr->node);
+ instr->block = new_block;
+ exec_list_push_head(&new_block->instr_list, &instr->node);
+ }
+
+ return new_block;
+}
+
+static void
+rewrite_phi_preds(nir_block *block, nir_block *old_pred, nir_block *new_pred)
+{
+ nir_foreach_instr_safe(block, instr) {
+ if (instr->type != nir_instr_type_phi)
+ break;
+
+ nir_phi_instr *phi = nir_instr_as_phi(instr);
+ nir_foreach_phi_src(phi, src) {
+ if (src->pred == old_pred) {
+ src->pred = new_pred;
+ break;
+ }
+ }
+ }
+}
+
+static void
+insert_phi_undef(nir_block *block, nir_block *pred)
+{
+ nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
+ nir_foreach_instr(block, instr) {
+ if (instr->type != nir_instr_type_phi)
+ break;
+
+ nir_phi_instr *phi = nir_instr_as_phi(instr);
+ nir_ssa_undef_instr *undef =
+ nir_ssa_undef_instr_create(ralloc_parent(phi),
+ phi->dest.ssa.num_components);
+ nir_instr_insert_before_cf_list(&impl->body, &undef->instr);
+ nir_phi_src *src = ralloc(phi, nir_phi_src);
+ src->pred = pred;
+ src->src.parent_instr = &phi->instr;
+ src->src.is_ssa = true;
+ src->src.ssa = &undef->def;
+
+ list_addtail(&src->src.use_link, &undef->def.uses);
+
+ exec_list_push_tail(&phi->srcs, &src->node);
+ }
+}
+
+/**
+ * Moves the successors of source to the successors of dest, leaving both
+ * successors of source NULL.
+ */
+
+static void
+move_successors(nir_block *source, nir_block *dest)
+{
+ nir_block *succ1 = source->successors[0];
+ nir_block *succ2 = source->successors[1];
+
+ if (succ1) {
+ unlink_blocks(source, succ1);
+ rewrite_phi_preds(succ1, source, dest);
+ }
+
+ if (succ2) {
+ unlink_blocks(source, succ2);
+ rewrite_phi_preds(succ2, source, dest);
+ }
+
+ unlink_block_successors(dest);
+ link_blocks(dest, succ1, succ2);
+}
+
+/* Given a basic block with no successors that has been inserted into the
+ * control flow tree, gives it the successors it would normally have assuming
+ * it doesn't end in a jump instruction. Also inserts phi sources with undefs
+ * if necessary.
+ */
+static void
+block_add_normal_succs(nir_block *block)
+{
+ if (exec_node_is_tail_sentinel(block->cf_node.node.next)) {
+ nir_cf_node *parent = block->cf_node.parent;
+ if (parent->type == nir_cf_node_if) {
+ nir_cf_node *next = nir_cf_node_next(parent);
+ assert(next->type == nir_cf_node_block);
+ nir_block *next_block = nir_cf_node_as_block(next);
+
+ link_blocks(block, next_block, NULL);
+ } else {
+ assert(parent->type == nir_cf_node_loop);
+ nir_loop *loop = nir_cf_node_as_loop(parent);
+
+ nir_cf_node *head = nir_loop_first_cf_node(loop);
+ assert(head->type == nir_cf_node_block);
+ nir_block *head_block = nir_cf_node_as_block(head);
+
+ link_blocks(block, head_block, NULL);
+ insert_phi_undef(head_block, block);
+ }
+ } else {
+ nir_cf_node *next = nir_cf_node_next(&block->cf_node);
+ if (next->type == nir_cf_node_if) {
+ nir_if *next_if = nir_cf_node_as_if(next);
+
+ nir_cf_node *first_then = nir_if_first_then_node(next_if);
+ assert(first_then->type == nir_cf_node_block);
+ nir_block *first_then_block = nir_cf_node_as_block(first_then);
+
+ nir_cf_node *first_else = nir_if_first_else_node(next_if);
+ assert(first_else->type == nir_cf_node_block);
+ nir_block *first_else_block = nir_cf_node_as_block(first_else);
+
+ link_blocks(block, first_then_block, first_else_block);
+ } else {
+ assert(next->type == nir_cf_node_loop);
+ nir_loop *next_loop = nir_cf_node_as_loop(next);
+
+ nir_cf_node *first = nir_loop_first_cf_node(next_loop);
+ assert(first->type == nir_cf_node_block);
+ nir_block *first_block = nir_cf_node_as_block(first);
+
+ link_blocks(block, first_block, NULL);
+ insert_phi_undef(first_block, block);
+ }
+ }
+}
+
+static nir_block *
+split_block_end(nir_block *block)
+{
+ nir_block *new_block = nir_block_create(ralloc_parent(block));
+ new_block->cf_node.parent = block->cf_node.parent;
+ exec_node_insert_after(&block->cf_node.node, &new_block->cf_node.node);
+
+ if (block_ends_in_jump(block)) {
+ /* Figure out what successor block would've had if it didn't have a jump
+ * instruction, and make new_block have that successor.
+ */
+ block_add_normal_succs(new_block);
+ } else {
+ move_successors(block, new_block);
+ }
+
+ return new_block;
+}
+
+static nir_block *
+split_block_before_instr(nir_instr *instr)
+{
+ assert(instr->type != nir_instr_type_phi);
+ nir_block *new_block = split_block_beginning(instr->block);
+
+ nir_foreach_instr_safe(instr->block, cur_instr) {
+ if (cur_instr == instr)
+ break;
+
+ exec_node_remove(&cur_instr->node);
+ cur_instr->block = new_block;
+ exec_list_push_tail(&new_block->instr_list, &cur_instr->node);
+ }
+
+ return new_block;
+}
+
+/* Splits a basic block at the point specified by the cursor. The "before" and
+ * "after" arguments are filled out with the blocks resulting from the split
+ * if non-NULL. Note that the "beginning" of the block is actually interpreted
+ * as before the first non-phi instruction, and it's illegal to split a block
+ * before a phi instruction.
+ */
+
+static void
+split_block_cursor(nir_cursor cursor,
+ nir_block **_before, nir_block **_after)
+{
+ nir_block *before, *after;
+ switch (cursor.option) {
+ case nir_cursor_before_block:
+ after = cursor.block;
+ before = split_block_beginning(cursor.block);
+ break;
+
+ case nir_cursor_after_block:
+ before = cursor.block;
+ after = split_block_end(cursor.block);
+ break;
+
+ case nir_cursor_before_instr:
+ after = cursor.instr->block;
+ before = split_block_before_instr(cursor.instr);
+ break;
+
+ case nir_cursor_after_instr:
+ /* We lower this to split_block_before_instr() so that we can keep the
+ * after-a-jump-instr case contained to split_block_end().
+ */
+ if (nir_instr_is_last(cursor.instr)) {
+ before = cursor.instr->block;
+ after = split_block_end(cursor.instr->block);
+ } else {
+ after = cursor.instr->block;
+ before = split_block_before_instr(nir_instr_next(cursor.instr));
+ }
+ break;
+ }
+
+ if (_before)
+ *_before = before;
+ if (_after)
+ *_after = after;
+}
+
+/**
+ * Inserts a non-basic block between two basic blocks and links them together.
+ */
+
+static void
+insert_non_block(nir_block *before, nir_cf_node *node, nir_block *after)
+{
+ node->parent = before->cf_node.parent;
+ exec_node_insert_after(&before->cf_node.node, &node->node);
+ link_block_to_non_block(before, node);
+ link_non_block_to_block(node, after);
+}
+
+/* walk up the control flow tree to find the innermost enclosed loop */
+static nir_loop *
+nearest_loop(nir_cf_node *node)
+{
+ while (node->type != nir_cf_node_loop) {
+ node = node->parent;
+ }
+
+ return nir_cf_node_as_loop(node);
+}
+
+/*
+ * update the CFG after a jump instruction has been added to the end of a block
+ */
+
+void
+nir_handle_add_jump(nir_block *block)
+{
+ nir_instr *instr = nir_block_last_instr(block);
+ nir_jump_instr *jump_instr = nir_instr_as_jump(instr);
+
+ unlink_block_successors(block);
+
+ nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
+ nir_metadata_preserve(impl, nir_metadata_none);
+
+ if (jump_instr->type == nir_jump_break ||
+ jump_instr->type == nir_jump_continue) {
+ nir_loop *loop = nearest_loop(&block->cf_node);
+
+ if (jump_instr->type == nir_jump_continue) {
+ nir_cf_node *first_node = nir_loop_first_cf_node(loop);
+ assert(first_node->type == nir_cf_node_block);
+ nir_block *first_block = nir_cf_node_as_block(first_node);
+ link_blocks(block, first_block, NULL);
+ } else {
+ nir_cf_node *after = nir_cf_node_next(&loop->cf_node);
+ assert(after->type == nir_cf_node_block);
+ nir_block *after_block = nir_cf_node_as_block(after);
+ link_blocks(block, after_block, NULL);
+
+ /* If we inserted a fake link, remove it */
+ nir_cf_node *last = nir_loop_last_cf_node(loop);
+ assert(last->type == nir_cf_node_block);
+ nir_block *last_block = nir_cf_node_as_block(last);
+ if (last_block->successors[1] != NULL)
+ unlink_blocks(last_block, after_block);
+ }
+ } else {
+ assert(jump_instr->type == nir_jump_return);
+ link_blocks(block, impl->end_block, NULL);
+ }
+}
+
+static void
+remove_phi_src(nir_block *block, nir_block *pred)
+{
+ nir_foreach_instr(block, instr) {
+ if (instr->type != nir_instr_type_phi)
+ break;
+
+ nir_phi_instr *phi = nir_instr_as_phi(instr);
+ nir_foreach_phi_src_safe(phi, src) {
+ if (src->pred == pred) {
+ list_del(&src->src.use_link);
+ exec_node_remove(&src->node);
+ }
+ }
+ }
+}
+
+/* Removes the successor of a block with a jump, and inserts a fake edge for
+ * infinite loops. Note that the jump to be eliminated may be free-floating.
+ */
+
+static
+void unlink_jump(nir_block *block, nir_jump_type type)
+{
+ if (block->successors[0])
+ remove_phi_src(block->successors[0], block);
+ if (block->successors[1])
+ remove_phi_src(block->successors[1], block);
+
+ if (type == nir_jump_break) {
+ nir_block *next = block->successors[0];
+
+ if (next->predecessors->entries == 1) {
+ nir_loop *loop =
+ nir_cf_node_as_loop(nir_cf_node_prev(&next->cf_node));
+
+ /* insert fake link */
+ nir_cf_node *last = nir_loop_last_cf_node(loop);
+ assert(last->type == nir_cf_node_block);
+ nir_block *last_block = nir_cf_node_as_block(last);
+
+ last_block->successors[1] = next;
+ block_add_pred(next, last_block);
+ }
+ }
+
+ unlink_block_successors(block);
+}
+
+void
+nir_handle_remove_jump(nir_block *block, nir_jump_type type)
+{
+ unlink_jump(block, type);
+
+ block_add_normal_succs(block);
+
+ nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
+ nir_metadata_preserve(impl, nir_metadata_none);
+}
+
+static void
+update_if_uses(nir_cf_node *node)
+{
+ if (node->type != nir_cf_node_if)
+ return;
+
+ nir_if *if_stmt = nir_cf_node_as_if(node);
+
+ if_stmt->condition.parent_if = if_stmt;
+ if (if_stmt->condition.is_ssa) {
+ list_addtail(&if_stmt->condition.use_link,
+ &if_stmt->condition.ssa->if_uses);
+ } else {
+ list_addtail(&if_stmt->condition.use_link,
+ &if_stmt->condition.reg.reg->if_uses);
+ }
+}
+
+/**
+ * Stitch two basic blocks together into one. The aggregate must have the same
+ * predecessors as the first and the same successors as the second.
+ */
+
+static void
+stitch_blocks(nir_block *before, nir_block *after)
+{
+ /*
+ * We move after into before, so we have to deal with up to 2 successors vs.
+ * possibly a large number of predecessors.
+ *
+ * TODO: special case when before is empty and after isn't?
+ */
+
+ if (block_ends_in_jump(before)) {
+ assert(exec_list_is_empty(&after->instr_list));
+ if (after->successors[0])
+ remove_phi_src(after->successors[0], after);
+ if (after->successors[1])
+ remove_phi_src(after->successors[1], after);
+ unlink_block_successors(after);
+ exec_node_remove(&after->cf_node.node);
+ } else {
+ move_successors(after, before);
+
+ foreach_list_typed(nir_instr, instr, node, &after->instr_list) {
+ instr->block = before;
+ }
+
+ exec_list_append(&before->instr_list, &after->instr_list);
+ exec_node_remove(&after->cf_node.node);
+ }
+}
+
+void
+nir_cf_node_insert(nir_cursor cursor, nir_cf_node *node)
+{
+ nir_block *before, *after;
+
+ split_block_cursor(cursor, &before, &after);
+
+ if (node->type == nir_cf_node_block) {
+ nir_block *block = nir_cf_node_as_block(node);
+ exec_node_insert_after(&before->cf_node.node, &block->cf_node.node);
+ block->cf_node.parent = before->cf_node.parent;
+ /* stitch_blocks() assumes that any block that ends with a jump has
+ * already been setup with the correct successors, so we need to set
+ * up jumps here as the block is being inserted.
+ */
+ if (block_ends_in_jump(block))
+ nir_handle_add_jump(block);
+
+ stitch_blocks(block, after);
+ stitch_blocks(before, block);
+ } else {
+ update_if_uses(node);
+ insert_non_block(before, node, after);
+ }
+}
+
+static bool
+replace_ssa_def_uses(nir_ssa_def *def, void *void_impl)
+{
+ nir_function_impl *impl = void_impl;
+ void *mem_ctx = ralloc_parent(impl);
+
+ nir_ssa_undef_instr *undef =
+ nir_ssa_undef_instr_create(mem_ctx, def->num_components);
+ nir_instr_insert_before_cf_list(&impl->body, &undef->instr);
+ nir_ssa_def_rewrite_uses(def, nir_src_for_ssa(&undef->def), mem_ctx);
+ return true;
+}
+
+static void
+cleanup_cf_node(nir_cf_node *node, nir_function_impl *impl)
+{
+ switch (node->type) {
+ case nir_cf_node_block: {
+ nir_block *block = nir_cf_node_as_block(node);
+ /* We need to walk the instructions and clean up defs/uses */
+ nir_foreach_instr_safe(block, instr) {
+ if (instr->type == nir_instr_type_jump) {
+ nir_jump_type jump_type = nir_instr_as_jump(instr)->type;
+ unlink_jump(block, jump_type);
+ } else {
+ nir_foreach_ssa_def(instr, replace_ssa_def_uses, impl);
+ nir_instr_remove(instr);
+ }
+ }
+ break;
+ }
+
+ case nir_cf_node_if: {
+ nir_if *if_stmt = nir_cf_node_as_if(node);
+ foreach_list_typed(nir_cf_node, child, node, &if_stmt->then_list)
+ cleanup_cf_node(child, impl);
+ foreach_list_typed(nir_cf_node, child, node, &if_stmt->else_list)
+ cleanup_cf_node(child, impl);
+
+ list_del(&if_stmt->condition.use_link);
+ break;
+ }
+
+ case nir_cf_node_loop: {
+ nir_loop *loop = nir_cf_node_as_loop(node);
+ foreach_list_typed(nir_cf_node, child, node, &loop->body)
+ cleanup_cf_node(child, impl);
+ break;
+ }
+ case nir_cf_node_function: {
+ nir_function_impl *impl = nir_cf_node_as_function(node);
+ foreach_list_typed(nir_cf_node, child, node, &impl->body)
+ cleanup_cf_node(child, impl);
+ break;
+ }
+ default:
+ unreachable("Invalid CF node type");
+ }
+}
+
+void
+nir_cf_extract(nir_cf_list *extracted, nir_cursor begin, nir_cursor end)
+{
+ nir_block *block_begin, *block_end, *block_before, *block_after;
+
+ /* In the case where begin points to an instruction in some basic block and
+ * end points to the end of the same basic block, we rely on the fact that
+ * splitting on an instruction moves earlier instructions into a new basic
+ * block. If the later instructions were moved instead, then the end cursor
+ * would be pointing to the same place that begin used to point to, which
+ * is obviously not what we want.
+ */
+ split_block_cursor(begin, &block_before, &block_begin);
+ split_block_cursor(end, &block_end, &block_after);
+
+ extracted->impl = nir_cf_node_get_function(&block_begin->cf_node);
+ exec_list_make_empty(&extracted->list);
+
+ nir_cf_node *cf_node = &block_begin->cf_node;
+ nir_cf_node *cf_node_end = &block_end->cf_node;
+ while (true) {
+ nir_cf_node *next = nir_cf_node_next(cf_node);
+
+ exec_node_remove(&cf_node->node);
+ cf_node->parent = NULL;
+ exec_list_push_tail(&extracted->list, &cf_node->node);
+
+ if (cf_node == cf_node_end)
+ break;
+
+ cf_node = next;
+ }
+
+ stitch_blocks(block_before, block_after);
+}
+
+void
+nir_cf_reinsert(nir_cf_list *cf_list, nir_cursor cursor)
+{
+ nir_block *before, *after;
+
+ split_block_cursor(cursor, &before, &after);
+
+ foreach_list_typed_safe(nir_cf_node, node, node, &cf_list->list) {
+ exec_node_remove(&node->node);
+ node->parent = before->cf_node.parent;
+ exec_node_insert_node_before(&after->cf_node.node, &node->node);
+ }
+
+ stitch_blocks(before,
+ nir_cf_node_as_block(nir_cf_node_next(&before->cf_node)));
+ stitch_blocks(nir_cf_node_as_block(nir_cf_node_prev(&after->cf_node)),
+ after);
+}
+
+void
+nir_cf_delete(nir_cf_list *cf_list)
+{
+ foreach_list_typed(nir_cf_node, node, node, &cf_list->list) {
+ cleanup_cf_node(node, cf_list->impl);
+ }
+}
diff --git a/src/glsl/nir/nir_control_flow.h b/src/glsl/nir/nir_control_flow.h
new file mode 100644
index 00000000000..5efd41caadf
--- /dev/null
+++ b/src/glsl/nir/nir_control_flow.h
@@ -0,0 +1,251 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Connor Abbott ([email protected])
+ *
+ */
+
+#include "nir.h"
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** NIR Control Flow Modification
+ *
+ * This file contains various API's that make modifying control flow in NIR,
+ * while maintaining the invariants checked by the validator, much easier.
+ * There are two parts to this:
+ *
+ * 1. Inserting control flow (if's and loops) in various places, for creating
+ * IR either from scratch or as part of some lowering pass.
+ * 2. Taking existing pieces of the IR and either moving them around or
+ * deleting them.
+ */
+
+/* Helper struct for representing a point to extract/insert. Helps reduce the
+ * combinatorial explosion of possible points to extract.
+ */
+
+typedef enum {
+ nir_cursor_before_block,
+ nir_cursor_after_block,
+ nir_cursor_before_instr,
+ nir_cursor_after_instr,
+} nir_cursor_option;
+
+typedef struct {
+ nir_cursor_option option;
+ union {
+ nir_block *block;
+ nir_instr *instr;
+ };
+} nir_cursor;
+
+static inline nir_cursor
+nir_before_block(nir_block *block)
+{
+ nir_cursor cursor;
+ cursor.option = nir_cursor_before_block;
+ cursor.block = block;
+ return cursor;
+}
+
+static inline nir_cursor
+nir_after_block(nir_block *block)
+{
+ nir_cursor cursor;
+ cursor.option = nir_cursor_after_block;
+ cursor.block = block;
+ return cursor;
+}
+
+static inline nir_cursor
+nir_before_instr(nir_instr *instr)
+{
+ nir_cursor cursor;
+ cursor.option = nir_cursor_before_instr;
+ cursor.instr = instr;
+ return cursor;
+}
+
+static inline nir_cursor
+nir_after_instr(nir_instr *instr)
+{
+ nir_cursor cursor;
+ cursor.option = nir_cursor_after_instr;
+ cursor.instr = instr;
+ return cursor;
+}
+
+static inline nir_cursor
+nir_before_cf_node(nir_cf_node *node)
+{
+ if (node->type == nir_cf_node_block)
+ return nir_before_block(nir_cf_node_as_block(node));
+
+ return nir_after_block(nir_cf_node_as_block(nir_cf_node_prev(node)));
+}
+
+static inline nir_cursor
+nir_after_cf_node(nir_cf_node *node)
+{
+ if (node->type == nir_cf_node_block)
+ return nir_after_block(nir_cf_node_as_block(node));
+
+ return nir_before_block(nir_cf_node_as_block(nir_cf_node_next(node)));
+}
+
+static inline nir_cursor
+nir_before_cf_list(struct exec_list *cf_list)
+{
+ nir_cf_node *first_node = exec_node_data(nir_cf_node,
+ exec_list_get_head(cf_list), node);
+ return nir_before_cf_node(first_node);
+}
+
+static inline nir_cursor
+nir_after_cf_list(struct exec_list *cf_list)
+{
+ nir_cf_node *last_node = exec_node_data(nir_cf_node,
+ exec_list_get_tail(cf_list), node);
+ return nir_after_cf_node(last_node);
+}
+
+/** Control flow insertion. */
+
+/** puts a control flow node where the cursor is */
+void nir_cf_node_insert(nir_cursor cursor, nir_cf_node *node);
+
+/** puts a control flow node immediately after another control flow node */
+static inline void
+nir_cf_node_insert_after(nir_cf_node *node, nir_cf_node *after)
+{
+ nir_cf_node_insert(nir_after_cf_node(node), after);
+}
+
+/** puts a control flow node immediately before another control flow node */
+static inline void
+nir_cf_node_insert_before(nir_cf_node *node, nir_cf_node *before)
+{
+ nir_cf_node_insert(nir_before_cf_node(node), before);
+}
+
+/** puts a control flow node at the beginning of a list from an if, loop, or function */
+static inline void
+nir_cf_node_insert_begin(struct exec_list *list, nir_cf_node *node)
+{
+ nir_cf_node_insert(nir_before_cf_list(list), node);
+}
+
+/** puts a control flow node at the end of a list from an if, loop, or function */
+static inline void
+nir_cf_node_insert_end(struct exec_list *list, nir_cf_node *node)
+{
+ nir_cf_node_insert(nir_after_cf_list(list), node);
+}
+
+
+/** Control flow motion.
+ *
+ * These functions let you take a part of a control flow list (basically
+ * equivalent to a series of statement in GLSL) and "extract" it from the IR,
+ * so that it's a free-floating piece of IR that can be either re-inserted
+ * somewhere else or deleted entirely. A few notes on using it:
+ *
+ * 1. Phi nodes are considered attached to the piece of control flow that
+ * their sources come from. There are three places where phi nodes can
+ * occur, which are the three places where a block can have multiple
+ * predecessors:
+ *
+ * 1) After an if statement, if neither branch ends in a jump.
+ * 2) After a loop, if there are multiple break's.
+ * 3) At the beginning of a loop.
+ *
+ * For #1, the phi node is considered to be part of the if, and for #2 and
+ * #3 the phi node is considered to be part of the loop. This allows us to
+ * keep phi's intact, but it means that phi nodes cannot be separated from
+ * the control flow they come from. For example, extracting an if without
+ * extracting all the phi nodes after it is not allowed, and neither is
+ * extracting only some of the phi nodes at the beginning of a block. It
+ * also means that extracting from the beginning of a basic block actually
+ * means extracting from the first non-phi instruction, since there's no
+ * situation where extracting phi nodes without extracting what comes
+ * before them makes any sense.
+ *
+ * 2. Phi node sources are guaranteed to remain valid, meaning that they still
+ * correspond one-to-one with the predecessors of the basic block they're
+ * part of. In addition, the original sources will be preserved unless they
+ * correspond to a break or continue that was deleted. However, no attempt
+ * is made to ensure that SSA form is maintained. In particular, it is
+ * *not* guaranteed that definitions of SSA values will dominate all their
+ * uses after all is said and done. Either the caller must ensure that this
+ * is the case, or it must insert extra phi nodes to restore SSA.
+ *
+ * 3. It is invalid to move a piece of IR with a break/continue outside of the
+ * loop it references. Doing this will result in invalid
+ * successors/predecessors and phi node sources.
+ *
+ * 4. It is invalid to move a piece of IR from one function implementation to
+ * another.
+ *
+ * 5. Extracting a control flow list will leave lots of dangling references to
+ * and from other pieces of the IR. It also leaves things in a not 100%
+ * consistent state. This means that some things (e.g. inserting
+ * instructions) might not work reliably on the extracted control flow. It
+ * also means that extracting control flow without re-inserting it or
+ * deleting it is a Bad Thing (tm).
+ */
+
+typedef struct {
+ struct exec_list list;
+ nir_function_impl *impl; /* for cleaning up if the list is deleted */
+} nir_cf_list;
+
+void nir_cf_extract(nir_cf_list *extracted, nir_cursor begin, nir_cursor end);
+
+void nir_cf_reinsert(nir_cf_list *cf_list, nir_cursor cursor);
+
+void nir_cf_delete(nir_cf_list *cf_list);
+
+static inline void
+nir_cf_list_extract(nir_cf_list *extracted, struct exec_list *cf_list)
+{
+ nir_cf_extract(extracted, nir_before_cf_list(cf_list),
+ nir_after_cf_list(cf_list));
+}
+
+/** removes a control flow node, doing any cleanup necessary */
+static inline void
+nir_cf_node_remove(nir_cf_node *node)
+{
+ nir_cf_list list;
+ nir_cf_extract(&list, nir_before_cf_node(node), nir_after_cf_node(node));
+ nir_cf_delete(&list);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/glsl/nir/nir_control_flow_private.h b/src/glsl/nir/nir_control_flow_private.h
new file mode 100644
index 00000000000..f32b57a8cef
--- /dev/null
+++ b/src/glsl/nir/nir_control_flow_private.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Connor Abbott ([email protected])
+ *
+ */
+
+#include "nir_control_flow.h"
+
+#pragma once
+
+/* Internal control-flow modification functions used when inserting/removing
+ * instructions.
+ */
+
+void nir_handle_add_jump(nir_block *block);
+void nir_handle_remove_jump(nir_block *block, nir_jump_type type);
diff --git a/src/glsl/nir/nir_dominance.c b/src/glsl/nir/nir_dominance.c
index 2f50db1c1f6..af4caae0055 100644
--- a/src/glsl/nir/nir_dominance.c
+++ b/src/glsl/nir/nir_dominance.c
@@ -42,7 +42,7 @@ static bool
init_block_cb(nir_block *block, void *_state)
{
dom_state *state = (dom_state *) _state;
- if (block == state->impl->start_block)
+ if (block == nir_start_block(state->impl))
block->imm_dom = block;
else
block->imm_dom = NULL;
@@ -78,7 +78,7 @@ static bool
calc_dominance_cb(nir_block *block, void *_state)
{
dom_state *state = (dom_state *) _state;
- if (block == state->impl->start_block)
+ if (block == nir_start_block(state->impl))
return true;
nir_block *new_idom = NULL;
@@ -209,12 +209,13 @@ nir_calc_dominance_impl(nir_function_impl *impl)
nir_foreach_block(impl, calc_dom_frontier_cb, &state);
- impl->start_block->imm_dom = NULL;
+ nir_block *start_block = nir_start_block(impl);
+ start_block->imm_dom = NULL;
calc_dom_children(impl);
unsigned dfs_index = 0;
- calc_dfs_indicies(impl->start_block, &dfs_index);
+ calc_dfs_indicies(start_block, &dfs_index);
}
void
diff --git a/src/glsl/nir/nir_intrinsics.h b/src/glsl/nir/nir_intrinsics.h
index 64861300b55..1f24f9f677d 100644
--- a/src/glsl/nir/nir_intrinsics.h
+++ b/src/glsl/nir/nir_intrinsics.h
@@ -123,6 +123,8 @@ INTRINSIC(image_atomic_or, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
INTRINSIC(image_atomic_xor, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
INTRINSIC(image_atomic_exchange, 3, ARR(4, 1, 1), true, 1, 1, 0, 0)
INTRINSIC(image_atomic_comp_swap, 4, ARR(4, 1, 1, 1), true, 1, 1, 0, 0)
+INTRINSIC(image_size, 0, ARR(), true, 4, 1, 0,
+ NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
#define SYSTEM_VALUE(name, components) \
INTRINSIC(load_##name, 0, ARR(), true, components, 0, 0, \
@@ -139,12 +141,18 @@ SYSTEM_VALUE(sample_mask_in, 1)
SYSTEM_VALUE(invocation_id, 1)
/*
- * The last index is the base address to load from. Indirect loads have an
- * additional register input, which is added to the constant address to
- * compute the final address to load from. For UBO's (and SSBO's), the first
- * source is the (possibly constant) UBO buffer index and the indirect (if it
- * exists) is the second source, and the first index is the descriptor set
- * index.
+ * The format of the indices depends on the type of the load. For uniforms,
+ * the first index is the base address and the second index is an offset that
+ * should be added to the base address. (This way you can determine in the
+ * back-end which variable is being accessed even in an array.) For inputs,
+ * the one and only index corresponds to the attribute slot. UBO loads
+ * have two indices the first of which is the descriptor set and the second
+ * is the base address to load from.
+ *
+ * UBO loads have a (possibly constant) source which is the UBO buffer index.
+ * For each type of load, the _indirect variant has one additional source
+ * (the second in the case of UBO's) that is the is an indirect to be added to
+ * the constant address or base offset to compute the final offset.
*
* For vector backends, the address is in terms of one vec4, and so each array
* element is +4 scalar components from the previous array element. For scalar
@@ -152,14 +160,14 @@ SYSTEM_VALUE(invocation_id, 1)
* elements begin immediately after the previous array element.
*/
-#define LOAD(name, extra_srcs, extra_indices, flags) \
- INTRINSIC(load_##name, extra_srcs, ARR(1), true, 0, 0, 1 + extra_indices, flags) \
+#define LOAD(name, extra_srcs, indices, flags) \
+ INTRINSIC(load_##name, extra_srcs, ARR(1), true, 0, 0, indices, flags) \
INTRINSIC(load_##name##_indirect, extra_srcs + 1, ARR(1, 1), \
- true, 0, 0, 1 + extra_indices, flags)
+ true, 0, 0, indices, flags)
-LOAD(uniform, 0, 0, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-LOAD(ubo, 1, 1, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
-LOAD(input, 0, 0, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
+LOAD(uniform, 0, 2, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
+LOAD(ubo, 1, 2, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
+LOAD(input, 0, 1, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
/* LOAD(ssbo, 1, 0) */
/*
diff --git a/src/glsl/nir/nir_lower_io.c b/src/glsl/nir/nir_lower_io.c
index 6a4494d5fd2..c9697e7845e 100644
--- a/src/glsl/nir/nir_lower_io.c
+++ b/src/glsl/nir/nir_lower_io.c
@@ -32,103 +32,17 @@
*/
#include "nir.h"
+#include "nir_builder.h"
struct lower_io_state {
+ nir_builder builder;
void *mem_ctx;
- bool is_scalar;
+ int (*type_size)(const struct glsl_type *type);
};
-static int
-type_size_vec4(const struct glsl_type *type)
-{
- unsigned int i;
- int size;
-
- switch (glsl_get_base_type(type)) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- if (glsl_type_is_matrix(type)) {
- return glsl_get_matrix_columns(type);
- } else {
- return 1;
- }
- case GLSL_TYPE_ARRAY:
- return type_size_vec4(glsl_get_array_element(type)) * glsl_get_length(type);
- case GLSL_TYPE_STRUCT:
- size = 0;
- for (i = 0; i < glsl_get_length(type); i++) {
- size += type_size_vec4(glsl_get_struct_field(type, i));
- }
- return size;
- case GLSL_TYPE_SUBROUTINE:
- return 1;
- case GLSL_TYPE_SAMPLER:
- return 0;
- case GLSL_TYPE_ATOMIC_UINT:
- return 0;
- case GLSL_TYPE_IMAGE:
- case GLSL_TYPE_VOID:
- case GLSL_TYPE_DOUBLE:
- case GLSL_TYPE_ERROR:
- case GLSL_TYPE_INTERFACE:
- unreachable("not reached");
- }
-
- return 0;
-}
-
-static unsigned
-type_size_scalar(const struct glsl_type *type)
-{
- unsigned int size, i;
-
- switch (glsl_get_base_type(type)) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- return glsl_get_components(type);
- case GLSL_TYPE_ARRAY:
- return type_size_scalar(glsl_get_array_element(type)) * glsl_get_length(type);
- case GLSL_TYPE_STRUCT:
- size = 0;
- for (i = 0; i < glsl_get_length(type); i++) {
- size += type_size_scalar(glsl_get_struct_field(type, i));
- }
- return size;
- case GLSL_TYPE_SUBROUTINE:
- return 1;
- case GLSL_TYPE_SAMPLER:
- return 0;
- case GLSL_TYPE_ATOMIC_UINT:
- return 0;
- case GLSL_TYPE_INTERFACE:
- return 0;
- case GLSL_TYPE_IMAGE:
- return 0;
- case GLSL_TYPE_FUNCTION:
- case GLSL_TYPE_VOID:
- case GLSL_TYPE_ERROR:
- case GLSL_TYPE_DOUBLE:
- unreachable("not reached");
- }
-
- return 0;
-}
-
-static unsigned
-type_size(const struct glsl_type *type, bool is_scalar)
-{
- if (is_scalar)
- return type_size_scalar(type);
- else
- return type_size_vec4(type);
-}
-
void
-nir_assign_var_locations(struct exec_list *var_list, unsigned *size, bool is_scalar)
+nir_assign_var_locations(struct exec_list *var_list, unsigned *size,
+ int (*type_size)(const struct glsl_type *))
{
unsigned location = 0;
@@ -142,7 +56,7 @@ nir_assign_var_locations(struct exec_list *var_list, unsigned *size, bool is_sca
continue;
var->data.driver_location = location;
- location += type_size(var->type, is_scalar);
+ location += type_size(var->type);
}
*size = location;
@@ -162,80 +76,6 @@ deref_has_indirect(nir_deref_var *deref)
return false;
}
-static bool
-mark_indirect_uses_block(nir_block *block, void *void_state)
-{
- struct set *indirect_set = void_state;
-
- nir_foreach_instr(block, instr) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
-
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
-
- for (unsigned i = 0;
- i < nir_intrinsic_infos[intrin->intrinsic].num_variables; i++) {
- if (deref_has_indirect(intrin->variables[i]))
- _mesa_set_add(indirect_set, intrin->variables[i]->var);
- }
- }
-
- return true;
-}
-
-/* Identical to nir_assign_var_locations_packed except that it assigns
- * locations to the variables that are used 100% directly first and then
- * assigns locations to variables that are used indirectly.
- */
-void
-nir_assign_var_locations_direct_first(nir_shader *shader,
- struct exec_list *var_list,
- unsigned *direct_size,
- unsigned *size,
- bool is_scalar)
-{
- struct set *indirect_set = _mesa_set_create(NULL, _mesa_hash_pointer,
- _mesa_key_pointer_equal);
-
- nir_foreach_overload(shader, overload) {
- if (overload->impl)
- nir_foreach_block(overload->impl, mark_indirect_uses_block,
- indirect_set);
- }
-
- unsigned location = 0;
-
- foreach_list_typed(nir_variable, var, node, var_list) {
- if ((var->data.mode == nir_var_uniform || var->data.mode == nir_var_shader_storage) &&
- var->interface_type != NULL)
- continue;
-
- if (_mesa_set_search(indirect_set, var))
- continue;
-
- var->data.driver_location = location;
- location += type_size(var->type, is_scalar);
- }
-
- *direct_size = location;
-
- foreach_list_typed(nir_variable, var, node, var_list) {
- if ((var->data.mode == nir_var_uniform || var->data.mode == nir_var_shader_storage) &&
- var->interface_type != NULL)
- continue;
-
- if (!_mesa_set_search(indirect_set, var))
- continue;
-
- var->data.driver_location = location;
- location += type_size(var->type, is_scalar);
- }
-
- *size = location;
-
- _mesa_set_destroy(indirect_set, NULL);
-}
-
static unsigned
get_io_offset(nir_deref_var *deref, nir_instr *instr, nir_src *indirect,
struct lower_io_state *state)
@@ -243,6 +83,9 @@ get_io_offset(nir_deref_var *deref, nir_instr *instr, nir_src *indirect,
bool found_indirect = false;
unsigned base_offset = 0;
+ nir_builder *b = &state->builder;
+ nir_builder_insert_before_instr(b, instr);
+
nir_deref *tail = &deref->deref;
while (tail->child != NULL) {
const struct glsl_type *parent_type = tail->type;
@@ -250,56 +93,56 @@ get_io_offset(nir_deref_var *deref, nir_instr *instr, nir_src *indirect,
if (tail->deref_type == nir_deref_type_array) {
nir_deref_array *deref_array = nir_deref_as_array(tail);
- unsigned size = type_size(tail->type, state->is_scalar);
+ unsigned size = state->type_size(tail->type);
base_offset += size * deref_array->base_offset;
if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
- nir_load_const_instr *load_const =
- nir_load_const_instr_create(state->mem_ctx, 1);
- load_const->value.u[0] = size;
- nir_instr_insert_before(instr, &load_const->instr);
-
- nir_alu_instr *mul = nir_alu_instr_create(state->mem_ctx,
- nir_op_imul);
- mul->src[0].src.is_ssa = true;
- mul->src[0].src.ssa = &load_const->def;
- nir_src_copy(&mul->src[1].src, &deref_array->indirect,
- state->mem_ctx);
- mul->dest.write_mask = 1;
- nir_ssa_dest_init(&mul->instr, &mul->dest.dest, 1, NULL);
- nir_instr_insert_before(instr, &mul->instr);
+ nir_ssa_def *mul =
+ nir_imul(b, nir_imm_int(b, size),
+ nir_ssa_for_src(b, deref_array->indirect, 1));
if (found_indirect) {
- nir_alu_instr *add = nir_alu_instr_create(state->mem_ctx,
- nir_op_iadd);
- add->src[0].src = *indirect;
- add->src[1].src.is_ssa = true;
- add->src[1].src.ssa = &mul->dest.dest.ssa;
- add->dest.write_mask = 1;
- nir_ssa_dest_init(&add->instr, &add->dest.dest, 1, NULL);
- nir_instr_insert_before(instr, &add->instr);
-
- indirect->is_ssa = true;
- indirect->ssa = &add->dest.dest.ssa;
+ indirect->ssa =
+ nir_iadd(b, nir_ssa_for_src(b, *indirect, 1), mul);
} else {
- indirect->is_ssa = true;
- indirect->ssa = &mul->dest.dest.ssa;
- found_indirect = true;
+ indirect->ssa = mul;
}
+ indirect->is_ssa = true;
+ found_indirect = true;
}
} else if (tail->deref_type == nir_deref_type_struct) {
nir_deref_struct *deref_struct = nir_deref_as_struct(tail);
- for (unsigned i = 0; i < deref_struct->index; i++)
- base_offset += type_size(glsl_get_struct_field(parent_type, i),
- state->is_scalar);
+ for (unsigned i = 0; i < deref_struct->index; i++) {
+ base_offset +=
+ state->type_size(glsl_get_struct_field(parent_type, i));
+ }
}
}
return base_offset;
}
+static nir_intrinsic_op
+load_op(nir_variable_mode mode, bool has_indirect)
+{
+ nir_intrinsic_op op;
+ switch (mode) {
+ case nir_var_shader_in:
+ op = has_indirect ? nir_intrinsic_load_input_indirect :
+ nir_intrinsic_load_input;
+ break;
+ case nir_var_uniform:
+ op = has_indirect ? nir_intrinsic_load_uniform_indirect :
+ nir_intrinsic_load_uniform;
+ break;
+ default:
+ unreachable("Unknown variable mode");
+ }
+ return op;
+}
+
static bool
nir_lower_io_block(nir_block *block, void *void_state)
{
@@ -319,31 +162,22 @@ nir_lower_io_block(nir_block *block, void *void_state)
bool has_indirect = deref_has_indirect(intrin->variables[0]);
- /* Figure out the opcode */
- nir_intrinsic_op load_op;
- switch (mode) {
- case nir_var_shader_in:
- load_op = has_indirect ? nir_intrinsic_load_input_indirect :
- nir_intrinsic_load_input;
- break;
- case nir_var_uniform:
- load_op = has_indirect ? nir_intrinsic_load_uniform_indirect :
- nir_intrinsic_load_uniform;
- break;
- default:
- unreachable("Unknown variable mode");
- }
-
- nir_intrinsic_instr *load = nir_intrinsic_instr_create(state->mem_ctx,
- load_op);
+ nir_intrinsic_instr *load =
+ nir_intrinsic_instr_create(state->mem_ctx,
+ load_op(mode, has_indirect));
load->num_components = intrin->num_components;
nir_src indirect;
unsigned offset = get_io_offset(intrin->variables[0],
&intrin->instr, &indirect, state);
- offset += intrin->variables[0]->var->data.driver_location;
- load->const_index[0] = offset;
+ unsigned location = intrin->variables[0]->var->data.driver_location;
+ if (mode == nir_var_uniform) {
+ load->const_index[0] = location;
+ load->const_index[1] = offset;
+ } else {
+ load->const_index[0] = location + offset;
+ }
if (has_indirect)
load->src[0] = indirect;
@@ -406,12 +240,13 @@ nir_lower_io_block(nir_block *block, void *void_state)
}
static void
-nir_lower_io_impl(nir_function_impl *impl, bool is_scalar)
+nir_lower_io_impl(nir_function_impl *impl, int(*type_size)(const struct glsl_type *))
{
struct lower_io_state state;
+ nir_builder_init(&state.builder, impl);
state.mem_ctx = ralloc_parent(impl);
- state.is_scalar = is_scalar;
+ state.type_size = type_size;
nir_foreach_block(impl, nir_lower_io_block, &state);
@@ -420,10 +255,10 @@ nir_lower_io_impl(nir_function_impl *impl, bool is_scalar)
}
void
-nir_lower_io(nir_shader *shader, bool is_scalar)
+nir_lower_io(nir_shader *shader, int(*type_size)(const struct glsl_type *))
{
nir_foreach_overload(shader, overload) {
if (overload->impl)
- nir_lower_io_impl(overload->impl, is_scalar);
+ nir_lower_io_impl(overload->impl, type_size);
}
}
diff --git a/src/glsl/nir/nir_lower_samplers.cpp b/src/glsl/nir/nir_lower_samplers.cpp
index 9a9cdd16a9a..438caacfd4d 100644
--- a/src/glsl/nir/nir_lower_samplers.cpp
+++ b/src/glsl/nir/nir_lower_samplers.cpp
@@ -192,12 +192,12 @@ lower_impl(nir_function_impl *impl, const struct gl_shader_program *shader_progr
}
extern "C" void
-nir_lower_samplers(nir_shader *shader, const struct gl_shader_program *shader_program,
- gl_shader_stage stage)
+nir_lower_samplers(nir_shader *shader,
+ const struct gl_shader_program *shader_program)
{
nir_foreach_overload(shader, overload) {
if (overload->impl)
- lower_impl(overload->impl, shader_program, stage);
+ lower_impl(overload->impl, shader_program, shader->stage);
}
}
diff --git a/src/glsl/nir/nir_lower_vars_to_ssa.c b/src/glsl/nir/nir_lower_vars_to_ssa.c
index ccb8f99dfba..4ff21663e57 100644
--- a/src/glsl/nir/nir_lower_vars_to_ssa.c
+++ b/src/glsl/nir/nir_lower_vars_to_ssa.c
@@ -935,7 +935,7 @@ nir_lower_vars_to_ssa_impl(nir_function_impl *impl)
nir_foreach_block(impl, register_variable_uses_block, &state);
insert_phi_nodes(&state);
- rename_variables_block(impl->start_block, &state);
+ rename_variables_block(nir_start_block(impl), &state);
nir_metadata_preserve(impl, nir_metadata_block_index |
nir_metadata_dominance);
diff --git a/src/glsl/nir/nir_opt_algebraic.py b/src/glsl/nir/nir_opt_algebraic.py
index d7c17403f9f..226e0a8d85c 100644
--- a/src/glsl/nir/nir_opt_algebraic.py
+++ b/src/glsl/nir/nir_opt_algebraic.py
@@ -113,6 +113,8 @@ optimizations = [
(('sge', a, b), ('b2f', ('fge', a, b)), 'options->lower_scmp'),
(('seq', a, b), ('b2f', ('feq', a, b)), 'options->lower_scmp'),
(('sne', a, b), ('b2f', ('fne', a, b)), 'options->lower_scmp'),
+ (('fne', ('fneg', a), a), ('fne', a, 0.0)),
+ (('feq', ('fneg', a), a), ('feq', a, 0.0)),
# Emulating booleans
(('imul', ('b2i', a), ('b2i', b)), ('b2i', ('iand', a, b))),
(('fmul', ('b2f', a), ('b2f', b)), ('b2f', ('iand', a, b))),
diff --git a/src/glsl/nir/nir_opt_gcm.c b/src/glsl/nir/nir_opt_gcm.c
index 44068bf37b8..5b412eebc32 100644
--- a/src/glsl/nir/nir_opt_gcm.c
+++ b/src/glsl/nir/nir_opt_gcm.c
@@ -256,7 +256,7 @@ gcm_schedule_early_instr(nir_instr *instr, struct gcm_state *state)
/* Start with the instruction at the top. As we iterate over the
* sources, it will get moved down as needed.
*/
- instr->block = state->impl->start_block;
+ instr->block = nir_start_block(state->impl);
state->instr = instr;
nir_foreach_src(instr, gcm_schedule_early_src, state);
diff --git a/src/glsl/nir/nir_opt_peephole_select.c b/src/glsl/nir/nir_opt_peephole_select.c
index 6620e5dc81f..26ec4ed92d3 100644
--- a/src/glsl/nir/nir_opt_peephole_select.c
+++ b/src/glsl/nir/nir_opt_peephole_select.c
@@ -26,6 +26,7 @@
*/
#include "nir.h"
+#include "nir_control_flow.h"
/*
* Implements a small peephole optimization that looks for
diff --git a/src/glsl/nir/nir_spirv.h b/src/glsl/nir/nir_spirv.h
index 3254f10a88d..1f09174ad7f 100644
--- a/src/glsl/nir/nir_spirv.h
+++ b/src/glsl/nir/nir_spirv.h
@@ -37,6 +37,7 @@ extern "C" {
#endif
nir_shader *spirv_to_nir(const uint32_t *words, size_t word_count,
+ gl_shader_stage stage,
const nir_shader_compiler_options *options);
#ifdef __cplusplus
diff --git a/src/glsl/nir/nir_to_ssa.c b/src/glsl/nir/nir_to_ssa.c
index a3c35fa0493..b089df79fcf 100644
--- a/src/glsl/nir/nir_to_ssa.c
+++ b/src/glsl/nir/nir_to_ssa.c
@@ -516,7 +516,7 @@ nir_convert_to_ssa_impl(nir_function_impl *impl)
rewrite_state state;
init_rewrite_state(impl, &state);
- rewrite_block(impl->start_block, &state);
+ rewrite_block(nir_start_block(impl), &state);
remove_unused_regs(impl, &state);
diff --git a/src/glsl/nir/nir_validate.c b/src/glsl/nir/nir_validate.c
index dc799414d24..9938c0ef8b1 100644
--- a/src/glsl/nir/nir_validate.c
+++ b/src/glsl/nir/nir_validate.c
@@ -75,6 +75,9 @@ typedef struct {
/* the current if statement being validated */
nir_if *if_stmt;
+ /* the current loop being visited */
+ nir_loop *loop;
+
/* the parent of the current cf node being visited */
nir_cf_node *parent_node;
@@ -594,9 +597,85 @@ validate_block(nir_block *block, validate_state *state)
}
}
+ struct set_entry *entry;
+ set_foreach(block->predecessors, entry) {
+ const nir_block *pred = entry->key;
+ assert(pred->successors[0] == block ||
+ pred->successors[1] == block);
+ }
+
if (!exec_list_is_empty(&block->instr_list) &&
- nir_block_last_instr(block)->type == nir_instr_type_jump)
+ nir_block_last_instr(block)->type == nir_instr_type_jump) {
assert(block->successors[1] == NULL);
+ nir_jump_instr *jump = nir_instr_as_jump(nir_block_last_instr(block));
+ switch (jump->type) {
+ case nir_jump_break: {
+ nir_block *after =
+ nir_cf_node_as_block(nir_cf_node_next(&state->loop->cf_node));
+ assert(block->successors[0] == after);
+ break;
+ }
+
+ case nir_jump_continue: {
+ nir_block *first =
+ nir_cf_node_as_block(nir_loop_first_cf_node(state->loop));
+ assert(block->successors[0] == first);
+ break;
+ }
+
+ case nir_jump_return:
+ assert(block->successors[0] == state->impl->end_block);
+ break;
+
+ default:
+ unreachable("bad jump type");
+ }
+ } else {
+ nir_cf_node *next = nir_cf_node_next(&block->cf_node);
+ if (next == NULL) {
+ switch (state->parent_node->type) {
+ case nir_cf_node_loop: {
+ nir_block *first =
+ nir_cf_node_as_block(nir_loop_first_cf_node(state->loop));
+ assert(block->successors[0] == first);
+ /* due to the hack for infinite loops, block->successors[1] may
+ * point to the block after the loop.
+ */
+ break;
+ }
+
+ case nir_cf_node_if: {
+ nir_block *after =
+ nir_cf_node_as_block(nir_cf_node_next(state->parent_node));
+ assert(block->successors[0] == after);
+ assert(block->successors[1] == NULL);
+ break;
+ }
+
+ case nir_cf_node_function:
+ assert(block->successors[0] == state->impl->end_block);
+ assert(block->successors[1] == NULL);
+ break;
+
+ default:
+ unreachable("unknown control flow node type");
+ }
+ } else {
+ if (next->type == nir_cf_node_if) {
+ nir_if *if_stmt = nir_cf_node_as_if(next);
+ assert(&block->successors[0]->cf_node ==
+ nir_if_first_then_node(if_stmt));
+ assert(&block->successors[1]->cf_node ==
+ nir_if_first_else_node(if_stmt));
+ } else {
+ assert(next->type == nir_cf_node_loop);
+ nir_loop *loop = nir_cf_node_as_loop(next);
+ assert(&block->successors[0]->cf_node ==
+ nir_loop_first_cf_node(loop));
+ assert(block->successors[1] == NULL);
+ }
+ }
+ }
}
static void
@@ -608,12 +687,6 @@ validate_if(nir_if *if_stmt, validate_state *state)
nir_cf_node *prev_node = nir_cf_node_prev(&if_stmt->cf_node);
assert(prev_node->type == nir_cf_node_block);
- nir_block *prev_block = nir_cf_node_as_block(prev_node);
- assert(&prev_block->successors[0]->cf_node ==
- nir_if_first_then_node(if_stmt));
- assert(&prev_block->successors[1]->cf_node ==
- nir_if_first_else_node(if_stmt));
-
assert(!exec_node_is_tail_sentinel(if_stmt->cf_node.node.next));
nir_cf_node *next_node = nir_cf_node_next(&if_stmt->cf_node);
assert(next_node->type == nir_cf_node_block);
@@ -647,10 +720,6 @@ validate_loop(nir_loop *loop, validate_state *state)
nir_cf_node *prev_node = nir_cf_node_prev(&loop->cf_node);
assert(prev_node->type == nir_cf_node_block);
- nir_block *prev_block = nir_cf_node_as_block(prev_node);
- assert(&prev_block->successors[0]->cf_node == nir_loop_first_cf_node(loop));
- assert(prev_block->successors[1] == NULL);
-
assert(!exec_node_is_tail_sentinel(loop->cf_node.node.next));
nir_cf_node *next_node = nir_cf_node_next(&loop->cf_node);
assert(next_node->type == nir_cf_node_block);
@@ -659,6 +728,8 @@ validate_loop(nir_loop *loop, validate_state *state)
nir_cf_node *old_parent = state->parent_node;
state->parent_node = &loop->cf_node;
+ nir_loop *old_loop = state->loop;
+ state->loop = loop;
exec_list_validate(&loop->body);
foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) {
@@ -666,6 +737,7 @@ validate_loop(nir_loop *loop, validate_state *state)
}
state->parent_node = old_parent;
+ state->loop = old_loop;
}
static void
@@ -921,6 +993,7 @@ init_validate_state(validate_state *state)
state->regs_found = NULL;
state->var_defs = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
_mesa_key_pointer_equal);
+ state->loop = NULL;
}
static void
diff --git a/src/glsl/nir/spirv2nir.c b/src/glsl/nir/spirv2nir.c
index 0eed23fbc3f..a7b8c0f4b15 100644
--- a/src/glsl/nir/spirv2nir.c
+++ b/src/glsl/nir/spirv2nir.c
@@ -49,6 +49,6 @@ int main(int argc, char **argv)
const void *map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
assert(map != NULL);
- nir_shader *shader = spirv_to_nir(map, word_count, NULL);
+ nir_shader *shader = spirv_to_nir(map, word_count, MESA_SHADER_FRAGMENT, NULL);
nir_print_shader(shader, stderr);
}
diff --git a/src/glsl/nir/spirv_to_nir.c b/src/glsl/nir/spirv_to_nir.c
index 65a995c29de..771637e8912 100644
--- a/src/glsl/nir/spirv_to_nir.c
+++ b/src/glsl/nir/spirv_to_nir.c
@@ -27,6 +27,7 @@
#include "spirv_to_nir_private.h"
#include "nir_vla.h"
+#include "nir_control_flow.h"
static struct vtn_ssa_value *
vtn_const_ssa_value(struct vtn_builder *b, nir_constant *constant,
@@ -2927,6 +2928,7 @@ vtn_walk_blocks(struct vtn_builder *b, struct vtn_block *start,
nir_shader *
spirv_to_nir(const uint32_t *words, size_t word_count,
+ gl_shader_stage stage,
const nir_shader_compiler_options *options)
{
const uint32_t *word_end = words + word_count;
@@ -2942,7 +2944,7 @@ spirv_to_nir(const uint32_t *words, size_t word_count,
words+= 5;
- nir_shader *shader = nir_shader_create(NULL, options);
+ nir_shader *shader = nir_shader_create(NULL, stage, options);
/* Initialize the stn_builder object */
struct vtn_builder *b = rzalloc(NULL, struct vtn_builder);
diff --git a/src/glsl/opt_constant_propagation.cpp b/src/glsl/opt_constant_propagation.cpp
index 10be8e800ff..5221417aca0 100644
--- a/src/glsl/opt_constant_propagation.cpp
+++ b/src/glsl/opt_constant_propagation.cpp
@@ -110,6 +110,8 @@ public:
virtual ir_visitor_status visit_enter(class ir_if *);
void add_constant(ir_assignment *ir);
+ void constant_folding(ir_rvalue **rvalue);
+ void constant_propagation(ir_rvalue **rvalue);
void kill(ir_variable *ir, unsigned write_mask);
void handle_if_block(exec_list *instructions);
void handle_rvalue(ir_rvalue **rvalue);
@@ -132,8 +134,38 @@ public:
void
-ir_constant_propagation_visitor::handle_rvalue(ir_rvalue **rvalue)
-{
+ir_constant_propagation_visitor::constant_folding(ir_rvalue **rvalue) {
+
+ if (*rvalue == NULL || (*rvalue)->ir_type == ir_type_constant)
+ return;
+
+ /* Note that we visit rvalues one leaving. So if an expression has a
+ * non-constant operand, no need to go looking down it to find if it's
+ * constant. This cuts the time of this pass down drastically.
+ */
+ ir_expression *expr = (*rvalue)->as_expression();
+ if (expr) {
+ for (unsigned int i = 0; i < expr->get_num_operands(); i++) {
+ if (!expr->operands[i]->as_constant())
+ return;
+ }
+ }
+
+ /* Ditto for swizzles. */
+ ir_swizzle *swiz = (*rvalue)->as_swizzle();
+ if (swiz && !swiz->val->as_constant())
+ return;
+
+ ir_constant *constant = (*rvalue)->constant_expression_value();
+ if (constant) {
+ *rvalue = constant;
+ this->progress = true;
+ }
+}
+
+void
+ir_constant_propagation_visitor::constant_propagation(ir_rvalue **rvalue) {
+
if (this->in_assignee || !*rvalue)
return;
@@ -216,6 +248,13 @@ ir_constant_propagation_visitor::handle_rvalue(ir_rvalue **rvalue)
this->progress = true;
}
+void
+ir_constant_propagation_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+ constant_propagation(rvalue);
+ constant_folding(rvalue);
+}
+
ir_visitor_status
ir_constant_propagation_visitor::visit_enter(ir_function_signature *ir)
{
@@ -243,6 +282,8 @@ ir_constant_propagation_visitor::visit_enter(ir_function_signature *ir)
ir_visitor_status
ir_constant_propagation_visitor::visit_leave(ir_assignment *ir)
{
+ constant_folding(&ir->rhs);
+
if (this->in_assignee)
return visit_continue;
diff --git a/src/glsl/shader_enums.h b/src/glsl/shader_enums.h
index 3fef7c48d6f..0c64af05fad 100644
--- a/src/glsl/shader_enums.h
+++ b/src/glsl/shader_enums.h
@@ -48,158 +48,6 @@ typedef enum
#define MESA_SHADER_STAGES (MESA_SHADER_COMPUTE + 1)
/**
- * Bitflags for system values.
- */
-#define SYSTEM_BIT_SAMPLE_ID ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_ID)
-#define SYSTEM_BIT_SAMPLE_POS ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_POS)
-#define SYSTEM_BIT_SAMPLE_MASK_IN ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_MASK_IN)
-/**
- * If the gl_register_file is PROGRAM_SYSTEM_VALUE, the register index will be
- * one of these values. If a NIR variable's mode is nir_var_system_value, it
- * will be one of these values.
- */
-typedef enum
-{
- /**
- * \name Vertex shader system values
- */
- /*@{*/
- /**
- * OpenGL-style vertex ID.
- *
- * Section 2.11.7 (Shader Execution), subsection Shader Inputs, of the
- * OpenGL 3.3 core profile spec says:
- *
- * "gl_VertexID holds the integer index i implicitly passed by
- * DrawArrays or one of the other drawing commands defined in section
- * 2.8.3."
- *
- * Section 2.8.3 (Drawing Commands) of the same spec says:
- *
- * "The commands....are equivalent to the commands with the same base
- * name (without the BaseVertex suffix), except that the ith element
- * transferred by the corresponding draw call will be taken from
- * element indices[i] + basevertex of each enabled array."
- *
- * Additionally, the overview in the GL_ARB_shader_draw_parameters spec
- * says:
- *
- * "In unextended GL, vertex shaders have inputs named gl_VertexID and
- * gl_InstanceID, which contain, respectively the index of the vertex
- * and instance. The value of gl_VertexID is the implicitly passed
- * index of the vertex being processed, which includes the value of
- * baseVertex, for those commands that accept it."
- *
- * gl_VertexID gets basevertex added in. This differs from DirectX where
- * SV_VertexID does \b not get basevertex added in.
- *
- * \note
- * If all system values are available, \c SYSTEM_VALUE_VERTEX_ID will be
- * equal to \c SYSTEM_VALUE_VERTEX_ID_ZERO_BASE plus
- * \c SYSTEM_VALUE_BASE_VERTEX.
- *
- * \sa SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, SYSTEM_VALUE_BASE_VERTEX
- */
- SYSTEM_VALUE_VERTEX_ID,
-
- /**
- * Instanced ID as supplied to gl_InstanceID
- *
- * Values assigned to gl_InstanceID always begin with zero, regardless of
- * the value of baseinstance.
- *
- * Section 11.1.3.9 (Shader Inputs) of the OpenGL 4.4 core profile spec
- * says:
- *
- * "gl_InstanceID holds the integer instance number of the current
- * primitive in an instanced draw call (see section 10.5)."
- *
- * Through a big chain of pseudocode, section 10.5 describes that
- * baseinstance is not counted by gl_InstanceID. In that section, notice
- *
- * "If an enabled vertex attribute array is instanced (it has a
- * non-zero divisor as specified by VertexAttribDivisor), the element
- * index that is transferred to the GL, for all vertices, is given by
- *
- * floor(instance/divisor) + baseinstance
- *
- * If an array corresponding to an attribute required by a vertex
- * shader is not enabled, then the corresponding element is taken from
- * the current attribute state (see section 10.2)."
- *
- * Note that baseinstance is \b not included in the value of instance.
- */
- SYSTEM_VALUE_INSTANCE_ID,
-
- /**
- * DirectX-style vertex ID.
- *
- * Unlike \c SYSTEM_VALUE_VERTEX_ID, this system value does \b not include
- * the value of basevertex.
- *
- * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_BASE_VERTEX
- */
- SYSTEM_VALUE_VERTEX_ID_ZERO_BASE,
-
- /**
- * Value of \c basevertex passed to \c glDrawElementsBaseVertex and similar
- * functions.
- *
- * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE
- */
- SYSTEM_VALUE_BASE_VERTEX,
- /*@}*/
-
- /**
- * \name Geometry shader system values
- */
- /*@{*/
- SYSTEM_VALUE_INVOCATION_ID, /**< (Also in Tessellation Control shader) */
- /*@}*/
-
- /**
- * \name Fragment shader system values
- */
- /*@{*/
- SYSTEM_VALUE_FRONT_FACE, /**< (not done yet) */
- SYSTEM_VALUE_SAMPLE_ID,
- SYSTEM_VALUE_SAMPLE_POS,
- SYSTEM_VALUE_SAMPLE_MASK_IN,
- /*@}*/
-
- /**
- * \name Tessellation Evaluation shader system values
- */
- /*@{*/
- SYSTEM_VALUE_TESS_COORD,
- SYSTEM_VALUE_VERTICES_IN, /**< Tessellation vertices in input patch */
- SYSTEM_VALUE_PRIMITIVE_ID, /**< (currently not used by GS) */
- SYSTEM_VALUE_TESS_LEVEL_OUTER, /**< TES input */
- SYSTEM_VALUE_TESS_LEVEL_INNER, /**< TES input */
- /*@}*/
-
- SYSTEM_VALUE_MAX /**< Number of values */
-} gl_system_value;
-
-
-/**
- * The possible interpolation qualifiers that can be applied to a fragment
- * shader input in GLSL.
- *
- * Note: INTERP_QUALIFIER_NONE must be 0 so that memsetting the
- * gl_fragment_program data structure to 0 causes the default behavior.
- */
-enum glsl_interp_qualifier
-{
- INTERP_QUALIFIER_NONE = 0,
- INTERP_QUALIFIER_SMOOTH,
- INTERP_QUALIFIER_FLAT,
- INTERP_QUALIFIER_NOPERSPECTIVE,
- INTERP_QUALIFIER_COUNT /**< Number of interpolation qualifiers */
-};
-
-
-/**
* Indexes for vertex program attributes.
* GL_NV_vertex_program aliases generic attributes over the conventional
* attributes. In GL_ARB_vertex_program shader the aliasing is optional.
@@ -305,7 +153,6 @@ typedef enum
BITFIELD64_RANGE(VERT_ATTRIB_GENERIC(0), VERT_ATTRIB_GENERIC_MAX)
/*@}*/
-
/**
* Indexes for vertex shader outputs, geometry shader inputs/outputs, and
* fragment shader inputs.
@@ -346,9 +193,6 @@ typedef enum
VARYING_SLOT_TESS_LEVEL_OUTER, /* Only appears as TCS output. */
VARYING_SLOT_TESS_LEVEL_INNER, /* Only appears as TCS output. */
VARYING_SLOT_VAR0, /* First generic varying slot */
- VARYING_SLOT_MAX = VARYING_SLOT_VAR0 + MAX_VARYING,
- VARYING_SLOT_PATCH0 = VARYING_SLOT_MAX,
- VARYING_SLOT_TESS_MAX = VARYING_SLOT_PATCH0 + MAX_VARYING
} gl_varying_slot;
@@ -383,9 +227,161 @@ typedef enum
#define VARYING_BIT_VIEWPORT BITFIELD64_BIT(VARYING_SLOT_VIEWPORT)
#define VARYING_BIT_FACE BITFIELD64_BIT(VARYING_SLOT_FACE)
#define VARYING_BIT_PNTC BITFIELD64_BIT(VARYING_SLOT_PNTC)
+#define VARYING_BIT_TESS_LEVEL_OUTER BITFIELD64_BIT(VARYING_SLOT_TESS_LEVEL_OUTER)
+#define VARYING_BIT_TESS_LEVEL_INNER BITFIELD64_BIT(VARYING_SLOT_TESS_LEVEL_INNER)
#define VARYING_BIT_VAR(V) BITFIELD64_BIT(VARYING_SLOT_VAR0 + (V))
/*@}*/
+/**
+ * Bitflags for system values.
+ */
+#define SYSTEM_BIT_SAMPLE_ID ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_ID)
+#define SYSTEM_BIT_SAMPLE_POS ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_POS)
+#define SYSTEM_BIT_SAMPLE_MASK_IN ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_MASK_IN)
+/**
+ * If the gl_register_file is PROGRAM_SYSTEM_VALUE, the register index will be
+ * one of these values. If a NIR variable's mode is nir_var_system_value, it
+ * will be one of these values.
+ */
+typedef enum
+{
+ /**
+ * \name Vertex shader system values
+ */
+ /*@{*/
+ /**
+ * OpenGL-style vertex ID.
+ *
+ * Section 2.11.7 (Shader Execution), subsection Shader Inputs, of the
+ * OpenGL 3.3 core profile spec says:
+ *
+ * "gl_VertexID holds the integer index i implicitly passed by
+ * DrawArrays or one of the other drawing commands defined in section
+ * 2.8.3."
+ *
+ * Section 2.8.3 (Drawing Commands) of the same spec says:
+ *
+ * "The commands....are equivalent to the commands with the same base
+ * name (without the BaseVertex suffix), except that the ith element
+ * transferred by the corresponding draw call will be taken from
+ * element indices[i] + basevertex of each enabled array."
+ *
+ * Additionally, the overview in the GL_ARB_shader_draw_parameters spec
+ * says:
+ *
+ * "In unextended GL, vertex shaders have inputs named gl_VertexID and
+ * gl_InstanceID, which contain, respectively the index of the vertex
+ * and instance. The value of gl_VertexID is the implicitly passed
+ * index of the vertex being processed, which includes the value of
+ * baseVertex, for those commands that accept it."
+ *
+ * gl_VertexID gets basevertex added in. This differs from DirectX where
+ * SV_VertexID does \b not get basevertex added in.
+ *
+ * \note
+ * If all system values are available, \c SYSTEM_VALUE_VERTEX_ID will be
+ * equal to \c SYSTEM_VALUE_VERTEX_ID_ZERO_BASE plus
+ * \c SYSTEM_VALUE_BASE_VERTEX.
+ *
+ * \sa SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, SYSTEM_VALUE_BASE_VERTEX
+ */
+ SYSTEM_VALUE_VERTEX_ID,
+
+ /**
+ * Instanced ID as supplied to gl_InstanceID
+ *
+ * Values assigned to gl_InstanceID always begin with zero, regardless of
+ * the value of baseinstance.
+ *
+ * Section 11.1.3.9 (Shader Inputs) of the OpenGL 4.4 core profile spec
+ * says:
+ *
+ * "gl_InstanceID holds the integer instance number of the current
+ * primitive in an instanced draw call (see section 10.5)."
+ *
+ * Through a big chain of pseudocode, section 10.5 describes that
+ * baseinstance is not counted by gl_InstanceID. In that section, notice
+ *
+ * "If an enabled vertex attribute array is instanced (it has a
+ * non-zero divisor as specified by VertexAttribDivisor), the element
+ * index that is transferred to the GL, for all vertices, is given by
+ *
+ * floor(instance/divisor) + baseinstance
+ *
+ * If an array corresponding to an attribute required by a vertex
+ * shader is not enabled, then the corresponding element is taken from
+ * the current attribute state (see section 10.2)."
+ *
+ * Note that baseinstance is \b not included in the value of instance.
+ */
+ SYSTEM_VALUE_INSTANCE_ID,
+
+ /**
+ * DirectX-style vertex ID.
+ *
+ * Unlike \c SYSTEM_VALUE_VERTEX_ID, this system value does \b not include
+ * the value of basevertex.
+ *
+ * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_BASE_VERTEX
+ */
+ SYSTEM_VALUE_VERTEX_ID_ZERO_BASE,
+
+ /**
+ * Value of \c basevertex passed to \c glDrawElementsBaseVertex and similar
+ * functions.
+ *
+ * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE
+ */
+ SYSTEM_VALUE_BASE_VERTEX,
+ /*@}*/
+
+ /**
+ * \name Geometry shader system values
+ */
+ /*@{*/
+ SYSTEM_VALUE_INVOCATION_ID, /**< (Also in Tessellation Control shader) */
+ /*@}*/
+
+ /**
+ * \name Fragment shader system values
+ */
+ /*@{*/
+ SYSTEM_VALUE_FRONT_FACE, /**< (not done yet) */
+ SYSTEM_VALUE_SAMPLE_ID,
+ SYSTEM_VALUE_SAMPLE_POS,
+ SYSTEM_VALUE_SAMPLE_MASK_IN,
+ /*@}*/
+
+ /**
+ * \name Tessellation Evaluation shader system values
+ */
+ /*@{*/
+ SYSTEM_VALUE_TESS_COORD,
+ SYSTEM_VALUE_VERTICES_IN, /**< Tessellation vertices in input patch */
+ SYSTEM_VALUE_PRIMITIVE_ID, /**< (currently not used by GS) */
+ SYSTEM_VALUE_TESS_LEVEL_OUTER, /**< TES input */
+ SYSTEM_VALUE_TESS_LEVEL_INNER, /**< TES input */
+ /*@}*/
+
+ SYSTEM_VALUE_MAX /**< Number of values */
+} gl_system_value;
+
+
+/**
+ * The possible interpolation qualifiers that can be applied to a fragment
+ * shader input in GLSL.
+ *
+ * Note: INTERP_QUALIFIER_NONE must be 0 so that memsetting the
+ * gl_fragment_program data structure to 0 causes the default behavior.
+ */
+enum glsl_interp_qualifier
+{
+ INTERP_QUALIFIER_NONE = 0,
+ INTERP_QUALIFIER_SMOOTH,
+ INTERP_QUALIFIER_FLAT,
+ INTERP_QUALIFIER_NOPERSPECTIVE,
+ INTERP_QUALIFIER_COUNT /**< Number of interpolation qualifiers */
+};
/**
* Fragment program results
@@ -405,8 +401,6 @@ typedef enum
* any are written, FRAG_RESULT_COLOR will not be written.
*/
FRAG_RESULT_DATA0 = 4,
- FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
} gl_frag_result;
-
#endif /* SHADER_ENUMS_H */
diff --git a/src/glx/dri_common.c b/src/glx/dri_common.c
index 63c8de38c7c..eedcd46a15a 100644
--- a/src/glx/dri_common.c
+++ b/src/glx/dri_common.c
@@ -253,8 +253,7 @@ __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
static int
scalarEqual(struct glx_config *mode, unsigned int attrib, unsigned int value)
{
- unsigned int glxValue;
- int i;
+ unsigned glxValue, i;
for (i = 0; i < ARRAY_SIZE(attribMap); i++)
if (attribMap[i].attrib == attrib) {
diff --git a/src/glx/dri_common_query_renderer.c b/src/glx/dri_common_query_renderer.c
index b3e107dc612..ebeedc9c037 100644
--- a/src/glx/dri_common_query_renderer.c
+++ b/src/glx/dri_common_query_renderer.c
@@ -56,7 +56,7 @@ static const struct {
static int
dri2_convert_glx_query_renderer_attribs(int attribute)
{
- int i;
+ unsigned i;
for (i = 0; i < ARRAY_SIZE(query_renderer_map); i++)
if (query_renderer_map[i].glx_attrib == attribute)
diff --git a/src/glx/glxext.c b/src/glx/glxext.c
index fdc24d439c1..dc87fb9e16c 100644
--- a/src/glx/glxext.c
+++ b/src/glx/glxext.c
@@ -138,6 +138,9 @@ __glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
if (!glxDraw)
return False;
+ aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
+ aevent->send_event = (awire->type & 0x80) != 0;
+ aevent->display = dpy;
aevent->event_type = awire->event_type;
aevent->drawable = glxDraw->xDrawable;
aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
diff --git a/src/mapi/glapi/gen/GL4x.xml b/src/mapi/glapi/gen/GL4x.xml
index 94ddfb72960..dee50275a57 100644
--- a/src/mapi/glapi/gen/GL4x.xml
+++ b/src/mapi/glapi/gen/GL4x.xml
@@ -44,4 +44,10 @@
<enum name="DEPTH_STENCIL_TEXTURE_MODE" value="0x90EA"/>
</category>
+<category name="4.5">
+ <function name="MemoryBarrierByRegion" es2="3.1">
+ <param name="barriers" type="GLbitfield"/>
+ </function>
+</category>
+
</OpenGLAPI>
diff --git a/src/mapi/glapi/gen/Makefile.am b/src/mapi/glapi/gen/Makefile.am
index 7d9d1a61215..86a92437f16 100644
--- a/src/mapi/glapi/gen/Makefile.am
+++ b/src/mapi/glapi/gen/Makefile.am
@@ -154,6 +154,7 @@ API_XML = \
ARB_shader_image_load_store.xml \
ARB_shader_subroutine.xml \
ARB_sync.xml \
+ ARB_tessellation_shader.xml \
ARB_texture_barrier.xml \
ARB_texture_buffer_object.xml \
ARB_texture_buffer_range.xml \
diff --git a/src/mesa/drivers/dri/common/drirc b/src/mesa/drivers/dri/common/drirc
index 97d961b6597..bb840eaba94 100644
--- a/src/mesa/drivers/dri/common/drirc
+++ b/src/mesa/drivers/dri/common/drirc
@@ -53,10 +53,12 @@ TODO: document the other workarounds.
<application name="Unigine OilRush (32-bit)" executable="OilRush_x86">
<option name="disable_blend_func_extended" value="true" />
+ <option name="allow_glsl_extension_directive_midshader" value="true" />
</application>
<application name="Unigine OilRush (64-bit)" executable="OilRush_x64">
<option name="disable_blend_func_extended" value="true" />
+ <option name="allow_glsl_extension_directive_midshader" value="true" />
</application>
<application name="Savage 2" executable="savage2.bin">
diff --git a/src/mesa/drivers/dri/common/utils.c b/src/mesa/drivers/dri/common/utils.c
index b51b263fe46..43d90d90599 100644
--- a/src/mesa/drivers/dri/common/utils.c
+++ b/src/mesa/drivers/dri/common/utils.c
@@ -452,7 +452,7 @@ int
driGetConfigAttrib(const __DRIconfig *config,
unsigned int attrib, unsigned int *value)
{
- int i;
+ unsigned i;
for (i = 0; i < ARRAY_SIZE(attribMap); i++)
if (attribMap[i].attrib == attrib)
diff --git a/src/mesa/drivers/dri/i915/intel_pixel_read.c b/src/mesa/drivers/dri/i915/intel_pixel_read.c
index 149e921218f..e6fa8f2dce8 100644
--- a/src/mesa/drivers/dri/i915/intel_pixel_read.c
+++ b/src/mesa/drivers/dri/i915/intel_pixel_read.c
@@ -91,7 +91,7 @@ do_blit_readpixels(struct gl_context * ctx,
if (ctx->_ImageTransferState ||
!_mesa_format_matches_format_and_type(irb->mt->format, format, type,
- false)) {
+ false, NULL)) {
DBG("%s - bad format for blit\n", __func__);
return false;
}
diff --git a/src/mesa/drivers/dri/i915/intel_tex_image.c b/src/mesa/drivers/dri/i915/intel_tex_image.c
index 0a213e9f614..5ab60d16173 100644
--- a/src/mesa/drivers/dri/i915/intel_tex_image.c
+++ b/src/mesa/drivers/dri/i915/intel_tex_image.c
@@ -134,7 +134,7 @@ try_pbo_upload(struct gl_context *ctx,
}
if (!_mesa_format_matches_format_and_type(intelImage->mt->format,
- format, type, false)) {
+ format, type, false, NULL)) {
DBG("%s: format mismatch (upload to %s with format 0x%x, type 0x%x)\n",
__func__, _mesa_get_format_name(intelImage->mt->format),
format, type);
diff --git a/src/mesa/drivers/dri/i965/brw_conditional_render.c b/src/mesa/drivers/dri/i965/brw_conditional_render.c
index 6d37c3b6928..122a4ecc0f6 100644
--- a/src/mesa/drivers/dri/i965/brw_conditional_render.c
+++ b/src/mesa/drivers/dri/i965/brw_conditional_render.c
@@ -56,6 +56,12 @@ set_predicate_for_result(struct brw_context *brw,
assert(query->bo != NULL);
+ /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM
+ * command when loading the values into the predicate source registers for
+ * conditional rendering.
+ */
+ brw_emit_pipe_control_flush(brw, PIPE_CONTROL_FLUSH_ENABLE);
+
brw_load_register_mem64(brw,
MI_PREDICATE_SRC0,
query->bo,
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index 328662da82e..0ee5ab2bdee 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -514,7 +514,7 @@ brw_initialize_context_constants(struct brw_context *brw)
ctx->Const.Program[MESA_SHADER_COMPUTE].MaxImageUniforms =
BRW_MAX_IMAGES;
ctx->Const.MaxImageUnits = MAX_IMAGE_UNITS;
- ctx->Const.MaxCombinedImageUnitsAndFragmentOutputs =
+ ctx->Const.MaxCombinedShaderOutputResources =
MAX_IMAGE_UNITS + BRW_MAX_DRAW_BUFFERS;
ctx->Const.MaxImageSamples = 0;
ctx->Const.MaxCombinedImageUniforms = 3 * BRW_MAX_IMAGES;
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index e092ef4a7c6..e5de4202c01 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -383,7 +383,7 @@ brw_postdraw_set_buffers_need_resolve(struct brw_context *brw)
brw_render_cache_set_add_bo(brw, stencil_irb->mt->bo);
}
- for (int i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ for (unsigned i = 0; i < fb->_NumColorDrawBuffers; i++) {
struct intel_renderbuffer *irb =
intel_renderbuffer(fb->_ColorDrawBuffers[i]);
@@ -626,7 +626,7 @@ brw_draw_init(struct brw_context *brw)
void
brw_draw_destroy(struct brw_context *brw)
{
- int i;
+ unsigned i;
for (i = 0; i < brw->vb.nr_buffers; i++) {
drm_intel_bo_unreference(brw->vb.buffers[i].bo);
diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c
index cbfd5855410..21d8f1e6994 100644
--- a/src/mesa/drivers/dri/i965/brw_draw_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c
@@ -395,7 +395,8 @@ brw_prepare_vertices(struct brw_context *brw)
GLuint interleaved = 0;
unsigned int min_index = brw->vb.min_index + brw->basevertex;
unsigned int max_index = brw->vb.max_index + brw->basevertex;
- int delta, i, j;
+ unsigned i;
+ int delta, j;
struct brw_vertex_element *upload[VERT_ATTRIB_MAX];
GLuint nr_uploads = 0;
@@ -418,10 +419,10 @@ brw_prepare_vertices(struct brw_context *brw)
/* Accumulate the list of enabled arrays. */
brw->vb.nr_enabled = 0;
while (vs_inputs) {
- GLuint i = ffsll(vs_inputs) - 1;
- struct brw_vertex_element *input = &brw->vb.inputs[i];
+ GLuint index = ffsll(vs_inputs) - 1;
+ struct brw_vertex_element *input = &brw->vb.inputs[index];
- vs_inputs &= ~BITFIELD64_BIT(i);
+ vs_inputs &= ~BITFIELD64_BIT(index);
brw->vb.enabled[brw->vb.nr_enabled++] = input;
}
@@ -438,7 +439,7 @@ brw_prepare_vertices(struct brw_context *brw)
if (_mesa_is_bufferobj(glarray->BufferObj)) {
struct intel_buffer_object *intel_buffer =
intel_buffer_object(glarray->BufferObj);
- int k;
+ unsigned k;
/* If we have a VB set to be uploaded for this buffer object
* already, reuse that VB state so that we emit fewer
@@ -792,21 +793,6 @@ brw_emit_vertices(struct brw_context *brw)
((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
}
- if (brw->gen >= 6 && gen6_edgeflag_input) {
- uint32_t format =
- brw_get_vertex_surface_type(brw, gen6_edgeflag_input->glarray);
-
- OUT_BATCH((gen6_edgeflag_input->buffer << GEN6_VE0_INDEX_SHIFT) |
- GEN6_VE0_VALID |
- GEN6_VE0_EDGE_FLAG_ENABLE |
- (format << BRW_VE0_FORMAT_SHIFT) |
- (gen6_edgeflag_input->offset << BRW_VE0_SRC_OFFSET_SHIFT));
- OUT_BATCH((BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_0_SHIFT) |
- (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) |
- (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
- (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT));
- }
-
if (brw->vs.prog_data->uses_vertexid || brw->vs.prog_data->uses_instanceid) {
uint32_t dw0 = 0, dw1 = 0;
uint32_t comp0 = BRW_VE1_COMPONENT_STORE_0;
@@ -847,6 +833,21 @@ brw_emit_vertices(struct brw_context *brw)
OUT_BATCH(dw1);
}
+ if (brw->gen >= 6 && gen6_edgeflag_input) {
+ uint32_t format =
+ brw_get_vertex_surface_type(brw, gen6_edgeflag_input->glarray);
+
+ OUT_BATCH((gen6_edgeflag_input->buffer << GEN6_VE0_INDEX_SHIFT) |
+ GEN6_VE0_VALID |
+ GEN6_VE0_EDGE_FLAG_ENABLE |
+ (format << BRW_VE0_FORMAT_SHIFT) |
+ (gen6_edgeflag_input->offset << BRW_VE0_SRC_OFFSET_SHIFT));
+ OUT_BATCH((BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_0_SHIFT) |
+ (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) |
+ (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
+ (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT));
+ }
+
ADVANCE_BATCH();
}
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 0e091ddc227..159f7161e11 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -455,8 +455,8 @@ fs_reg::component_size(unsigned width) const
return MAX2(width * stride, 1) * type_sz(type);
}
-int
-fs_visitor::type_size(const struct glsl_type *type)
+extern "C" int
+type_size_scalar(const struct glsl_type *type)
{
unsigned int size, i;
@@ -467,11 +467,11 @@ fs_visitor::type_size(const struct glsl_type *type)
case GLSL_TYPE_BOOL:
return type->components();
case GLSL_TYPE_ARRAY:
- return type_size(type->fields.array) * type->length;
+ return type_size_scalar(type->fields.array) * type->length;
case GLSL_TYPE_STRUCT:
size = 0;
for (i = 0; i < type->length; i++) {
- size += type_size(type->fields.structure[i].type);
+ size += type_size_scalar(type->fields.structure[i].type);
}
return size;
case GLSL_TYPE_SAMPLER:
@@ -907,7 +907,7 @@ fs_reg
fs_visitor::vgrf(const glsl_type *const type)
{
int reg_width = dispatch_width / 8;
- return fs_reg(GRF, alloc.allocate(type_size(type) * reg_width),
+ return fs_reg(GRF, alloc.allocate(type_size_scalar(type) * reg_width),
brw_type_for_base_type(type));
}
@@ -944,15 +944,17 @@ fs_visitor::import_uniforms(fs_visitor *v)
}
void
-fs_visitor::setup_vector_uniform_values(const gl_constant_value *values, unsigned n)
+fs_visitor::setup_vec4_uniform_value(unsigned param_offset,
+ const gl_constant_value *values,
+ unsigned n)
{
static const gl_constant_value zero = { 0 };
for (unsigned i = 0; i < n; ++i)
- stage_prog_data->param[uniforms++] = &values[i];
+ stage_prog_data->param[param_offset + i] = &values[i];
for (unsigned i = n; i < 4; ++i)
- stage_prog_data->param[uniforms++] = &zero;
+ stage_prog_data->param[param_offset + i] = &zero;
}
fs_reg *
@@ -1769,21 +1771,21 @@ fs_visitor::compact_virtual_grfs()
return progress;
}
-/*
- * Implements array access of uniforms by inserting a
- * PULL_CONSTANT_LOAD instruction.
+/**
+ * Assign UNIFORM file registers to either push constants or pull constants.
*
- * Unlike temporary GRF array access (where we don't support it due to
- * the difficulty of doing relative addressing on instruction
- * destinations), we could potentially do array access of uniforms
- * that were loaded in GRF space as push constants. In real-world
- * usage we've seen, though, the arrays being used are always larger
- * than we could load as push constants, so just always move all
- * uniform array access out to a pull constant buffer.
+ * We allow a fragment shader to have more than the specified minimum
+ * maximum number of fragment shader uniform components (64). If
+ * there are too many of these, they'd fill up all of register space.
+ * So, this will push some of them out to the pull constant buffer and
+ * update the program to load them. We also use pull constants for all
+ * indirect constant loads because we don't support indirect accesses in
+ * registers yet.
*/
void
-fs_visitor::move_uniform_array_access_to_pull_constants()
+fs_visitor::assign_constant_locations()
{
+ /* Only the first compile (SIMD8 mode) gets to decide on locations. */
if (dispatch_width != 8)
return;
@@ -1820,23 +1822,6 @@ fs_visitor::move_uniform_array_access_to_pull_constants()
}
}
}
-}
-
-/**
- * Assign UNIFORM file registers to either push constants or pull constants.
- *
- * We allow a fragment shader to have more than the specified minimum
- * maximum number of fragment shader uniform components (64). If
- * there are too many of these, they'd fill up all of register space.
- * So, this will push some of them out to the pull constant buffer and
- * update the program to load them.
- */
-void
-fs_visitor::assign_constant_locations()
-{
- /* Only the first compile (SIMD8 mode) gets to decide on locations. */
- if (dispatch_width != 8)
- return;
/* Find which UNIFORM registers are still in use. */
bool is_live[uniforms];
@@ -4823,7 +4808,6 @@ fs_visitor::optimize()
split_virtual_grfs();
- move_uniform_array_access_to_pull_constants();
assign_constant_locations();
demote_pull_constants();
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 975183e990d..31f39fe0adc 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -112,7 +112,6 @@ public:
void swizzle_result(ir_texture_opcode op, int dest_components,
fs_reg orig_val, uint32_t sampler);
- int type_size(const struct glsl_type *type);
fs_inst *get_instruction_generating_reg(fs_inst *start,
fs_inst *end,
const fs_reg &reg);
@@ -147,7 +146,6 @@ public:
void spill_reg(int spill_reg);
void split_virtual_grfs();
bool compact_virtual_grfs();
- void move_uniform_array_access_to_pull_constants();
void assign_constant_locations();
void demote_pull_constants();
void invalidate_live_intervals();
@@ -291,8 +289,9 @@ public:
struct brw_reg interp_reg(int location, int channel);
- virtual void setup_vector_uniform_values(const gl_constant_value *values,
- unsigned n);
+ virtual void setup_vec4_uniform_value(unsigned param_offset,
+ const gl_constant_value *values,
+ unsigned n);
int implied_mrf_writes(fs_inst *inst);
@@ -318,9 +317,6 @@ public:
/** Number of uniform variable components visited. */
unsigned uniforms;
- /** Total number of direct uniforms we can get from NIR */
- unsigned num_direct_uniforms;
-
/** Byte-offset for the next available spot in the scratch space buffer. */
unsigned last_scratch;
diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
index 93a36cc03bf..6272b61a98b 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
@@ -131,7 +131,7 @@ fs_visitor::nir_setup_outputs(nir_shader *shader)
switch (stage) {
case MESA_SHADER_VERTEX:
- for (int i = 0; i < ALIGN(type_size(var->type), 4) / 4; i++) {
+ for (int i = 0; i < ALIGN(type_size_scalar(var->type), 4) / 4; i++) {
int output = var->data.location + i;
this->outputs[output] = offset(reg, bld, 4 * i);
this->output_components[output] = vector_elements;
@@ -175,19 +175,9 @@ fs_visitor::nir_setup_outputs(nir_shader *shader)
void
fs_visitor::nir_setup_uniforms(nir_shader *shader)
{
- num_direct_uniforms = shader->num_direct_uniforms;
-
if (dispatch_width != 8)
return;
- /* We split the uniform register file in half. The first half is
- * entirely direct uniforms. The second half is indirect.
- */
- if (num_direct_uniforms > 0)
- param_size[0] = num_direct_uniforms;
- if (shader->num_uniforms > num_direct_uniforms)
- param_size[num_direct_uniforms] = shader->num_uniforms - num_direct_uniforms;
-
uniforms = shader->num_uniforms;
if (shader_prog) {
@@ -200,15 +190,19 @@ fs_visitor::nir_setup_uniforms(nir_shader *shader)
nir_setup_builtin_uniform(var);
else
nir_setup_uniform(var);
+
+ param_size[var->data.driver_location] = type_size_scalar(var->type);
}
} else {
- /* prog_to_nir doesn't create uniform variables; set param up directly. */
+ /* prog_to_nir only creates a single giant uniform variable so we can
+ * just set param up directly. */
for (unsigned p = 0; p < prog->Parameters->NumParameters; p++) {
for (unsigned int i = 0; i < 4; i++) {
stage_prog_data->param[4 * p + i] =
&prog->Parameters->ParameterValues[p][i];
}
}
+ param_size[0] = prog->Parameters->NumParameters * 4;
}
}
@@ -239,15 +233,7 @@ fs_visitor::nir_setup_uniform(nir_variable *var)
}
if (storage->type->is_image()) {
- /* Images don't get a valid location assigned by nir_lower_io()
- * because their size is driver-specific, so we need to allocate
- * space for them here at the end of the parameter array.
- */
- var->data.driver_location = uniforms;
- param_size[uniforms] =
- BRW_IMAGE_PARAM_SIZE * MAX2(storage->array_elements, 1);
-
- setup_image_uniform_values(storage);
+ setup_image_uniform_values(index, storage);
} else {
unsigned slots = storage->type->component_slots();
if (storage->array_elements)
@@ -1406,6 +1392,51 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
break;
}
+ case nir_intrinsic_image_size: {
+ /* Get the referenced image variable and type. */
+ const nir_variable *var = instr->variables[0]->var;
+ const glsl_type *type = var->type->without_array();
+
+ /* Get the size of the image. */
+ const fs_reg image = get_nir_image_deref(instr->variables[0]);
+ const fs_reg size = offset(image, bld, BRW_IMAGE_PARAM_SIZE_OFFSET);
+
+ /* For 1DArray image types, the array index is stored in the Z component.
+ * Fix this by swizzling the Z component to the Y component.
+ */
+ const bool is_1d_array_image =
+ type->sampler_dimensionality == GLSL_SAMPLER_DIM_1D &&
+ type->sampler_array;
+
+ /* For CubeArray images, we should count the number of cubes instead
+ * of the number of faces. Fix it by dividing the (Z component) by 6.
+ */
+ const bool is_cube_array_image =
+ type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE &&
+ type->sampler_array;
+
+ /* Copy all the components. */
+ const nir_intrinsic_info *info = &nir_intrinsic_infos[instr->intrinsic];
+ for (unsigned c = 0; c < info->dest_components; ++c) {
+ if ((int)c >= type->coordinate_components()) {
+ bld.MOV(offset(retype(dest, BRW_REGISTER_TYPE_D), bld, c),
+ fs_reg(1));
+ } else if (c == 1 && is_1d_array_image) {
+ bld.MOV(offset(retype(dest, BRW_REGISTER_TYPE_D), bld, c),
+ offset(size, bld, 2));
+ } else if (c == 2 && is_cube_array_image) {
+ bld.emit(SHADER_OPCODE_INT_QUOTIENT,
+ offset(retype(dest, BRW_REGISTER_TYPE_D), bld, c),
+ offset(size, bld, c), fs_reg(6));
+ } else {
+ bld.MOV(offset(retype(dest, BRW_REGISTER_TYPE_D), bld, c),
+ offset(size, bld, c));
+ }
+ }
+
+ break;
+ }
+
case nir_intrinsic_load_front_face:
bld.MOV(retype(dest, BRW_REGISTER_TYPE_D),
*emit_frontfacing_interpolation());
@@ -1467,21 +1498,13 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
has_indirect = true;
/* fallthrough */
case nir_intrinsic_load_uniform: {
- unsigned index = instr->const_index[0];
-
- fs_reg uniform_reg;
- if (index < num_direct_uniforms) {
- uniform_reg = fs_reg(UNIFORM, 0);
- } else {
- uniform_reg = fs_reg(UNIFORM, num_direct_uniforms);
- index -= num_direct_uniforms;
- }
+ fs_reg uniform_reg(UNIFORM, instr->const_index[0]);
+ uniform_reg.reg_offset = instr->const_index[1];
for (unsigned j = 0; j < instr->num_components; j++) {
- fs_reg src = offset(retype(uniform_reg, dest.type), bld, index);
+ fs_reg src = offset(retype(uniform_reg, dest.type), bld, j);
if (has_indirect)
src.reladdr = new(mem_ctx) fs_reg(get_nir_src(instr->src[0]));
- index++;
bld.MOV(dest, src);
dest = offset(dest, bld, 1);
diff --git a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp
index b70895ec2ff..6eb988938d4 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp
@@ -156,7 +156,7 @@ brw_alloc_reg_set(struct brw_compiler *compiler, int dispatch_width)
}
uint8_t *ra_reg_to_grf = ralloc_array(compiler, uint8_t, ra_reg_count);
- struct ra_regs *regs = ra_alloc_reg_set(compiler, ra_reg_count);
+ struct ra_regs *regs = ra_alloc_reg_set(compiler, ra_reg_count, false);
if (devinfo->gen >= 6)
ra_set_allocate_round_robin(regs);
int *classes = ralloc_array(compiler, int, class_count);
@@ -232,7 +232,7 @@ brw_alloc_reg_set(struct brw_compiler *compiler, int dispatch_width)
for (int base_reg = j;
base_reg < j + (class_sizes[i] + 1) / 2;
base_reg++) {
- ra_add_transitive_reg_conflict(regs, base_reg, reg);
+ ra_add_reg_conflict(regs, base_reg, reg);
}
reg++;
@@ -246,7 +246,7 @@ brw_alloc_reg_set(struct brw_compiler *compiler, int dispatch_width)
for (int base_reg = j;
base_reg < j + class_sizes[i];
base_reg++) {
- ra_add_transitive_reg_conflict(regs, base_reg, reg);
+ ra_add_reg_conflict(regs, base_reg, reg);
}
reg++;
@@ -255,6 +255,12 @@ brw_alloc_reg_set(struct brw_compiler *compiler, int dispatch_width)
}
assert(reg == ra_reg_count);
+ /* Applying transitivity to all of the base registers gives us the
+ * appropreate register conflict relationships everywhere.
+ */
+ for (int reg = 0; reg < base_reg_count; reg++)
+ ra_make_reg_conflicts_transitive(regs, reg);
+
/* Add a special class for aligned pairs, which we'll put delta_xy
* in on Gen <= 6 so that we can do PLN.
*/
diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c
index e9d9467d330..27511525bff 100644
--- a/src/mesa/drivers/dri/i965/brw_misc_state.c
+++ b/src/mesa/drivers/dri/i965/brw_misc_state.c
@@ -878,7 +878,8 @@ brw_upload_invariant_state(struct brw_context *brw)
{
const bool is_965 = brw->gen == 4 && !brw->is_g4x;
- brw_select_pipeline(brw, BRW_RENDER_PIPELINE);
+ brw_emit_select_pipeline(brw, BRW_RENDER_PIPELINE);
+ brw->last_pipeline = BRW_RENDER_PIPELINE;
if (brw->gen < 6) {
/* Disable depth offset clamping. */
diff --git a/src/mesa/drivers/dri/i965/brw_nir.c b/src/mesa/drivers/dri/i965/brw_nir.c
index 79e31d86759..0276d47c4d4 100644
--- a/src/mesa/drivers/dri/i965/brw_nir.c
+++ b/src/mesa/drivers/dri/i965/brw_nir.c
@@ -22,6 +22,7 @@
*/
#include "brw_nir.h"
+#include "brw_shader.h"
#include "glsl/glsl_parser_extras.h"
#include "glsl/nir/glsl_to_nir.h"
#include "program/prog_to_nir.h"
@@ -130,22 +131,24 @@ brw_process_nir(nir_shader *nir,
nir_optimize(nir, is_scalar);
if (is_scalar) {
- nir_assign_var_locations_direct_first(nir, &nir->uniforms,
- &nir->num_direct_uniforms,
- &nir->num_uniforms,
- is_scalar);
- nir_assign_var_locations(&nir->outputs, &nir->num_outputs, is_scalar);
+ nir_assign_var_locations(&nir->uniforms,
+ &nir->num_uniforms,
+ type_size_scalar);
+ nir_assign_var_locations(&nir->inputs, &nir->num_inputs, type_size_scalar);
+ nir_assign_var_locations(&nir->outputs, &nir->num_outputs, type_size_scalar);
+ nir_lower_io(nir, type_size_scalar);
} else {
nir_assign_var_locations(&nir->uniforms,
&nir->num_uniforms,
- is_scalar);
+ type_size_vec4);
+
+ nir_assign_var_locations(&nir->inputs, &nir->num_inputs, type_size_vec4);
foreach_list_typed(nir_variable, var, node, &nir->outputs)
var->data.driver_location = var->data.location;
- }
- nir_assign_var_locations(&nir->inputs, &nir->num_inputs, is_scalar);
- nir_lower_io(nir, is_scalar);
+ nir_lower_io(nir, type_size_vec4);
+ }
nir_validate_shader(nir);
@@ -153,7 +156,7 @@ brw_process_nir(nir_shader *nir,
nir_validate_shader(nir);
if (shader_prog) {
- nir_lower_samplers(nir, shader_prog, stage);
+ nir_lower_samplers(nir, shader_prog);
} else {
nir_lower_samplers_for_vk(nir);
}
diff --git a/src/mesa/drivers/dri/i965/brw_primitive_restart.c b/src/mesa/drivers/dri/i965/brw_primitive_restart.c
index 6ed79d7cb75..c8d90027ea0 100644
--- a/src/mesa/drivers/dri/i965/brw_primitive_restart.c
+++ b/src/mesa/drivers/dri/i965/brw_primitive_restart.c
@@ -91,7 +91,7 @@ can_cut_index_handle_prims(struct gl_context *ctx,
return false;
}
- for (int i = 0; i < nr_prims; i++) {
+ for (unsigned i = 0; i < nr_prims; i++) {
switch (prim[i].mode) {
case GL_POINTS:
case GL_LINES:
diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c
index d6b012c392e..a8e5ababba4 100644
--- a/src/mesa/drivers/dri/i965/brw_queryobj.c
+++ b/src/mesa/drivers/dri/i965/brw_queryobj.c
@@ -66,20 +66,11 @@ brw_write_timestamp(struct brw_context *brw, drm_intel_bo *query_bo, int idx)
void
brw_write_depth_count(struct brw_context *brw, drm_intel_bo *query_bo, int idx)
{
- uint32_t flags;
-
- flags = (PIPE_CONTROL_WRITE_DEPTH_COUNT |
- PIPE_CONTROL_DEPTH_STALL);
-
- /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM
- * command when loading the values into the predicate source registers for
- * conditional rendering.
- */
- if (brw->predicate.supported)
- flags |= PIPE_CONTROL_FLUSH_ENABLE;
-
- brw_emit_pipe_control_write(brw, flags, query_bo,
- idx * sizeof(uint64_t), 0, 0);
+ brw_emit_pipe_control_write(brw,
+ PIPE_CONTROL_WRITE_DEPTH_COUNT |
+ PIPE_CONTROL_DEPTH_STALL,
+ query_bo, idx * sizeof(uint64_t),
+ 0, 0);
}
/**
diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp
index 67b8dde7cc8..0007e5c07a5 100644
--- a/src/mesa/drivers/dri/i965/brw_shader.cpp
+++ b/src/mesa/drivers/dri/i965/brw_shader.cpp
@@ -122,7 +122,7 @@ brw_compiler_create(void *mem_ctx, const struct brw_device_info *devinfo)
compiler->glsl_compiler_options[MESA_SHADER_VERTEX].OptimizeForAOS = true;
compiler->glsl_compiler_options[MESA_SHADER_GEOMETRY].OptimizeForAOS = true;
- if (compiler->scalar_vs || brw_env_var_as_boolean("INTEL_USE_NIR", false)) {
+ if (compiler->scalar_vs || brw_env_var_as_boolean("INTEL_USE_NIR", true)) {
if (compiler->scalar_vs) {
/* If we're using the scalar backend for vertex shaders, we need to
* configure these accordingly.
@@ -135,7 +135,7 @@ brw_compiler_create(void *mem_ctx, const struct brw_device_info *devinfo)
compiler->glsl_compiler_options[MESA_SHADER_VERTEX].NirOptions = nir_options;
}
- if (brw_env_var_as_boolean("INTEL_USE_NIR", false)) {
+ if (brw_env_var_as_boolean("INTEL_USE_NIR", true)) {
compiler->glsl_compiler_options[MESA_SHADER_GEOMETRY].NirOptions = nir_options;
}
@@ -1421,7 +1421,8 @@ backend_shader::assign_common_binding_table_offsets(uint32_t next_binding_table_
}
void
-backend_shader::setup_image_uniform_values(const gl_uniform_storage *storage)
+backend_shader::setup_image_uniform_values(unsigned param_offset,
+ const gl_uniform_storage *storage)
{
const unsigned stage = _mesa_program_enum_to_shader_stage(prog->Target);
@@ -1432,18 +1433,19 @@ backend_shader::setup_image_uniform_values(const gl_uniform_storage *storage)
/* Upload the brw_image_param structure. The order is expected to match
* the BRW_IMAGE_PARAM_*_OFFSET defines.
*/
- setup_vector_uniform_values(
+ setup_vec4_uniform_value(param_offset + BRW_IMAGE_PARAM_SURFACE_IDX_OFFSET,
(const gl_constant_value *)&param->surface_idx, 1);
- setup_vector_uniform_values(
+ setup_vec4_uniform_value(param_offset + BRW_IMAGE_PARAM_OFFSET_OFFSET,
(const gl_constant_value *)param->offset, 2);
- setup_vector_uniform_values(
+ setup_vec4_uniform_value(param_offset + BRW_IMAGE_PARAM_SIZE_OFFSET,
(const gl_constant_value *)param->size, 3);
- setup_vector_uniform_values(
+ setup_vec4_uniform_value(param_offset + BRW_IMAGE_PARAM_STRIDE_OFFSET,
(const gl_constant_value *)param->stride, 4);
- setup_vector_uniform_values(
+ setup_vec4_uniform_value(param_offset + BRW_IMAGE_PARAM_TILING_OFFSET,
(const gl_constant_value *)param->tiling, 3);
- setup_vector_uniform_values(
+ setup_vec4_uniform_value(param_offset + BRW_IMAGE_PARAM_SWIZZLING_OFFSET,
(const gl_constant_value *)param->swizzling, 2);
+ param_offset += BRW_IMAGE_PARAM_SIZE;
brw_mark_surface_used(
stage_prog_data,
diff --git a/src/mesa/drivers/dri/i965/brw_shader.h b/src/mesa/drivers/dri/i965/brw_shader.h
index 2cc97f24972..ccccf4d6938 100644
--- a/src/mesa/drivers/dri/i965/brw_shader.h
+++ b/src/mesa/drivers/dri/i965/brw_shader.h
@@ -270,9 +270,11 @@ public:
virtual void invalidate_live_intervals() = 0;
- virtual void setup_vector_uniform_values(const gl_constant_value *values,
- unsigned n) = 0;
- void setup_image_uniform_values(const gl_uniform_storage *storage);
+ virtual void setup_vec4_uniform_value(unsigned param_offset,
+ const gl_constant_value *values,
+ unsigned n) = 0;
+ void setup_image_uniform_values(unsigned param_offset,
+ const gl_uniform_storage *storage);
};
uint32_t brw_texture_offset(int *offsets, unsigned num_components);
@@ -307,6 +309,9 @@ bool brw_cs_precompile(struct gl_context *ctx,
struct gl_shader_program *shader_prog,
struct gl_program *prog);
+int type_size_scalar(const struct glsl_type *type);
+int type_size_vec4(const struct glsl_type *type);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/mesa/drivers/dri/i965/brw_state_cache.c b/src/mesa/drivers/dri/i965/brw_state_cache.c
index 5effb4c8829..e817ecfb8cc 100644
--- a/src/mesa/drivers/dri/i965/brw_state_cache.c
+++ b/src/mesa/drivers/dri/i965/brw_state_cache.c
@@ -208,7 +208,7 @@ brw_lookup_prog(const struct brw_cache *cache,
const void *data, unsigned data_size)
{
const struct brw_context *brw = cache->brw;
- int i;
+ unsigned i;
const struct brw_cache_item *item;
for (i = 0; i < cache->size; i++) {
diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c
index b8b03932065..e96732a1908 100644
--- a/src/mesa/drivers/dri/i965/brw_tex_layout.c
+++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c
@@ -555,7 +555,7 @@ brw_miptree_layout_texture_array(struct brw_context *brw,
if (mt->compressed)
img_height /= mt->align_h;
- for (int q = 0; q < mt->level[level].depth; q++) {
+ for (unsigned q = 0; q < mt->level[level].depth; q++) {
if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) {
intel_miptree_set_image_offset(mt, level, q, 0, q * img_height);
} else {
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
index 341c516b39a..673a29e4b7f 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h
@@ -177,8 +177,9 @@ public:
void fail(const char *msg, ...);
void setup_uniform_clipplane_values(gl_clip_plane *clip_planes);
- virtual void setup_vector_uniform_values(const gl_constant_value *values,
- unsigned n);
+ virtual void setup_vec4_uniform_value(unsigned param_offset,
+ const gl_constant_value *values,
+ unsigned n);
void setup_uniform_values(ir_variable *ir);
void setup_builtin_uniform_values(ir_variable *ir);
int setup_uniforms(int payload_reg);
@@ -409,7 +410,6 @@ public:
void visit_atomic_counter_intrinsic(ir_call *ir);
- int type_size(const struct glsl_type *type);
bool is_high_sampler(src_reg sampler);
virtual void emit_nir_code();
@@ -447,7 +447,6 @@ public:
dst_reg *nir_locals;
dst_reg *nir_ssa_values;
src_reg *nir_inputs;
- unsigned *nir_uniform_driver_location;
dst_reg *nir_system_values;
protected:
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_gs_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_gs_nir.cpp
index d85fb6f31ec..8a8dd571e74 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_gs_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_gs_nir.cpp
@@ -44,7 +44,7 @@ vec4_gs_visitor::nir_setup_inputs(nir_shader *shader)
*/
assert(var->type->length > 0);
int length = var->type->length;
- int size = type_size(var->type) / length;
+ int size = type_size_vec4(var->type) / length;
for (int i = 0; i < length; i++) {
int location = var->data.location + i * BRW_VARYING_SLOT_COUNT;
for (int j = 0; j < size; j++) {
@@ -55,7 +55,7 @@ vec4_gs_visitor::nir_setup_inputs(nir_shader *shader)
}
}
} else {
- int size = type_size(var->type);
+ int size = type_size_vec4(var->type);
for (int i = 0; i < size; i++) {
src_reg src = src_reg(ATTR, var->data.location + i, var->type);
src = retype(src, brw_type_for_base_type(var->type));
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
index fd3d556bfb6..d5a24d823b5 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
@@ -119,7 +119,7 @@ vec4_visitor::nir_setup_inputs(nir_shader *shader)
foreach_list_typed(nir_variable, var, node, &shader->inputs) {
int offset = var->data.driver_location;
- unsigned size = type_size(var->type);
+ unsigned size = type_size_vec4(var->type);
for (unsigned i = 0; i < size; i++) {
src_reg src = src_reg(ATTR, var->data.location + i, var->type);
nir_inputs[offset + i] = src;
@@ -132,20 +132,17 @@ vec4_visitor::nir_setup_uniforms(nir_shader *shader)
{
uniforms = 0;
- nir_uniform_driver_location =
- rzalloc_array(mem_ctx, unsigned, this->uniform_array_size);
-
if (shader_prog) {
foreach_list_typed(nir_variable, var, node, &shader->uniforms) {
/* UBO's, atomics and samplers don't take up space in the
uniform file */
if (var->interface_type != NULL || var->type->contains_atomic() ||
- type_size(var->type) == 0) {
+ type_size_vec4(var->type) == 0) {
continue;
}
assert(uniforms < uniform_array_size);
- this->uniform_size[uniforms] = type_size(var->type);
+ this->uniform_size[uniforms] = type_size_vec4(var->type);
if (strncmp(var->name, "gl_", 3) == 0)
nir_setup_builtin_uniform(var);
@@ -161,7 +158,7 @@ vec4_visitor::nir_setup_uniforms(nir_shader *shader)
strcmp(var->name, "parameters") == 0);
assert(uniforms < uniform_array_size);
- this->uniform_size[uniforms] = type_size(var->type);
+ this->uniform_size[uniforms] = type_size_vec4(var->type);
struct gl_program_parameter_list *plist = prog->Parameters;
for (unsigned p = 0; p < plist->NumParameters; p++) {
@@ -182,7 +179,6 @@ vec4_visitor::nir_setup_uniforms(nir_shader *shader)
stage_prog_data->param[uniforms * 4 + i] = &zero;
}
- nir_uniform_driver_location[uniforms] = var->data.driver_location;
uniforms++;
}
}
@@ -230,7 +226,6 @@ vec4_visitor::nir_setup_uniform(nir_variable *var)
stage_prog_data->param[uniforms * 4 + i] = &zero;
}
- nir_uniform_driver_location[uniforms] = var->data.driver_location;
uniforms++;
}
}
@@ -263,7 +258,6 @@ vec4_visitor::nir_setup_builtin_uniform(nir_variable *var)
(var->type->is_scalar() || var->type->is_vector() ||
var->type->is_matrix() ? var->type->vector_elements : 4);
- nir_uniform_driver_location[uniforms] = var->data.driver_location;
uniforms++;
}
}
@@ -458,13 +452,28 @@ vec4_visitor::nir_emit_load_const(nir_load_const_instr *instr)
dst_reg reg = dst_reg(GRF, alloc.allocate(1));
reg.type = BRW_REGISTER_TYPE_F;
+ unsigned remaining = brw_writemask_for_size(instr->def.num_components);
+
/* @FIXME: consider emitting vector operations to save some MOVs in
* cases where the components are representable in 8 bits.
- * By now, we emit a MOV for each component.
+ * For now, we emit a MOV for each distinct value.
*/
- for (unsigned i = 0; i < instr->def.num_components; ++i) {
- reg.writemask = 1 << i;
+ for (unsigned i = 0; i < instr->def.num_components; i++) {
+ unsigned writemask = 1 << i;
+
+ if ((remaining & writemask) == 0)
+ continue;
+
+ for (unsigned j = i; j < instr->def.num_components; j++) {
+ if (instr->value.u[i] == instr->value.u[j]) {
+ writemask |= 1 << j;
+ }
+ }
+
+ reg.writemask = writemask;
emit(MOV(reg, src_reg(instr->value.f[i])));
+
+ remaining &= ~writemask;
}
/* Set final writemask */
@@ -555,24 +564,14 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
has_indirect = true;
/* fallthrough */
case nir_intrinsic_load_uniform: {
- int uniform = instr->const_index[0];
-
dest = get_nir_dest(instr->dest);
- if (has_indirect) {
- /* Split addressing into uniform and offset */
- int offset = uniform - nir_uniform_driver_location[uniform];
- assert(offset >= 0);
+ src = src_reg(dst_reg(UNIFORM, instr->const_index[0]));
+ src.reg_offset = instr->const_index[1];
- uniform -= offset;
- assert(uniform >= 0);
-
- src = src_reg(dst_reg(UNIFORM, uniform));
- src.reg_offset = offset;
+ if (has_indirect) {
src_reg tmp = get_nir_src(instr->src[0], BRW_REGISTER_TYPE_D, 1);
src.reladdr = new(mem_ctx) src_reg(tmp);
- } else {
- src = src_reg(dst_reg(UNIFORM, uniform));
}
emit(MOV(dest, src));
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_reg_allocate.cpp b/src/mesa/drivers/dri/i965/brw_vec4_reg_allocate.cpp
index 617c9889cad..62ed7084883 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_reg_allocate.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_reg_allocate.cpp
@@ -115,7 +115,7 @@ brw_vec4_alloc_reg_set(struct brw_compiler *compiler)
ralloc_free(compiler->vec4_reg_set.ra_reg_to_grf);
compiler->vec4_reg_set.ra_reg_to_grf = ralloc_array(compiler, uint8_t, ra_reg_count);
ralloc_free(compiler->vec4_reg_set.regs);
- compiler->vec4_reg_set.regs = ra_alloc_reg_set(compiler, ra_reg_count);
+ compiler->vec4_reg_set.regs = ra_alloc_reg_set(compiler, ra_reg_count, false);
if (compiler->devinfo->gen >= 6)
ra_set_allocate_round_robin(compiler->vec4_reg_set.regs);
ralloc_free(compiler->vec4_reg_set.classes);
@@ -140,7 +140,7 @@ brw_vec4_alloc_reg_set(struct brw_compiler *compiler)
for (int base_reg = j;
base_reg < j + class_sizes[i];
base_reg++) {
- ra_add_transitive_reg_conflict(compiler->vec4_reg_set.regs, base_reg, reg);
+ ra_add_reg_conflict(compiler->vec4_reg_set.regs, base_reg, reg);
}
reg++;
@@ -158,6 +158,9 @@ brw_vec4_alloc_reg_set(struct brw_compiler *compiler)
}
assert(reg == ra_reg_count);
+ for (int reg = 0; reg < base_reg_count; reg++)
+ ra_make_reg_conflicts_transitive(compiler->vec4_reg_set.regs, reg);
+
ra_set_finalize(compiler->vec4_reg_set.regs, q_values);
for (int i = 0; i < MAX_VGRF_SIZE; i++)
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 20b628e9192..499f6288aee 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -597,8 +597,8 @@ vec4_visitor::visit_instructions(const exec_list *list)
* This method is useful to calculate how much register space is needed to
* store a particular type.
*/
-int
-vec4_visitor::type_size(const struct glsl_type *type)
+extern "C" int
+type_size_vec4(const struct glsl_type *type)
{
unsigned int i;
int size;
@@ -620,11 +620,11 @@ vec4_visitor::type_size(const struct glsl_type *type)
}
case GLSL_TYPE_ARRAY:
assert(type->length > 0);
- return type_size(type->fields.array) * type->length;
+ return type_size_vec4(type->fields.array) * type->length;
case GLSL_TYPE_STRUCT:
size = 0;
for (i = 0; i < type->length; i++) {
- size += type_size(type->fields.structure[i].type);
+ size += type_size_vec4(type->fields.structure[i].type);
}
return size;
case GLSL_TYPE_SUBROUTINE:
@@ -655,7 +655,7 @@ src_reg::src_reg(class vec4_visitor *v, const struct glsl_type *type)
init();
this->file = GRF;
- this->reg = v->alloc.allocate(v->type_size(type));
+ this->reg = v->alloc.allocate(type_size_vec4(type));
if (type->is_array() || type->is_record()) {
this->swizzle = BRW_SWIZZLE_NOOP;
@@ -673,7 +673,7 @@ src_reg::src_reg(class vec4_visitor *v, const struct glsl_type *type, int size)
init();
this->file = GRF;
- this->reg = v->alloc.allocate(v->type_size(type) * size);
+ this->reg = v->alloc.allocate(type_size_vec4(type) * size);
this->swizzle = BRW_SWIZZLE_NOOP;
@@ -685,7 +685,7 @@ dst_reg::dst_reg(class vec4_visitor *v, const struct glsl_type *type)
init();
this->file = GRF;
- this->reg = v->alloc.allocate(v->type_size(type));
+ this->reg = v->alloc.allocate(type_size_vec4(type));
if (type->is_array() || type->is_record()) {
this->writemask = WRITEMASK_XYZW;
@@ -697,18 +697,21 @@ dst_reg::dst_reg(class vec4_visitor *v, const struct glsl_type *type)
}
void
-vec4_visitor::setup_vector_uniform_values(const gl_constant_value *values,
- unsigned n)
+vec4_visitor::setup_vec4_uniform_value(unsigned param_offset,
+ const gl_constant_value *values,
+ unsigned n)
{
static const gl_constant_value zero = { 0 };
+ assert(param_offset % 4 == 0);
+
for (unsigned i = 0; i < n; ++i)
- stage_prog_data->param[4 * uniforms + i] = &values[i];
+ stage_prog_data->param[param_offset + i] = &values[i];
for (unsigned i = n; i < 4; ++i)
- stage_prog_data->param[4 * uniforms + i] = &zero;
+ stage_prog_data->param[param_offset + i] = &zero;
- uniform_vector_size[uniforms++] = n;
+ uniform_vector_size[param_offset / 4] = n;
}
/* Our support for uniforms is piggy-backed on the struct
@@ -744,9 +747,12 @@ vec4_visitor::setup_uniform_values(ir_variable *ir)
storage->type->matrix_columns);
const unsigned vector_size = storage->type->vector_elements;
- for (unsigned s = 0; s < vector_count; s++)
- setup_vector_uniform_values(&storage->storage[s * vector_size],
- vector_size);
+ for (unsigned s = 0; s < vector_count; s++) {
+ setup_vec4_uniform_value(uniforms * 4,
+ &storage->storage[s * vector_size],
+ vector_size);
+ uniforms++;
+ }
}
}
@@ -1070,7 +1076,7 @@ vec4_visitor::visit(ir_variable *ir)
assert(ir->data.location != -1);
reg = new(mem_ctx) dst_reg(this, ir->type);
- for (int i = 0; i < type_size(ir->type); i++) {
+ for (int i = 0; i < type_size_vec4(ir->type); i++) {
output_reg[ir->data.location + i] = *reg;
output_reg[ir->data.location + i].reg_offset = i;
output_reg_annotation[ir->data.location + i] = ir->name;
@@ -1092,14 +1098,14 @@ vec4_visitor::visit(ir_variable *ir)
* Some uniforms, such as samplers and atomic counters, have no actual
* storage, so we should ignore them.
*/
- if (ir->is_in_buffer_block() || type_size(ir->type) == 0)
+ if (ir->is_in_buffer_block() || type_size_vec4(ir->type) == 0)
return;
/* Track how big the whole uniform variable is, in case we need to put a
* copy of its data into pull constants for array access.
*/
assert(this->uniforms < uniform_array_size);
- this->uniform_size[this->uniforms] = type_size(ir->type);
+ this->uniform_size[this->uniforms] = type_size_vec4(ir->type);
if (!strncmp(ir->name, "gl_", 3)) {
setup_builtin_uniform_values(ir);
@@ -2052,7 +2058,7 @@ vec4_visitor::compute_array_stride(ir_dereference_array *ir)
/* Under normal circumstances array elements are stored consecutively, so
* the stride is equal to the size of the array element.
*/
- return type_size(ir->type);
+ return type_size_vec4(ir->type);
}
@@ -2121,7 +2127,7 @@ vec4_visitor::visit(ir_dereference_record *ir)
for (i = 0; i < struct_type->length; i++) {
if (strcmp(struct_type->fields.structure[i].name, ir->field) == 0)
break;
- offset += type_size(struct_type->fields.structure[i].type);
+ offset += type_size_vec4(struct_type->fields.structure[i].type);
}
/* If the type is smaller than a vec4, replicate the last channel out. */
@@ -2330,7 +2336,7 @@ vec4_visitor::visit(ir_assignment *ir)
emit_bool_to_cond_code(ir->condition, &predicate);
}
- for (i = 0; i < type_size(ir->lhs->type); i++) {
+ for (i = 0; i < type_size_vec4(ir->lhs->type); i++) {
vec4_instruction *inst = emit(MOV(dst, src));
inst->predicate = predicate;
diff --git a/src/mesa/drivers/dri/i965/brw_vs_surface_state.c b/src/mesa/drivers/dri/i965/brw_vs_surface_state.c
index 72e37d4b467..fd7e56e50d5 100644
--- a/src/mesa/drivers/dri/i965/brw_vs_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_vs_surface_state.c
@@ -56,7 +56,7 @@ brw_upload_pull_constants(struct brw_context *brw,
const struct brw_stage_prog_data *prog_data,
bool dword_pitch)
{
- int i;
+ unsigned i;
uint32_t surf_index = prog_data->binding_table.pull_constants_start;
if (!prog_data->nr_pull_params) {
diff --git a/src/mesa/drivers/dri/i965/brw_wm_state.c b/src/mesa/drivers/dri/i965/brw_wm_state.c
index 0cd439046b3..cd0b56ba60c 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_state.c
@@ -47,7 +47,7 @@ brw_color_buffer_write_enabled(struct brw_context *brw)
struct gl_context *ctx = &brw->ctx;
/* BRW_NEW_FRAGMENT_PROGRAM */
const struct gl_fragment_program *fp = brw->fragment_program;
- int i;
+ unsigned i;
/* _NEW_BUFFERS */
for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index f13a97ce2b0..8213f4ea2fb 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -898,7 +898,7 @@ brw_upload_ubo_surfaces(struct brw_context *brw,
uint32_t *surf_offsets =
&stage_state->surf_offset[prog_data->binding_table.ubo_start];
- for (int i = 0; i < shader->NumUniformBlocks; i++) {
+ for (unsigned i = 0; i < shader->NumUniformBlocks; i++) {
struct gl_uniform_buffer_binding *binding;
struct intel_buffer_object *intel_bo;
@@ -958,7 +958,7 @@ brw_upload_abo_surfaces(struct brw_context *brw,
uint32_t *surf_offsets =
&stage_state->surf_offset[prog_data->binding_table.abo_start];
- for (int i = 0; i < prog->NumAtomicBuffers; i++) {
+ for (unsigned i = 0; i < prog->NumAtomicBuffers; i++) {
struct gl_atomic_buffer_binding *binding =
&ctx->AtomicBufferBindings[prog->AtomicBuffers[i].Binding];
struct intel_buffer_object *intel_bo =
@@ -1117,7 +1117,7 @@ update_texture_image_param(struct brw_context *brw,
minify(mt->logical_depth0, u->Level) :
mt->logical_depth0);
- intel_miptree_get_image_offset(mt, u->Level, u->Layer,
+ intel_miptree_get_image_offset(mt, u->Level, u->_Layer,
&param->offset[0],
&param->offset[1]);
@@ -1202,7 +1202,7 @@ update_image_surface(struct brw_context *brw,
access != GL_READ_ONLY);
} else {
- const unsigned min_layer = obj->MinLayer + u->Layer;
+ const unsigned min_layer = obj->MinLayer + u->_Layer;
const unsigned min_level = obj->MinLevel + u->Level;
const unsigned num_layers = (!u->Layered ? 1 :
obj->Target == GL_TEXTURE_CUBE_MAP ? 6 :
diff --git a/src/mesa/drivers/dri/i965/gen6_vs_state.c b/src/mesa/drivers/dri/i965/gen6_vs_state.c
index 35d10ef8779..6653a6d759b 100644
--- a/src/mesa/drivers/dri/i965/gen6_vs_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_vs_state.c
@@ -68,7 +68,7 @@ gen6_upload_push_constants(struct brw_context *brw,
_mesa_load_state_parameters(ctx, prog->Parameters);
gl_constant_value *param;
- int i;
+ unsigned i;
param = brw_state_batch(brw, type,
prog_data->nr_params * sizeof(gl_constant_value),
diff --git a/src/mesa/drivers/dri/i965/gen7_sol_state.c b/src/mesa/drivers/dri/i965/gen7_sol_state.c
index 41573a80a52..8cd2fc4b48a 100644
--- a/src/mesa/drivers/dri/i965/gen7_sol_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_sol_state.c
@@ -116,7 +116,7 @@ gen7_upload_3dstate_so_decl_list(struct brw_context *brw,
/* Construct the list of SO_DECLs to be emitted. The formatting of the
* command is feels strange -- each dword pair contains a SO_DECL per stream.
*/
- for (int i = 0; i < linked_xfb_info->NumOutputs; i++) {
+ for (unsigned i = 0; i < linked_xfb_info->NumOutputs; i++) {
int buffer = linked_xfb_info->Outputs[i].OutputBuffer;
uint16_t decl = 0;
int varying = linked_xfb_info->Outputs[i].OutputRegister;
diff --git a/src/mesa/drivers/dri/i965/gen8_draw_upload.c b/src/mesa/drivers/dri/i965/gen8_draw_upload.c
index 1af90ecc6a4..1b48643e577 100644
--- a/src/mesa/drivers/dri/i965/gen8_draw_upload.c
+++ b/src/mesa/drivers/dri/i965/gen8_draw_upload.c
@@ -40,16 +40,25 @@ gen8_emit_vertices(struct brw_context *brw)
{
struct gl_context *ctx = &brw->ctx;
uint32_t mocs_wb = brw->gen >= 9 ? SKL_MOCS_WB : BDW_MOCS_WB;
+ bool uses_edge_flag;
brw_prepare_vertices(brw);
brw_prepare_shader_draw_parameters(brw);
+ uses_edge_flag = (ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL);
+
if (brw->vs.prog_data->uses_vertexid || brw->vs.prog_data->uses_instanceid) {
unsigned vue = brw->vb.nr_enabled;
- WARN_ONCE(brw->vs.prog_data->inputs_read & VERT_BIT_EDGEFLAG,
- "Using VID/IID with edgeflags, need to reorder the "
- "vertex attributes");
+ /* The element for the edge flags must always be last, so we have to
+ * insert the SGVS before it in that case.
+ */
+ if (uses_edge_flag) {
+ assert(vue > 0);
+ vue--;
+ }
+
WARN_ONCE(vue >= 33,
"Trying to insert VID/IID past 33rd vertex element, "
"need to reorder the vertex attrbutes.");
@@ -74,7 +83,7 @@ gen8_emit_vertices(struct brw_context *brw)
BEGIN_BATCH(3);
OUT_BATCH(_3DSTATE_VF_INSTANCING << 16 | (3 - 2));
- OUT_BATCH(brw->vb.nr_buffers | GEN8_VF_INSTANCING_ENABLE);
+ OUT_BATCH(vue | GEN8_VF_INSTANCING_ENABLE);
OUT_BATCH(0);
ADVANCE_BATCH();
} else {
@@ -138,7 +147,18 @@ gen8_emit_vertices(struct brw_context *brw)
ADVANCE_BATCH();
}
- unsigned nr_elements = brw->vb.nr_enabled + brw->vs.prog_data->uses_vertexid;
+ /* Normally we don't need an element for the SGVS attribute because the
+ * 3DSTATE_VF_SGVS instruction lets you store the generated attribute in an
+ * element that is past the list in 3DSTATE_VERTEX_ELEMENTS. However if the
+ * vertex ID is used then it needs an element for the base vertex buffer.
+ * Additionally if there is an edge flag element then the SGVS can't be
+ * inserted past that so we need a dummy element to ensure that the edge
+ * flag is the last one.
+ */
+ bool needs_sgvs_element = (brw->vs.prog_data->uses_vertexid ||
+ (brw->vs.prog_data->uses_instanceid &&
+ uses_edge_flag));
+ unsigned nr_elements = brw->vb.nr_enabled + needs_sgvs_element;
/* The hardware allows one more VERTEX_ELEMENTS than VERTEX_BUFFERS,
* presumably for VertexID/InstanceID.
@@ -192,6 +212,24 @@ gen8_emit_vertices(struct brw_context *brw)
(comp3 << BRW_VE1_COMPONENT_3_SHIFT));
}
+ if (needs_sgvs_element) {
+ if (brw->vs.prog_data->uses_vertexid) {
+ OUT_BATCH(GEN6_VE0_VALID |
+ brw->vb.nr_buffers << GEN6_VE0_INDEX_SHIFT |
+ BRW_SURFACEFORMAT_R32_UINT << BRW_VE0_FORMAT_SHIFT);
+ OUT_BATCH((BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_0_SHIFT) |
+ (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) |
+ (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
+ (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT));
+ } else {
+ OUT_BATCH(GEN6_VE0_VALID);
+ OUT_BATCH((BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_0_SHIFT) |
+ (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) |
+ (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
+ (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT));
+ }
+ }
+
if (gen6_edgeflag_input) {
uint32_t format =
brw_get_vertex_surface_type(brw, gen6_edgeflag_input->glarray);
@@ -206,25 +244,26 @@ gen8_emit_vertices(struct brw_context *brw)
(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT));
}
-
- if (brw->vs.prog_data->uses_vertexid) {
- OUT_BATCH(GEN6_VE0_VALID |
- brw->vb.nr_buffers << GEN6_VE0_INDEX_SHIFT |
- BRW_SURFACEFORMAT_R32_UINT << BRW_VE0_FORMAT_SHIFT);
- OUT_BATCH((BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_0_SHIFT) |
- (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) |
- (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) |
- (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT));
- }
ADVANCE_BATCH();
- for (unsigned i = 0; i < brw->vb.nr_enabled; i++) {
+ for (unsigned i = 0, j = 0; i < brw->vb.nr_enabled; i++) {
const struct brw_vertex_element *input = brw->vb.enabled[i];
const struct brw_vertex_buffer *buffer = &brw->vb.buffers[input->buffer];
+ unsigned element_index;
+
+ /* The edge flag element is reordered to be the last one in the code
+ * above so we need to compensate for that in the element indices used
+ * below.
+ */
+ if (input == gen6_edgeflag_input)
+ element_index = nr_elements - 1;
+ else
+ element_index = j++;
BEGIN_BATCH(3);
OUT_BATCH(_3DSTATE_VF_INSTANCING << 16 | (3 - 2));
- OUT_BATCH(i | (buffer->step_rate ? GEN8_VF_INSTANCING_ENABLE : 0));
+ OUT_BATCH(element_index |
+ (buffer->step_rate ? GEN8_VF_INSTANCING_ENABLE : 0));
OUT_BATCH(buffer->step_rate);
ADVANCE_BATCH();
}
diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c
index 3bc28a12026..1a246d3ea3a 100644
--- a/src/mesa/drivers/dri/i965/intel_extensions.c
+++ b/src/mesa/drivers/dri/i965/intel_extensions.c
@@ -331,6 +331,7 @@ intelInitExtensions(struct gl_context *ctx)
ctx->Extensions.ARB_gpu_shader5 = true;
ctx->Extensions.ARB_shader_atomic_counters = true;
ctx->Extensions.ARB_shader_image_load_store = true;
+ ctx->Extensions.ARB_shader_image_size = true;
ctx->Extensions.ARB_texture_compression_bptc = true;
ctx->Extensions.ARB_texture_view = true;
diff --git a/src/mesa/drivers/dri/i965/intel_fbo.c b/src/mesa/drivers/dri/i965/intel_fbo.c
index 72648b01e33..64d57e8bc89 100644
--- a/src/mesa/drivers/dri/i965/intel_fbo.c
+++ b/src/mesa/drivers/dri/i965/intel_fbo.c
@@ -662,7 +662,7 @@ intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
struct intel_renderbuffer *stencilRb =
intel_get_renderbuffer(fb, BUFFER_STENCIL);
struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL;
- int i;
+ unsigned i;
DBG("%s() on fb %p (%s)\n", __func__,
fb, (fb == ctx->DrawBuffer ? "drawbuffer" :
@@ -797,7 +797,7 @@ intel_blit_framebuffer_with_blitter(struct gl_context *ctx,
intel_prepare_render(brw);
if (mask & GL_COLOR_BUFFER_BIT) {
- GLint i;
+ unsigned i;
struct gl_renderbuffer *src_rb = readFb->_ColorReadBuffer;
struct intel_renderbuffer *src_irb = intel_renderbuffer(src_rb);
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index a164c6985dc..5911b444454 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -122,7 +122,7 @@ aub_dump_bmp(struct gl_context *ctx)
{
struct gl_framebuffer *fb = ctx->DrawBuffer;
- for (int i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ for (unsigned i = 0; i < fb->_NumColorDrawBuffers; i++) {
struct intel_renderbuffer *irb =
intel_renderbuffer(fb->_ColorDrawBuffers[i]);
@@ -1219,7 +1219,7 @@ intel_screen_make_configs(__DRIscreen *dri_screen)
__DRIconfig **configs = NULL;
/* Generate singlesample configs without accumulation buffer. */
- for (int i = 0; i < ARRAY_SIZE(formats); i++) {
+ for (unsigned i = 0; i < ARRAY_SIZE(formats); i++) {
__DRIconfig **new_configs;
int num_depth_stencil_bits = 2;
@@ -1256,7 +1256,7 @@ intel_screen_make_configs(__DRIscreen *dri_screen)
/* Generate the minimum possible set of configs that include an
* accumulation buffer.
*/
- for (int i = 0; i < ARRAY_SIZE(formats); i++) {
+ for (unsigned i = 0; i < ARRAY_SIZE(formats); i++) {
__DRIconfig **new_configs;
if (formats[i] == MESA_FORMAT_B5G6R5_UNORM) {
@@ -1288,7 +1288,7 @@ intel_screen_make_configs(__DRIscreen *dri_screen)
* supported. Singlebuffer configs are not supported because no one wants
* them.
*/
- for (int i = 0; i < ARRAY_SIZE(formats); i++) {
+ for (unsigned i = 0; i < ARRAY_SIZE(formats); i++) {
if (devinfo->gen < 6)
break;
diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
index 1cdea937f91..e17b41ce55c 100644
--- a/src/mesa/main/bufferobj.c
+++ b/src/mesa/main/bufferobj.c
@@ -866,8 +866,8 @@ _mesa_init_buffer_objects( struct gl_context *ctx )
_mesa_reference_buffer_object(ctx,
&ctx->AtomicBufferBindings[i].BufferObject,
ctx->Shared->NullBufferObj);
- ctx->AtomicBufferBindings[i].Offset = -1;
- ctx->AtomicBufferBindings[i].Size = -1;
+ ctx->AtomicBufferBindings[i].Offset = 0;
+ ctx->AtomicBufferBindings[i].Size = 0;
}
}
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 888c461d1c2..be542dd6797 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -402,10 +402,6 @@ one_time_init( struct gl_context *ctx )
PACKAGE_VERSION, __DATE__, __TIME__);
}
#endif
-
-#ifdef DEBUG
- _mesa_test_formats();
-#endif
}
/* per-API one-time init */
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index d934d19c3e7..4a3c231e36f 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -50,6 +50,7 @@ enum {
ES1 = 1 << API_OPENGLES,
ES2 = 1 << API_OPENGLES2,
ES3 = 1 << (API_OPENGL_LAST + 1),
+ ES31 = 1 << (API_OPENGL_LAST + 2),
};
/**
@@ -152,6 +153,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_shader_atomic_counters", o(ARB_shader_atomic_counters), GL, 2011 },
{ "GL_ARB_shader_bit_encoding", o(ARB_shader_bit_encoding), GL, 2010 },
{ "GL_ARB_shader_image_load_store", o(ARB_shader_image_load_store), GL, 2011 },
+ { "GL_ARB_shader_image_size", o(ARB_shader_image_size), GL, 2012 },
{ "GL_ARB_shader_objects", o(dummy_true), GL, 2002 },
{ "GL_ARB_shader_precision", o(ARB_shader_precision), GL, 2010 },
{ "GL_ARB_shader_stencil_export", o(ARB_shader_stencil_export), GL, 2009 },
@@ -773,6 +775,8 @@ _mesa_make_extension_string(struct gl_context *ctx)
unsigned api_set = (1 << ctx->API);
if (_mesa_is_gles3(ctx))
api_set |= ES3;
+ if (_mesa_is_gles31(ctx))
+ api_set |= ES31;
/* Check if the MESA_EXTENSION_MAX_YEAR env var is set */
{
@@ -854,6 +858,8 @@ _mesa_get_extension_count(struct gl_context *ctx)
unsigned api_set = (1 << ctx->API);
if (_mesa_is_gles3(ctx))
api_set |= ES3;
+ if (_mesa_is_gles31(ctx))
+ api_set |= ES31;
/* only count once */
if (ctx->Extensions.Count != 0)
@@ -880,6 +886,8 @@ _mesa_get_enabled_extension(struct gl_context *ctx, GLuint index)
unsigned api_set = (1 << ctx->API);
if (_mesa_is_gles3(ctx))
api_set |= ES3;
+ if (_mesa_is_gles31(ctx))
+ api_set |= ES31;
base = (GLboolean*) &ctx->Extensions;
n = 0;
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c
index 841834030df..07db1950bbb 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -2033,6 +2033,16 @@ renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
*/
sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER,
internalFormat, samples);
+
+ /* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16:
+ *
+ * "If a negative number is provided where an argument of type sizei or
+ * sizeiptr is specified, the error INVALID VALUE is generated."
+ */
+ if (samples < 0) {
+ sample_count_error = GL_INVALID_VALUE;
+ }
+
if (sample_count_error != GL_NO_ERROR) {
_mesa_error(ctx, sample_count_error, "%s(samples)", func);
return;
diff --git a/src/mesa/main/format_info.py b/src/mesa/main/format_info.py
index 3bae57e54ed..839d4073c61 100644
--- a/src/mesa/main/format_info.py
+++ b/src/mesa/main/format_info.py
@@ -98,14 +98,6 @@ def get_gl_data_type(fmat):
else:
assert False
-def get_mesa_layout(fmat):
- if fmat.layout == 'array':
- return 'MESA_FORMAT_LAYOUT_ARRAY'
- elif fmat.layout == 'packed':
- return 'MESA_FORMAT_LAYOUT_PACKED'
- else:
- return 'MESA_FORMAT_LAYOUT_OTHER'
-
def get_channel_bits(fmat, chan_name):
if fmat.is_compressed():
# These values are pretty-much bogus, but OpenGL requires that we
@@ -179,7 +171,7 @@ for fmat in formats:
print ' {'
print ' {0},'.format(fmat.name)
print ' "{0}",'.format(fmat.name)
- print ' {0},'.format(get_mesa_layout(fmat))
+ print ' {0},'.format('MESA_FORMAT_LAYOUT_' + fmat.layout.upper())
print ' {0},'.format(get_gl_base_format(fmat))
print ' {0},'.format(get_gl_data_type(fmat))
@@ -188,6 +180,8 @@ for fmat in formats:
bits = [ get_channel_bits(fmat, name) for name in ['l', 'i', 'z', 's']]
print ' {0},'.format(', '.join(map(str, bits)))
+ print ' {0:d},'.format(fmat.colorspace == 'srgb')
+
print ' {0}, {1}, {2},'.format(fmat.block_width, fmat.block_height,
int(fmat.block_size() / 8))
diff --git a/src/mesa/main/format_utils.c b/src/mesa/main/format_utils.c
index 810bb163400..5fdabd5b97f 100644
--- a/src/mesa/main/format_utils.c
+++ b/src/mesa/main/format_utils.c
@@ -602,7 +602,7 @@ _mesa_format_to_array(mesa_format format, GLenum *type, int *num_components,
*normalized = !_mesa_is_format_integer(format);
- _mesa_format_to_type_and_comps(format, type, &format_components);
+ _mesa_uncompressed_format_to_type_and_comps(format, type, &format_components);
switch (_mesa_get_format_layout(format)) {
case MESA_FORMAT_LAYOUT_ARRAY:
diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c
index d7b2bae59e7..8dd07d88f40 100644
--- a/src/mesa/main/formats.c
+++ b/src/mesa/main/formats.c
@@ -65,6 +65,8 @@ struct gl_format_info
GLubyte DepthBits;
GLubyte StencilBits;
+ bool IsSRGBFormat;
+
/**
* To describe compressed formats. If not compressed, Width=Height=1.
*/
@@ -81,6 +83,7 @@ static const struct gl_format_info *
_mesa_get_format_info(mesa_format format)
{
const struct gl_format_info *info = &format_info[format];
+ STATIC_ASSERT(ARRAY_SIZE(format_info) == MESA_FORMAT_COUNT);
assert(info->Name == format);
return info;
}
@@ -188,6 +191,12 @@ _mesa_get_format_max_bits(mesa_format format)
* The return value will be one of:
* MESA_FORMAT_LAYOUT_ARRAY
* MESA_FORMAT_LAYOUT_PACKED
+ * MESA_FORMAT_LAYOUT_S3TC
+ * MESA_FORMAT_LAYOUT_RGTC
+ * MESA_FORMAT_LAYOUT_FXT1
+ * MESA_FORMAT_LAYOUT_ETC1
+ * MESA_FORMAT_LAYOUT_ETC2
+ * MESA_FORMAT_LAYOUT_BPTC
* MESA_FORMAT_LAYOUT_OTHER
*/
extern enum mesa_format_layout
@@ -562,30 +571,8 @@ _mesa_is_format_color_format(mesa_format format)
GLenum
_mesa_get_format_color_encoding(mesa_format format)
{
- /* XXX this info should be encoded in gl_format_info */
- switch (format) {
- case MESA_FORMAT_BGR_SRGB8:
- case MESA_FORMAT_A8B8G8R8_SRGB:
- case MESA_FORMAT_B8G8R8A8_SRGB:
- case MESA_FORMAT_A8R8G8B8_SRGB:
- case MESA_FORMAT_R8G8B8A8_SRGB:
- case MESA_FORMAT_L_SRGB8:
- case MESA_FORMAT_L8A8_SRGB:
- case MESA_FORMAT_A8L8_SRGB:
- case MESA_FORMAT_SRGB_DXT1:
- case MESA_FORMAT_SRGBA_DXT1:
- case MESA_FORMAT_SRGBA_DXT3:
- case MESA_FORMAT_SRGBA_DXT5:
- case MESA_FORMAT_R8G8B8X8_SRGB:
- case MESA_FORMAT_ETC2_SRGB8:
- case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
- case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
- case MESA_FORMAT_B8G8R8X8_SRGB:
- case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
- return GL_SRGB;
- default:
- return GL_LINEAR;
- }
+ const struct gl_format_info *info = _mesa_get_format_info(format);
+ return info->IsSRGBFormat ? GL_SRGB : GL_LINEAR;
}
@@ -878,124 +865,13 @@ _mesa_format_row_stride(mesa_format format, GLsizei width)
}
-/**
- * Debug/test: check that all formats are handled in the
- * _mesa_format_to_type_and_comps() function. When new pixel formats
- * are added to Mesa, that function needs to be updated.
- * This is a no-op after the first call.
- */
-static void
-check_format_to_type_and_comps(void)
-{
- mesa_format f;
-
- for (f = MESA_FORMAT_NONE + 1; f < MESA_FORMAT_COUNT; f++) {
- GLenum datatype = 0;
- GLuint comps = 0;
- /* This function will emit a problem/warning if the format is
- * not handled.
- */
- _mesa_format_to_type_and_comps(f, &datatype, &comps);
- }
-}
/**
- * Do sanity checking of the format info table.
+ * Return datatype and number of components per texel for the given
+ * uncompressed mesa_format. Only used for mipmap generation code.
*/
void
-_mesa_test_formats(void)
-{
- GLuint i;
-
- STATIC_ASSERT(ARRAY_SIZE(format_info) == MESA_FORMAT_COUNT);
-
- for (i = 0; i < MESA_FORMAT_COUNT; i++) {
- const struct gl_format_info *info = _mesa_get_format_info(i);
- assert(info);
-
- assert(info->Name == i);
-
- if (info->Name == MESA_FORMAT_NONE)
- continue;
-
- if (info->BlockWidth == 1 && info->BlockHeight == 1) {
- if (info->RedBits > 0) {
- GLuint t = info->RedBits + info->GreenBits
- + info->BlueBits + info->AlphaBits;
- assert(t / 8 <= info->BytesPerBlock);
- (void) t;
- }
- }
-
- assert(info->DataType == GL_UNSIGNED_NORMALIZED ||
- info->DataType == GL_SIGNED_NORMALIZED ||
- info->DataType == GL_UNSIGNED_INT ||
- info->DataType == GL_INT ||
- info->DataType == GL_FLOAT ||
- /* Z32_FLOAT_X24S8 has DataType of GL_NONE */
- info->DataType == GL_NONE);
-
- if (info->BaseFormat == GL_RGB) {
- assert(info->RedBits > 0);
- assert(info->GreenBits > 0);
- assert(info->BlueBits > 0);
- assert(info->AlphaBits == 0);
- assert(info->LuminanceBits == 0);
- assert(info->IntensityBits == 0);
- }
- else if (info->BaseFormat == GL_RGBA) {
- assert(info->RedBits > 0);
- assert(info->GreenBits > 0);
- assert(info->BlueBits > 0);
- assert(info->AlphaBits > 0);
- assert(info->LuminanceBits == 0);
- assert(info->IntensityBits == 0);
- }
- else if (info->BaseFormat == GL_RG) {
- assert(info->RedBits > 0);
- assert(info->GreenBits > 0);
- assert(info->BlueBits == 0);
- assert(info->AlphaBits == 0);
- assert(info->LuminanceBits == 0);
- assert(info->IntensityBits == 0);
- }
- else if (info->BaseFormat == GL_RED) {
- assert(info->RedBits > 0);
- assert(info->GreenBits == 0);
- assert(info->BlueBits == 0);
- assert(info->AlphaBits == 0);
- assert(info->LuminanceBits == 0);
- assert(info->IntensityBits == 0);
- }
- else if (info->BaseFormat == GL_LUMINANCE) {
- assert(info->RedBits == 0);
- assert(info->GreenBits == 0);
- assert(info->BlueBits == 0);
- assert(info->AlphaBits == 0);
- assert(info->LuminanceBits > 0);
- assert(info->IntensityBits == 0);
- }
- else if (info->BaseFormat == GL_INTENSITY) {
- assert(info->RedBits == 0);
- assert(info->GreenBits == 0);
- assert(info->BlueBits == 0);
- assert(info->AlphaBits == 0);
- assert(info->LuminanceBits == 0);
- assert(info->IntensityBits > 0);
- }
- }
-
- check_format_to_type_and_comps();
-}
-
-
-
-/**
- * Return datatype and number of components per texel for the given mesa_format.
- * Only used for mipmap generation code.
- */
-void
-_mesa_format_to_type_and_comps(mesa_format format,
+_mesa_uncompressed_format_to_type_and_comps(mesa_format format,
GLenum *datatype, GLuint *comps)
{
switch (format) {
@@ -1229,44 +1105,6 @@ _mesa_format_to_type_and_comps(mesa_format format,
*comps = 2;
return;
- case MESA_FORMAT_RGB_FXT1:
- case MESA_FORMAT_RGBA_FXT1:
- case MESA_FORMAT_RGB_DXT1:
- case MESA_FORMAT_RGBA_DXT1:
- case MESA_FORMAT_RGBA_DXT3:
- case MESA_FORMAT_RGBA_DXT5:
- case MESA_FORMAT_SRGB_DXT1:
- case MESA_FORMAT_SRGBA_DXT1:
- case MESA_FORMAT_SRGBA_DXT3:
- case MESA_FORMAT_SRGBA_DXT5:
- case MESA_FORMAT_R_RGTC1_UNORM:
- case MESA_FORMAT_R_RGTC1_SNORM:
- case MESA_FORMAT_RG_RGTC2_UNORM:
- case MESA_FORMAT_RG_RGTC2_SNORM:
- case MESA_FORMAT_L_LATC1_UNORM:
- case MESA_FORMAT_L_LATC1_SNORM:
- case MESA_FORMAT_LA_LATC2_UNORM:
- case MESA_FORMAT_LA_LATC2_SNORM:
- case MESA_FORMAT_ETC1_RGB8:
- case MESA_FORMAT_ETC2_RGB8:
- case MESA_FORMAT_ETC2_SRGB8:
- case MESA_FORMAT_ETC2_RGBA8_EAC:
- case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
- case MESA_FORMAT_ETC2_R11_EAC:
- case MESA_FORMAT_ETC2_RG11_EAC:
- case MESA_FORMAT_ETC2_SIGNED_R11_EAC:
- case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
- case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
- case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
- case MESA_FORMAT_BPTC_RGBA_UNORM:
- case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
- case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
- case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
- /* XXX generate error instead? */
- *datatype = GL_UNSIGNED_BYTE;
- *comps = 0;
- return;
-
case MESA_FORMAT_RGBA_FLOAT32:
*datatype = GL_FLOAT;
*comps = 4;
@@ -1564,14 +1402,12 @@ _mesa_format_to_type_and_comps(mesa_format format,
case MESA_FORMAT_COUNT:
assert(0);
return;
-
- case MESA_FORMAT_NONE:
- /* For debug builds, warn if any formats are not handled */
-#ifdef DEBUG
default:
-#endif
- _mesa_problem(NULL, "bad format %s in _mesa_format_to_type_and_comps",
+ /* Warn if any formats are not handled */
+ _mesa_problem(NULL, "bad format %s in _mesa_uncompressed_format_to_type_and_comps",
_mesa_get_format_name(format));
+ assert(format == MESA_FORMAT_NONE ||
+ _mesa_is_format_compressed(format));
*datatype = 0;
*comps = 1;
}
@@ -1584,20 +1420,26 @@ _mesa_format_to_type_and_comps(mesa_format format,
* \param format the user-specified image format
* \param type the user-specified image datatype
* \param swapBytes typically the current pixel pack/unpack byteswap state
+ * \param[out] error GL_NO_ERROR if format is an expected input.
+ * GL_INVALID_ENUM if format is an unexpected input.
* \return GL_TRUE if the formats match, GL_FALSE otherwise.
*/
GLboolean
_mesa_format_matches_format_and_type(mesa_format mesa_format,
GLenum format, GLenum type,
- GLboolean swapBytes)
+ GLboolean swapBytes, GLenum *error)
{
const GLboolean littleEndian = _mesa_little_endian();
+ if (error)
+ *error = GL_NO_ERROR;
/* Note: When reading a GL format/type combination, the format lists channel
* assignments from most significant channel in the type to least
* significant. A type with _REV indicates that the assignments are
* swapped, so they are listed from least significant to most significant.
*
+ * Compressed formats will fall through and return GL_FALSE.
+ *
* For sanity, please keep this switch statement ordered the same as the
* enums in formats.h.
*/
@@ -1858,26 +1700,6 @@ _mesa_format_matches_format_and_type(mesa_format mesa_format,
case MESA_FORMAT_S_UINT8:
return format == GL_STENCIL_INDEX && type == GL_UNSIGNED_BYTE;
- case MESA_FORMAT_SRGB_DXT1:
- case MESA_FORMAT_SRGBA_DXT1:
- case MESA_FORMAT_SRGBA_DXT3:
- case MESA_FORMAT_SRGBA_DXT5:
- return GL_FALSE;
-
- case MESA_FORMAT_RGB_FXT1:
- case MESA_FORMAT_RGBA_FXT1:
- case MESA_FORMAT_RGB_DXT1:
- case MESA_FORMAT_RGBA_DXT1:
- case MESA_FORMAT_RGBA_DXT3:
- case MESA_FORMAT_RGBA_DXT5:
- return GL_FALSE;
-
- case MESA_FORMAT_BPTC_RGBA_UNORM:
- case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
- case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
- case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
- return GL_FALSE;
-
case MESA_FORMAT_RGBA_FLOAT32:
return format == GL_RGBA && type == GL_FLOAT && !swapBytes;
case MESA_FORMAT_RGBA_FLOAT16:
@@ -2074,31 +1896,6 @@ _mesa_format_matches_format_and_type(mesa_format mesa_format,
return format == GL_RGBA && type == GL_UNSIGNED_SHORT &&
!swapBytes;
- case MESA_FORMAT_R_RGTC1_UNORM:
- case MESA_FORMAT_R_RGTC1_SNORM:
- case MESA_FORMAT_RG_RGTC2_UNORM:
- case MESA_FORMAT_RG_RGTC2_SNORM:
- return GL_FALSE;
-
- case MESA_FORMAT_L_LATC1_UNORM:
- case MESA_FORMAT_L_LATC1_SNORM:
- case MESA_FORMAT_LA_LATC2_UNORM:
- case MESA_FORMAT_LA_LATC2_SNORM:
- return GL_FALSE;
-
- case MESA_FORMAT_ETC1_RGB8:
- case MESA_FORMAT_ETC2_RGB8:
- case MESA_FORMAT_ETC2_SRGB8:
- case MESA_FORMAT_ETC2_RGBA8_EAC:
- case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
- case MESA_FORMAT_ETC2_R11_EAC:
- case MESA_FORMAT_ETC2_RG11_EAC:
- case MESA_FORMAT_ETC2_SIGNED_R11_EAC:
- case MESA_FORMAT_ETC2_SIGNED_RG11_EAC:
- case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
- case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
- return GL_FALSE;
-
case MESA_FORMAT_A_SNORM8:
return format == GL_ALPHA && type == GL_BYTE;
case MESA_FORMAT_L_SNORM8:
@@ -2181,8 +1978,11 @@ _mesa_format_matches_format_and_type(mesa_format mesa_format,
case MESA_FORMAT_B8G8R8X8_SRGB:
case MESA_FORMAT_X8R8G8B8_SRGB:
return GL_FALSE;
+ default:
+ assert(_mesa_is_format_compressed(format));
+ if (error)
+ *error = GL_INVALID_ENUM;
}
-
return GL_FALSE;
}
diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h
index d938e6ad513..4936fa0d482 100644
--- a/src/mesa/main/formats.h
+++ b/src/mesa/main/formats.h
@@ -64,6 +64,12 @@ extern "C" {
enum mesa_format_layout {
MESA_FORMAT_LAYOUT_ARRAY,
MESA_FORMAT_LAYOUT_PACKED,
+ MESA_FORMAT_LAYOUT_S3TC,
+ MESA_FORMAT_LAYOUT_RGTC,
+ MESA_FORMAT_LAYOUT_FXT1,
+ MESA_FORMAT_LAYOUT_ETC1,
+ MESA_FORMAT_LAYOUT_ETC2,
+ MESA_FORMAT_LAYOUT_BPTC,
MESA_FORMAT_LAYOUT_OTHER,
};
@@ -659,7 +665,7 @@ extern GLint
_mesa_format_row_stride(mesa_format format, GLsizei width);
extern void
-_mesa_format_to_type_and_comps(mesa_format format,
+_mesa_uncompressed_format_to_type_and_comps(mesa_format format,
GLenum *datatype, GLuint *comps);
extern void
@@ -680,7 +686,7 @@ _mesa_format_has_color_component(mesa_format format, int component);
GLboolean
_mesa_format_matches_format_and_type(mesa_format mesa_format,
GLenum format, GLenum type,
- GLboolean swapBytes);
+ GLboolean swapBytes, GLenum *error);
#ifdef __cplusplus
}
diff --git a/src/mesa/main/get_hash_params.py b/src/mesa/main/get_hash_params.py
index 7dc92f10100..517c391955d 100644
--- a/src/mesa/main/get_hash_params.py
+++ b/src/mesa/main/get_hash_params.py
@@ -806,7 +806,7 @@ descriptor=[
[ "MAX_VERTEX_ATTRIB_BINDINGS", "CONTEXT_ENUM(Const.MaxVertexAttribBindings), NO_EXTRA" ],
# GL_ARB_shader_image_load_store
- [ "MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS", "CONTEXT_INT(Const.MaxCombinedImageUnitsAndFragmentOutputs), extra_ARB_shader_image_load_store" ],
+ [ "MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS", "CONTEXT_INT(Const.MaxCombinedShaderOutputResources), extra_ARB_shader_image_load_store" ],
[ "MAX_IMAGE_SAMPLES", "CONTEXT_INT(Const.MaxImageSamples), extra_ARB_shader_image_load_store" ],
[ "MAX_GEOMETRY_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_GEOMETRY].MaxImageUniforms), extra_ARB_shader_image_load_store_and_geometry_shader"],
diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c
index 1e22f930092..2bf5902fba4 100644
--- a/src/mesa/main/mipmap.c
+++ b/src/mesa/main/mipmap.c
@@ -1886,7 +1886,7 @@ generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,
GLenum datatype;
GLuint comps;
- _mesa_format_to_type_and_comps(srcImage->TexFormat, &datatype, &comps);
+ _mesa_uncompressed_format_to_type_and_comps(srcImage->TexFormat, &datatype, &comps);
for (level = texObj->BaseLevel; level < maxLevel; level++) {
/* generate image[level+1] from image[level] */
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 83f3717754d..4883cbc93d5 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -94,7 +94,10 @@ struct vbo_context;
#define PRIM_OUTSIDE_BEGIN_END (PRIM_MAX + 1)
#define PRIM_UNKNOWN (PRIM_MAX + 2)
-
+#define VARYING_SLOT_MAX (VARYING_SLOT_VAR0 + MAX_VARYING)
+#define VARYING_SLOT_PATCH0 (VARYING_SLOT_MAX)
+#define VARYING_SLOT_TESS_MAX (VARYING_SLOT_PATCH0 + MAX_VARYING)
+#define FRAG_RESULT_MAX (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
/**
* Determine if the given gl_varying_slot appears in the fragment shader.
@@ -117,7 +120,6 @@ _mesa_varying_slot_in_fs(gl_varying_slot slot)
}
}
-
/**
* Indexes for all renderbuffers
*/
@@ -3571,7 +3573,7 @@ struct gl_constants
/* GL_ARB_shader_image_load_store */
GLuint MaxImageUnits;
- GLuint MaxCombinedImageUnitsAndFragmentOutputs;
+ GLuint MaxCombinedShaderOutputResources;
GLuint MaxImageSamples;
GLuint MaxCombinedImageUniforms;
@@ -3656,6 +3658,7 @@ struct gl_extensions
GLboolean ARB_shader_atomic_counters;
GLboolean ARB_shader_bit_encoding;
GLboolean ARB_shader_image_load_store;
+ GLboolean ARB_shader_image_size;
GLboolean ARB_shader_precision;
GLboolean ARB_shader_stencil_export;
GLboolean ARB_shader_storage_buffer_object;
@@ -4073,10 +4076,16 @@ struct gl_image_unit
GLboolean _Valid;
/**
+ * Layer of the texture object bound to this unit as specified by the
+ * application.
+ */
+ GLuint Layer;
+
+ /**
* Layer of the texture object bound to this unit, or zero if the
* whole level is bound.
*/
- GLuint Layer;
+ GLuint _Layer;
/**
* Access allowed to this texture image. Either \c GL_READ_ONLY,
diff --git a/src/mesa/main/multisample.c b/src/mesa/main/multisample.c
index 09e6154f7ec..e7783ea5374 100644
--- a/src/mesa/main/multisample.c
+++ b/src/mesa/main/multisample.c
@@ -150,15 +150,6 @@ GLenum
_mesa_check_sample_count(struct gl_context *ctx, GLenum target,
GLenum internalFormat, GLsizei samples)
{
- /* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16:
- *
- * "If a negative number is provided where an argument of type sizei or
- * sizeiptr is specified, the error INVALID VALUE is generated."
- */
- if (samples < 0) {
- return GL_INVALID_VALUE;
- }
-
/* Section 4.4 (Framebuffer objects), page 198 of the OpenGL ES 3.0.0
* specification says:
*
diff --git a/src/mesa/main/readpix.c b/src/mesa/main/readpix.c
index d826ecfc3d5..12779446c6d 100644
--- a/src/mesa/main/readpix.c
+++ b/src/mesa/main/readpix.c
@@ -201,7 +201,7 @@ readpixels_can_use_memcpy(const struct gl_context *ctx, GLenum format, GLenum ty
/* The Mesa format must match the input format and type. */
if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
- packing->SwapBytes)) {
+ packing->SwapBytes, NULL)) {
return GL_FALSE;
}
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index f9a7d130f9c..b227c17548e 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -1995,55 +1995,6 @@ _mesa_use_shader_program(struct gl_context *ctx, GLenum type,
}
-static GLuint
-_mesa_create_shader_program(struct gl_context* ctx, GLboolean separate,
- GLenum type, GLsizei count,
- const GLchar* const *strings)
-{
- const GLuint shader = create_shader(ctx, type);
- GLuint program = 0;
-
- if (shader) {
- _mesa_ShaderSource(shader, count, strings, NULL);
-
- compile_shader(ctx, shader);
-
- program = create_shader_program(ctx);
- if (program) {
- struct gl_shader_program *shProg;
- struct gl_shader *sh;
- GLint compiled = GL_FALSE;
-
- shProg = _mesa_lookup_shader_program(ctx, program);
- sh = _mesa_lookup_shader(ctx, shader);
-
- shProg->SeparateShader = separate;
-
- get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled);
- if (compiled) {
- attach_shader(ctx, program, shader);
- link_program(ctx, program);
- detach_shader(ctx, program, shader);
-
-#if 0
- /* Possibly... */
- if (active-user-defined-varyings-in-linked-program) {
- append-error-to-info-log;
- shProg->LinkStatus = GL_FALSE;
- }
-#endif
- }
- if (sh->InfoLog)
- ralloc_strcat(&shProg->InfoLog, sh->InfoLog);
- }
-
- delete_shader(ctx, shader);
- }
-
- return program;
-}
-
-
/**
* Copy program-specific data generated by linking from the gl_shader_program
* object to a specific gl_program object.
@@ -2111,7 +2062,56 @@ _mesa_CreateShaderProgramv(GLenum type, GLsizei count,
{
GET_CURRENT_CONTEXT(ctx);
- return _mesa_create_shader_program(ctx, GL_TRUE, type, count, strings);
+ const GLuint shader = create_shader(ctx, type);
+ GLuint program = 0;
+
+ /*
+ * According to OpenGL 4.5 and OpenGL ES 3.1 standards, section 7.3:
+ * GL_INVALID_VALUE should be generated if count < 0
+ */
+ if (count < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glCreateShaderProgram (count < 0)");
+ return program;
+ }
+
+ if (shader) {
+ _mesa_ShaderSource(shader, count, strings, NULL);
+
+ compile_shader(ctx, shader);
+
+ program = create_shader_program(ctx);
+ if (program) {
+ struct gl_shader_program *shProg;
+ struct gl_shader *sh;
+ GLint compiled = GL_FALSE;
+
+ shProg = _mesa_lookup_shader_program(ctx, program);
+ sh = _mesa_lookup_shader(ctx, shader);
+
+ shProg->SeparateShader = GL_TRUE;
+
+ get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled);
+ if (compiled) {
+ attach_shader(ctx, program, shader);
+ link_program(ctx, program);
+ detach_shader(ctx, program, shader);
+
+#if 0
+ /* Possibly... */
+ if (active-user-defined-varyings-in-linked-program) {
+ append-error-to-info-log;
+ shProg->LinkStatus = GL_FALSE;
+ }
+#endif
+ }
+ if (sh->InfoLog)
+ ralloc_strcat(&shProg->InfoLog, sh->InfoLog);
+ }
+
+ delete_shader(ctx, shader);
+ }
+
+ return program;
}
diff --git a/src/mesa/main/shaderimage.c b/src/mesa/main/shaderimage.c
index a348cdb0405..c4bba842ca7 100644
--- a/src/mesa/main/shaderimage.c
+++ b/src/mesa/main/shaderimage.c
@@ -331,17 +331,88 @@ get_image_format_class(mesa_format format)
}
}
+/**
+ * Return whether an image format should be supported based on the current API
+ * version of the context.
+ */
+static bool
+is_image_format_supported(const struct gl_context *ctx, GLenum format)
+{
+ switch (format) {
+ /* Formats supported on both desktop and ES GL, c.f. table 8.27 of the
+ * OpenGL ES 3.1 specification.
+ */
+ case GL_RGBA32F:
+ case GL_RGBA16F:
+ case GL_R32F:
+ case GL_RGBA32UI:
+ case GL_RGBA16UI:
+ case GL_RGBA8UI:
+ case GL_R32UI:
+ case GL_RGBA32I:
+ case GL_RGBA16I:
+ case GL_RGBA8I:
+ case GL_R32I:
+ case GL_RGBA8:
+ case GL_RGBA8_SNORM:
+ return true;
+
+ /* Formats supported on unextended desktop GL and the original
+ * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2
+ * specification.
+ */
+ case GL_RG32F:
+ case GL_RG16F:
+ case GL_R11F_G11F_B10F:
+ case GL_R16F:
+ case GL_RGB10_A2UI:
+ case GL_RG32UI:
+ case GL_RG16UI:
+ case GL_RG8UI:
+ case GL_R16UI:
+ case GL_R8UI:
+ case GL_RG32I:
+ case GL_RG16I:
+ case GL_RG8I:
+ case GL_R16I:
+ case GL_R8I:
+ case GL_RGBA16:
+ case GL_RGB10_A2:
+ case GL_RG16:
+ case GL_RG8:
+ case GL_R16:
+ case GL_R8:
+ case GL_RGBA16_SNORM:
+ case GL_RG16_SNORM:
+ case GL_RG8_SNORM:
+ case GL_R16_SNORM:
+ case GL_R8_SNORM:
+ return _mesa_is_desktop_gl(ctx);
+
+ default:
+ return false;
+ }
+}
+
+struct gl_image_unit
+_mesa_default_image_unit(struct gl_context *ctx)
+{
+ const GLenum format = _mesa_is_desktop_gl(ctx) ? GL_R8 : GL_R32UI;
+ const struct gl_image_unit u = {
+ .Access = GL_READ_ONLY,
+ .Format = format,
+ ._ActualFormat = _mesa_get_shader_image_format(format)
+ };
+ return u;
+}
+
void
_mesa_init_image_units(struct gl_context *ctx)
{
unsigned i;
- for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i) {
- struct gl_image_unit *u = &ctx->ImageUnits[i];
- u->Access = GL_READ_ONLY;
- u->Format = GL_R8;
- u->_ActualFormat = _mesa_get_shader_image_format(u->Format);
- }
+ for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i)
+ ctx->ImageUnits[i] = _mesa_default_image_unit(ctx);
}
static GLboolean
@@ -362,7 +433,7 @@ validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u)
return GL_FALSE;
if (_mesa_tex_target_is_layered(t->Target) &&
- u->Layer >= _mesa_get_texture_layers(t, u->Level))
+ u->_Layer >= _mesa_get_texture_layers(t, u->Level))
return GL_FALSE;
if (t->Target == GL_TEXTURE_BUFFER) {
@@ -370,7 +441,7 @@ validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u)
} else {
struct gl_texture_image *img = (t->Target == GL_TEXTURE_CUBE_MAP ?
- t->Image[u->Layer][u->Level] :
+ t->Image[u->_Layer][u->Level] :
t->Image[0][u->Level]);
if (!img || img->Border || img->NumSamples > ctx->Const.MaxImageSamples)
@@ -442,7 +513,7 @@ validate_bind_image_texture(struct gl_context *ctx, GLuint unit,
return GL_FALSE;
}
- if (!_mesa_get_shader_image_format(format)) {
+ if (!is_image_format_supported(ctx, format)) {
_mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)");
return GL_FALSE;
}
@@ -475,6 +546,18 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level,
return;
}
+ /* From section 8.22 "Texture Image Loads and Stores" of the OpenGL ES
+ * 3.1 spec:
+ *
+ * "An INVALID_OPERATION error is generated if texture is not the name
+ * of an immutable texture object."
+ */
+ if (_mesa_is_gles(ctx) && !t->Immutable) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindImageTexture(!immutable)");
+ return;
+ }
+
_mesa_reference_texobj(&u->TexObj, t);
} else {
_mesa_reference_texobj(&u->TexObj, NULL);
@@ -488,7 +571,8 @@ _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level,
if (u->TexObj && _mesa_tex_target_is_layered(u->TexObj->Target)) {
u->Layered = layered;
- u->Layer = (layered ? 0 : layer);
+ u->Layer = layer;
+ u->_Layer = (u->Layered ? 0 : u->Layer);
} else {
u->Layered = GL_FALSE;
u->Layer = 0;
@@ -599,7 +683,7 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
tex_format = image->InternalFormat;
}
- if (_mesa_get_shader_image_format(tex_format) == MESA_FORMAT_NONE) {
+ if (!is_image_format_supported(ctx, tex_format)) {
/* The ARB_multi_bind spec says:
*
* "An INVALID_OPERATION error is generated if the internal
@@ -619,7 +703,7 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
_mesa_reference_texobj(&u->TexObj, texObj);
u->Level = 0;
u->Layered = _mesa_tex_target_is_layered(texObj->Target);
- u->Layer = 0;
+ u->_Layer = u->Layer = 0;
u->Access = GL_READ_WRITE;
u->Format = tex_format;
u->_ActualFormat = _mesa_get_shader_image_format(tex_format);
@@ -629,7 +713,7 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
_mesa_reference_texobj(&u->TexObj, NULL);
u->Level = 0;
u->Layered = GL_FALSE;
- u->Layer = 0;
+ u->_Layer = u->Layer = 0;
u->Access = GL_READ_ONLY;
u->Format = GL_R8;
u->_ActualFormat = MESA_FORMAT_R_UNORM8;
@@ -653,3 +737,43 @@ _mesa_MemoryBarrier(GLbitfield barriers)
if (ctx->Driver.MemoryBarrier)
ctx->Driver.MemoryBarrier(ctx, barriers);
}
+
+void GLAPIENTRY
+_mesa_MemoryBarrierByRegion(GLbitfield barriers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ GLbitfield all_allowed_bits = GL_ATOMIC_COUNTER_BARRIER_BIT |
+ GL_FRAMEBUFFER_BARRIER_BIT |
+ GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
+ GL_SHADER_STORAGE_BARRIER_BIT |
+ GL_TEXTURE_FETCH_BARRIER_BIT |
+ GL_UNIFORM_BARRIER_BIT;
+
+ if (ctx->Driver.MemoryBarrier) {
+ /* From section 7.11.2 of the OpenGL ES 3.1 specification:
+ *
+ * "When barriers is ALL_BARRIER_BITS, shader memory accesses will be
+ * synchronized relative to all these barrier bits, but not to other
+ * barrier bits specific to MemoryBarrier."
+ *
+ * That is, if barriers is the special value GL_ALL_BARRIER_BITS, then all
+ * barriers allowed by glMemoryBarrierByRegion should be activated."
+ */
+ if (barriers == GL_ALL_BARRIER_BITS)
+ return ctx->Driver.MemoryBarrier(ctx, all_allowed_bits);
+
+ /* From section 7.11.2 of the OpenGL ES 3.1 specification:
+ *
+ * "An INVALID_VALUE error is generated if barriers is not the special
+ * value ALL_BARRIER_BITS, and has any bits set other than those
+ * described above."
+ */
+ if ((barriers & ~all_allowed_bits) != 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMemoryBarrierByRegion(unsupported barrier bit");
+ }
+
+ ctx->Driver.MemoryBarrier(ctx, barriers);
+ }
+}
diff --git a/src/mesa/main/shaderimage.h b/src/mesa/main/shaderimage.h
index 33d8a1eff55..bbe088a2459 100644
--- a/src/mesa/main/shaderimage.h
+++ b/src/mesa/main/shaderimage.h
@@ -43,6 +43,12 @@ mesa_format
_mesa_get_shader_image_format(GLenum format);
/**
+ * Get a single image unit struct with the default state.
+ */
+struct gl_image_unit
+_mesa_default_image_unit(struct gl_context *ctx);
+
+/**
* Initialize a context's shader image units to the default state.
*/
void
@@ -68,6 +74,9 @@ _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures);
void GLAPIENTRY
_mesa_MemoryBarrier(GLbitfield barriers);
+void GLAPIENTRY
+_mesa_MemoryBarrierByRegion(GLbitfield barriers);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/mesa/main/tests/Makefile.am b/src/mesa/main/tests/Makefile.am
index 251474d5c25..9467f3ba8c6 100644
--- a/src/mesa/main/tests/Makefile.am
+++ b/src/mesa/main/tests/Makefile.am
@@ -27,6 +27,7 @@ AM_CPPFLAGS += -DHAVE_SHARED_GLAPI
main_test_SOURCES += \
dispatch_sanity.cpp \
+ mesa_formats.cpp \
program_state_string.cpp
main_test_LDADD += \
diff --git a/src/mesa/main/tests/dispatch_sanity.cpp b/src/mesa/main/tests/dispatch_sanity.cpp
index af89d2c1cfb..59107eb67b1 100644
--- a/src/mesa/main/tests/dispatch_sanity.cpp
+++ b/src/mesa/main/tests/dispatch_sanity.cpp
@@ -851,6 +851,9 @@ const struct function common_desktop_functions_possible[] = {
// { "glTextureStorage2DMultisampleEXT", 43, -1 }, // XXX: Add to xml
// { "glTextureStorage3DMultisampleEXT", 43, -1 }, // XXX: Add to xml
+/* GL 4.5 */
+ { "glMemoryBarrierByRegion", 45, -1 },
+
/* GL_ARB_internalformat_query */
{ "glGetInternalformativ", 30, -1 },
@@ -1739,6 +1742,9 @@ const struct function gl_core_functions_possible[] = {
// { "glTextureStorage2DMultisampleEXT", 43, -1 }, // XXX: Add to xml
// { "glTextureStorage3DMultisampleEXT", 43, -1 }, // XXX: Add to xml
+/* GL 4.5 */
+ { "glMemoryBarrierByRegion", 45, -1 },
+
/* GL_ARB_direct_state_access */
{ "glCreateTransformFeedbacks", 45, -1 },
{ "glTransformFeedbackBufferBase", 45, -1 },
@@ -2461,8 +2467,7 @@ const struct function gles31_functions_possible[] = {
{ "glGetBooleani_v", 31, -1 },
{ "glMemoryBarrier", 31, -1 },
- // FINISHME: This function has not been implemented yet.
- // { "glMemoryBarrierByRegion", 31, -1 },
+ { "glMemoryBarrierByRegion", 31, -1 },
{ "glTexStorage2DMultisample", 31, -1 },
{ "glGetMultisamplefv", 31, -1 },
diff --git a/src/mesa/main/tests/mesa_formats.cpp b/src/mesa/main/tests/mesa_formats.cpp
new file mode 100644
index 00000000000..5356cd919a8
--- /dev/null
+++ b/src/mesa/main/tests/mesa_formats.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \name mesa_formats.cpp
+ *
+ * Verify that all mesa formats are handled in certain functions and that
+ * the format info table is sane.
+ *
+ */
+
+#include <gtest/gtest.h>
+
+#include "main/formats.h"
+#include "main/glformats.h"
+
+/**
+ * Debug/test: check that all uncompressed formats are handled in the
+ * _mesa_uncompressed_format_to_type_and_comps() function. When new pixel
+ * formats are added to Mesa, that function needs to be updated.
+ */
+TEST(MesaFormatsTest, FormatTypeAndComps)
+{
+ for (int fi = MESA_FORMAT_NONE + 1; fi < MESA_FORMAT_COUNT; ++fi) {
+ mesa_format f = (mesa_format) fi;
+ SCOPED_TRACE(_mesa_get_format_name(f));
+
+ /* This function will emit a problem/warning if the format is
+ * not handled.
+ */
+ if (!_mesa_is_format_compressed(f)) {
+ GLenum datatype = 0;
+ GLenum error = 0;
+ GLuint comps = 0;
+
+ /* If the datatype is zero, the format was not handled */
+ _mesa_uncompressed_format_to_type_and_comps(f, &datatype, &comps);
+ EXPECT_NE(datatype, (GLenum)0);
+
+ /* If the error isn't NO_ERROR, the format was not handled.
+ * Use an arbitrary GLenum format. */
+ _mesa_format_matches_format_and_type(f, GL_RG, datatype,
+ GL_FALSE, &error);
+ EXPECT_EQ((GLenum)GL_NO_ERROR, error);
+ }
+
+ }
+}
+
+/**
+ * Do sanity checking of the format info table.
+ */
+TEST(MesaFormatsTest, FormatSanity)
+{
+ for (int fi = 0; fi < MESA_FORMAT_COUNT; ++fi) {
+ mesa_format f = (mesa_format) fi;
+ SCOPED_TRACE(_mesa_get_format_name(f));
+ GLenum datatype = _mesa_get_format_datatype(f);
+ GLint r = _mesa_get_format_bits(f, GL_RED_BITS);
+ GLint g = _mesa_get_format_bits(f, GL_GREEN_BITS);
+ GLint b = _mesa_get_format_bits(f, GL_BLUE_BITS);
+ GLint a = _mesa_get_format_bits(f, GL_ALPHA_BITS);
+ GLint l = _mesa_get_format_bits(f, GL_TEXTURE_LUMINANCE_SIZE);
+ GLint i = _mesa_get_format_bits(f, GL_TEXTURE_INTENSITY_SIZE);
+
+ /* Note: Z32_FLOAT_X24S8 has datatype of GL_NONE */
+ EXPECT_TRUE(datatype == GL_NONE ||
+ datatype == GL_UNSIGNED_NORMALIZED ||
+ datatype == GL_SIGNED_NORMALIZED ||
+ datatype == GL_UNSIGNED_INT ||
+ datatype == GL_INT ||
+ datatype == GL_FLOAT);
+
+ if (r > 0 && !_mesa_is_format_compressed(f)) {
+ GLint bytes = _mesa_get_format_bytes(f);
+ EXPECT_LE((r+g+b+a) / 8, bytes);
+ }
+
+ /* Determines if the base format has a channel [rgba] or property [li].
+ * > indicates existance
+ * == indicates non-existance
+ */
+ #define HAS_PROP(rop,gop,bop,aop,lop,iop) \
+ do { \
+ EXPECT_TRUE(r rop 0); \
+ EXPECT_TRUE(g gop 0); \
+ EXPECT_TRUE(b bop 0); \
+ EXPECT_TRUE(a aop 0); \
+ EXPECT_TRUE(l lop 0); \
+ EXPECT_TRUE(i iop 0); \
+ } while(0)
+
+ switch (_mesa_get_format_base_format(f)) {
+ case GL_RGBA:
+ HAS_PROP(>,>,>,>,==,==);
+ break;
+ case GL_RGB:
+ HAS_PROP(>,>,>,==,==,==);
+ break;
+ case GL_RG:
+ HAS_PROP(>,>,==,==,==,==);
+ break;
+ case GL_RED:
+ HAS_PROP(>,==,==,==,==,==);
+ break;
+ case GL_LUMINANCE:
+ HAS_PROP(==,==,==,==,>,==);
+ break;
+ case GL_INTENSITY:
+ HAS_PROP(==,==,==,==,==,>);
+ break;
+ default:
+ break;
+ }
+
+ #undef HAS_PROP
+
+ }
+}
diff --git a/src/mesa/main/texcompress.c b/src/mesa/main/texcompress.c
index 0fd1a3683d1..edfb03625c2 100644
--- a/src/mesa/main/texcompress.c
+++ b/src/mesa/main/texcompress.c
@@ -586,34 +586,16 @@ _mesa_compressed_image_address(GLint col, GLint row, GLint img,
compressed_fetch_func
_mesa_get_compressed_fetch_func(mesa_format format)
{
- switch (format) {
- case MESA_FORMAT_RGB_DXT1:
- case MESA_FORMAT_RGBA_DXT1:
- case MESA_FORMAT_RGBA_DXT3:
- case MESA_FORMAT_RGBA_DXT5:
- case MESA_FORMAT_SRGB_DXT1:
- case MESA_FORMAT_SRGBA_DXT1:
- case MESA_FORMAT_SRGBA_DXT3:
- case MESA_FORMAT_SRGBA_DXT5:
+ switch (_mesa_get_format_layout(format)) {
+ case MESA_FORMAT_LAYOUT_S3TC:
return _mesa_get_dxt_fetch_func(format);
- case MESA_FORMAT_RGB_FXT1:
- case MESA_FORMAT_RGBA_FXT1:
+ case MESA_FORMAT_LAYOUT_FXT1:
return _mesa_get_fxt_fetch_func(format);
- case MESA_FORMAT_R_RGTC1_UNORM:
- case MESA_FORMAT_L_LATC1_UNORM:
- case MESA_FORMAT_R_RGTC1_SNORM:
- case MESA_FORMAT_L_LATC1_SNORM:
- case MESA_FORMAT_RG_RGTC2_UNORM:
- case MESA_FORMAT_LA_LATC2_UNORM:
- case MESA_FORMAT_RG_RGTC2_SNORM:
- case MESA_FORMAT_LA_LATC2_SNORM:
+ case MESA_FORMAT_LAYOUT_RGTC:
return _mesa_get_compressed_rgtc_func(format);
- case MESA_FORMAT_ETC1_RGB8:
+ case MESA_FORMAT_LAYOUT_ETC1:
return _mesa_get_etc_fetch_func(format);
- case MESA_FORMAT_BPTC_RGBA_UNORM:
- case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
- case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
- case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
+ case MESA_FORMAT_LAYOUT_BPTC:
return _mesa_get_bptc_fetch_func(format);
default:
return NULL;
diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c
index c0ccce3d50e..3c1e166ffa1 100644
--- a/src/mesa/main/texgetimage.c
+++ b/src/mesa/main/texgetimage.c
@@ -651,7 +651,7 @@ get_tex_memcpy(struct gl_context *ctx,
texBaseFormat == texImage->_BaseFormat) {
memCopy = _mesa_format_matches_format_and_type(texImage->TexFormat,
format, type,
- ctx->Pack.SwapBytes);
+ ctx->Pack.SwapBytes, NULL);
}
if (depth > 1) {
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 3a556a6ad6e..274ecad44e9 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -1785,18 +1785,36 @@ compressedteximage_only_format(const struct gl_context *ctx, GLenum format)
}
+/* Writes to an GL error pointer if non-null and returns whether or not the
+ * error is GL_NO_ERROR */
+static bool
+write_error(GLenum *err_ptr, GLenum error)
+{
+ if (err_ptr)
+ *err_ptr = error;
+
+ return error == GL_NO_ERROR;
+}
+
/**
* Helper function to determine whether a target and specific compression
- * format are supported.
+ * format are supported. The error parameter returns GL_NO_ERROR if the
+ * target can be compressed. Otherwise it returns either GL_INVALID_OPERATION
+ * or GL_INVALID_ENUM, whichever is more appropriate.
*/
GLboolean
_mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target,
- GLenum intFormat)
+ GLenum intFormat, GLenum *error)
{
+ GLboolean target_can_be_compresed = GL_FALSE;
+ mesa_format format = _mesa_glenum_to_compressed_format(intFormat);
+ enum mesa_format_layout layout = _mesa_get_format_layout(format);
+
switch (target) {
case GL_TEXTURE_2D:
case GL_PROXY_TEXTURE_2D:
- return GL_TRUE; /* true for any compressed format so far */
+ target_can_be_compresed = GL_TRUE; /* true for any compressed format so far */
+ break;
case GL_PROXY_TEXTURE_CUBE_MAP:
case GL_TEXTURE_CUBE_MAP:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
@@ -1805,26 +1823,46 @@ _mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target,
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- return ctx->Extensions.ARB_texture_cube_map;
+ target_can_be_compresed = ctx->Extensions.ARB_texture_cube_map;
+ break;
case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
case GL_TEXTURE_2D_ARRAY_EXT:
- return ctx->Extensions.EXT_texture_array;
+ target_can_be_compresed = ctx->Extensions.EXT_texture_array;
+ break;
case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
case GL_TEXTURE_CUBE_MAP_ARRAY:
- return ctx->Extensions.ARB_texture_cube_map_array;
+ /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec:
+ *
+ * "The ETC2/EAC texture compression algorithm supports only
+ * two-dimensional images. If internalformat is an ETC2/EAC format,
+ * glCompressedTexImage3D will generate an INVALID_OPERATION error if
+ * target is not TEXTURE_2D_ARRAY."
+ *
+ * This should also be applicable for glTexStorage3D(). Other available
+ * targets for these functions are: TEXTURE_3D and TEXTURE_CUBE_MAP_ARRAY.
+ */
+ if (layout == MESA_FORMAT_LAYOUT_ETC2 && _mesa_is_gles3(ctx))
+ return write_error(error, GL_INVALID_OPERATION);
+
+ target_can_be_compresed = ctx->Extensions.ARB_texture_cube_map_array;
+ break;
case GL_TEXTURE_3D:
- switch (intFormat) {
- case GL_COMPRESSED_RGBA_BPTC_UNORM:
- case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
- case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
- case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
- return ctx->Extensions.ARB_texture_compression_bptc;
- default:
- return GL_FALSE;
+
+ /* See ETC2/EAC comment in switch case GL_TEXTURE_CUBE_MAP_ARRAY. */
+ if (layout == MESA_FORMAT_LAYOUT_ETC2 && _mesa_is_gles3(ctx))
+ return write_error(error, GL_INVALID_OPERATION);
+
+ if (layout == MESA_FORMAT_LAYOUT_BPTC) {
+ target_can_be_compresed = ctx->Extensions.ARB_texture_compression_bptc;
+ break;
}
+
+ break;
default:
- return GL_FALSE;
+ break;
}
+ return write_error(error,
+ target_can_be_compresed ? GL_NO_ERROR : GL_INVALID_ENUM);
}
@@ -2284,8 +2322,9 @@ texture_error_check( struct gl_context *ctx,
/* additional checks for compressed textures */
if (_mesa_is_compressed_format(ctx, internalFormat)) {
- if (!_mesa_target_can_be_compressed(ctx, target, internalFormat)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
+ GLenum err;
+ if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &err)) {
+ _mesa_error(ctx, err,
"glTexImage%dD(target can't be compressed)", dimensions);
return GL_TRUE;
}
@@ -2340,16 +2379,8 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
GLenum error = GL_NO_ERROR;
char *reason = ""; /* no error */
- if (!_mesa_target_can_be_compressed(ctx, target, internalFormat)) {
+ if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &error)) {
reason = "target";
- /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec:
- *
- * "The ETC2/EAC texture compression algorithm supports only
- * two-dimensional images. If internalformat is an ETC2/EAC format,
- * CompressedTexImage3D will generate an INVALID_OPERATION error if
- * target is not TEXTURE_2D_ARRAY."
- */
- error = _mesa_is_desktop_gl(ctx) ? GL_INVALID_ENUM : GL_INVALID_OPERATION;
goto error;
}
@@ -2813,9 +2844,10 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
}
if (_mesa_is_compressed_format(ctx, internalFormat)) {
- if (!_mesa_target_can_be_compressed(ctx, target, internalFormat)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glCopyTexImage%dD(target)", dimensions);
+ GLenum err;
+ if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &err)) {
+ _mesa_error(ctx, err,
+ "glCopyTexImage%dD(target can't be compressed)", dimensions);
return GL_TRUE;
}
if (compressedteximage_only_format(ctx, internalFormat)) {
@@ -5569,10 +5601,13 @@ static GLboolean
is_renderable_texture_format(struct gl_context *ctx, GLenum internalformat)
{
/* Everything that is allowed for renderbuffers,
- * except for a base format of GL_STENCIL_INDEX.
+ * except for a base format of GL_STENCIL_INDEX, unless supported.
*/
GLenum baseFormat = _mesa_base_fbo_format(ctx, internalformat);
- return baseFormat != 0 && baseFormat != GL_STENCIL_INDEX;
+ if (ctx->Extensions.ARB_texture_stencil8)
+ return baseFormat != 0;
+ else
+ return baseFormat != 0 && baseFormat != GL_STENCIL_INDEX;
}
@@ -5596,13 +5631,13 @@ check_multisample_target(GLuint dims, GLenum target, bool dsa)
static void
-_mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims,
- struct gl_texture_object *texObj,
- GLenum target, GLsizei samples,
- GLint internalformat, GLsizei width,
- GLsizei height, GLsizei depth,
- GLboolean fixedsamplelocations,
- GLboolean immutable, const char *func)
+texture_image_multisample(struct gl_context *ctx, GLuint dims,
+ struct gl_texture_object *texObj,
+ GLenum target, GLsizei samples,
+ GLint internalformat, GLsizei width,
+ GLsizei height, GLsizei depth,
+ GLboolean fixedsamplelocations,
+ GLboolean immutable, const char *func)
{
struct gl_texture_image *texImage;
GLboolean sizeOK, dimensionsOK, samplesOK;
@@ -5616,6 +5651,11 @@ _mesa_texture_image_multisample(struct gl_context *ctx, GLuint dims,
return;
}
+ if (samples < 1) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples < 1)", func);
+ return;
+ }
+
if (!check_multisample_target(dims, target, dsa)) {
if (dsa) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(target)", func);
@@ -5763,10 +5803,10 @@ _mesa_TexImage2DMultisample(GLenum target, GLsizei samples,
if (!texObj)
return;
- _mesa_texture_image_multisample(ctx, 2, texObj, target, samples,
- internalformat, width, height, 1,
- fixedsamplelocations, GL_FALSE,
- "glTexImage2DMultisample");
+ texture_image_multisample(ctx, 2, texObj, target, samples,
+ internalformat, width, height, 1,
+ fixedsamplelocations, GL_FALSE,
+ "glTexImage2DMultisample");
}
@@ -5783,12 +5823,26 @@ _mesa_TexImage3DMultisample(GLenum target, GLsizei samples,
if (!texObj)
return;
- _mesa_texture_image_multisample(ctx, 3, texObj, target, samples,
- internalformat, width, height, depth,
- fixedsamplelocations, GL_FALSE,
- "glTexImage3DMultisample");
+ texture_image_multisample(ctx, 3, texObj, target, samples,
+ internalformat, width, height, depth,
+ fixedsamplelocations, GL_FALSE,
+ "glTexImage3DMultisample");
}
+static bool
+valid_texstorage_ms_parameters(GLsizei width, GLsizei height, GLsizei depth,
+ GLsizei samples, unsigned dims)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_valid_tex_storage_dim(width, height, depth)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexStorage%uDMultisample(width=%d,height=%d,depth=%d)",
+ dims, width, height, depth);
+ return false;
+ }
+ return true;
+}
void GLAPIENTRY
_mesa_TexStorage2DMultisample(GLenum target, GLsizei samples,
@@ -5802,10 +5856,13 @@ _mesa_TexStorage2DMultisample(GLenum target, GLsizei samples,
if (!texObj)
return;
- _mesa_texture_image_multisample(ctx, 2, texObj, target, samples,
- internalformat, width, height, 1,
- fixedsamplelocations, GL_TRUE,
- "glTexStorage2DMultisample");
+ if (!valid_texstorage_ms_parameters(width, height, 1, samples, 2))
+ return;
+
+ texture_image_multisample(ctx, 2, texObj, target, samples,
+ internalformat, width, height, 1,
+ fixedsamplelocations, GL_TRUE,
+ "glTexStorage2DMultisample");
}
void GLAPIENTRY
@@ -5821,10 +5878,13 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples,
if (!texObj)
return;
- _mesa_texture_image_multisample(ctx, 3, texObj, target, samples,
- internalformat, width, height, depth,
- fixedsamplelocations, GL_TRUE,
- "glTexStorage3DMultisample");
+ if (!valid_texstorage_ms_parameters(width, height, depth, samples, 3))
+ return;
+
+ texture_image_multisample(ctx, 3, texObj, target, samples,
+ internalformat, width, height, depth,
+ fixedsamplelocations, GL_TRUE,
+ "glTexStorage3DMultisample");
}
void GLAPIENTRY
@@ -5841,10 +5901,13 @@ _mesa_TextureStorage2DMultisample(GLuint texture, GLsizei samples,
if (!texObj)
return;
- _mesa_texture_image_multisample(ctx, 2, texObj, texObj->Target, samples,
- internalformat, width, height, 1,
- fixedsamplelocations, GL_TRUE,
- "glTextureStorage2DMultisample");
+ if (!valid_texstorage_ms_parameters(width, height, 1, samples, 2))
+ return;
+
+ texture_image_multisample(ctx, 2, texObj, texObj->Target, samples,
+ internalformat, width, height, 1,
+ fixedsamplelocations, GL_TRUE,
+ "glTextureStorage2DMultisample");
}
void GLAPIENTRY
@@ -5862,8 +5925,11 @@ _mesa_TextureStorage3DMultisample(GLuint texture, GLsizei samples,
if (!texObj)
return;
- _mesa_texture_image_multisample(ctx, 3, texObj, texObj->Target, samples,
- internalformat, width, height, depth,
- fixedsamplelocations, GL_TRUE,
- "glTextureStorage3DMultisample");
+ if (!valid_texstorage_ms_parameters(width, height, depth, samples, 3))
+ return;
+
+ texture_image_multisample(ctx, 3, texObj, texObj->Target, samples,
+ internalformat, width, height, depth,
+ fixedsamplelocations, GL_TRUE,
+ "glTextureStorage3DMultisample");
}
diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h
index bf729daf534..a4736b5a29f 100644
--- a/src/mesa/main/teximage.h
+++ b/src/mesa/main/teximage.h
@@ -133,7 +133,7 @@ _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level,
extern GLboolean
_mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target,
- GLenum intFormat);
+ GLenum intFormat, GLenum *error);
extern GLuint
_mesa_tex_target_to_face(GLenum target);
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index cd7cfd6a4fb..c5d83e145a6 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -37,6 +37,7 @@
#include "hash.h"
#include "imports.h"
#include "macros.h"
+#include "shaderimage.h"
#include "teximage.h"
#include "texobj.h"
#include "texstate.h"
@@ -1411,8 +1412,10 @@ unbind_texobj_from_image_units(struct gl_context *ctx,
for (i = 0; i < ctx->Const.MaxImageUnits; i++) {
struct gl_image_unit *unit = &ctx->ImageUnits[i];
- if (texObj == unit->TexObj)
+ if (texObj == unit->TexObj) {
_mesa_reference_texobj(&unit->TexObj, NULL);
+ *unit = _mesa_default_image_unit(ctx);
+ }
}
}
@@ -1742,10 +1745,10 @@ _mesa_BindTexture( GLenum target, GLuint texName )
* texture object will be decremented. It'll be deleted if the
* count hits zero.
*/
-void
-_mesa_bind_texture_unit(struct gl_context *ctx,
- GLuint unit,
- struct gl_texture_object *texObj)
+static void
+bind_texture_unit(struct gl_context *ctx,
+ GLuint unit,
+ struct gl_texture_object *texObj)
{
struct gl_texture_unit *texUnit;
@@ -1834,7 +1837,7 @@ _mesa_BindTextureUnit(GLuint unit, GLuint texture)
}
assert(valid_texture_object(texObj));
- _mesa_bind_texture_unit(ctx, unit, texObj);
+ bind_texture_unit(ctx, unit, texObj);
}
diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h
index ec5ccb27601..690878c85fc 100644
--- a/src/mesa/main/texobj.h
+++ b/src/mesa/main/texobj.h
@@ -209,10 +209,6 @@ extern void
_mesa_delete_nameless_texture(struct gl_context *ctx,
struct gl_texture_object *texObj);
-extern void
-_mesa_bind_texture_unit(struct gl_context *ctx,
- GLuint unit,
- struct gl_texture_object *texObj);
/*@}*/
diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c
index c0611c3e489..16739f1779b 100644
--- a/src/mesa/main/texparam.c
+++ b/src/mesa/main/texparam.c
@@ -1562,6 +1562,19 @@ invalid_pname:
_mesa_enum_to_string(pname));
}
+static bool
+valid_tex_level_parameteriv_target(struct gl_context *ctx, GLenum target,
+ bool dsa)
+{
+ const char *suffix = dsa ? "ture" : "";
+ if (!legal_get_tex_level_parameter_target(ctx, target, dsa)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTex%sLevelParameter[if]v(target=%s)", suffix,
+ _mesa_enum_to_string(target));
+ return false;
+ }
+ return true;
+}
/**
* This isn't exposed to the rest of the driver because it is a part of the
@@ -1585,13 +1598,6 @@ get_tex_level_parameteriv(struct gl_context *ctx,
return;
}
- if (!legal_get_tex_level_parameter_target(ctx, target, dsa)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetTex%sLevelParameter[if]v(target=%s)", suffix,
- _mesa_enum_to_string(target));
- return;
- }
-
maxLevels = _mesa_max_texture_levels(ctx, target);
assert(maxLevels != 0);
@@ -1619,6 +1625,9 @@ _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
GLint iparam;
GET_CURRENT_CONTEXT(ctx);
+ if (!valid_tex_level_parameteriv_target(ctx, target, false))
+ return;
+
texObj = _mesa_get_current_tex_object(ctx, target);
if (!texObj)
return;
@@ -1636,6 +1645,9 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
struct gl_texture_object *texObj;
GET_CURRENT_CONTEXT(ctx);
+ if (!valid_tex_level_parameteriv_target(ctx, target, false))
+ return;
+
texObj = _mesa_get_current_tex_object(ctx, target);
if (!texObj)
return;
@@ -1657,6 +1669,9 @@ _mesa_GetTextureLevelParameterfv(GLuint texture, GLint level,
if (!texObj)
return;
+ if (!valid_tex_level_parameteriv_target(ctx, texObj->Target, true))
+ return;
+
get_tex_level_parameteriv(ctx, texObj, texObj->Target, level,
pname, &iparam, true);
@@ -1675,6 +1690,9 @@ _mesa_GetTextureLevelParameteriv(GLuint texture, GLint level,
if (!texObj)
return;
+ if (!valid_tex_level_parameteriv_target(ctx, texObj->Target, true))
+ return;
+
get_tex_level_parameteriv(ctx, texObj, texObj->Target, level,
pname, params, true);
}
@@ -1890,6 +1908,12 @@ get_tex_parameterfv(struct gl_context *ctx,
*params = (GLfloat) obj->Sampler.sRGBDecode;
break;
+ case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
+ if (!ctx->Extensions.ARB_shader_image_load_store)
+ goto invalid_pname;
+ *params = (GLfloat) obj->ImageFormatCompatibilityType;
+ break;
+
default:
goto invalid_pname;
}
diff --git a/src/mesa/main/texstorage.c b/src/mesa/main/texstorage.c
index 4a2cc6065df..c53bb295c66 100644
--- a/src/mesa/main/texstorage.c
+++ b/src/mesa/main/texstorage.c
@@ -189,6 +189,20 @@ clear_texture_fields(struct gl_context *ctx,
}
+/**
+ * Update/re-validate framebuffer object.
+ */
+static void
+update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
+{
+ const unsigned numFaces = _mesa_num_tex_faces(texObj->Target);
+ for (int level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
+ for (unsigned face = 0; face < numFaces; face++)
+ _mesa_update_fbo_texture(ctx, texObj, face, level);
+ }
+}
+
+
GLboolean
_mesa_is_legal_tex_storage_format(struct gl_context *ctx, GLenum internalformat)
{
@@ -287,29 +301,21 @@ tex_storage_error_check(struct gl_context *ctx,
* order to allow meta functions to use legacy formats. */
/* size check */
- if (width < 1 || height < 1 || depth < 1) {
+ if (!_mesa_valid_tex_storage_dim(width, height, depth)) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glTex%sStorage%uD(width, height or depth < 1)",
suffix, dims);
return GL_TRUE;
}
- /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec:
- *
- * "The ETC2/EAC texture compression algorithm supports only
- * two-dimensional images. If internalformat is an ETC2/EAC format,
- * CompressedTexImage3D will generate an INVALID_OPERATION error if
- * target is not TEXTURE_2D_ARRAY."
- *
- * This should also be applicable for glTexStorage3D().
- */
- if (_mesa_is_compressed_format(ctx, internalformat)
- && !_mesa_target_can_be_compressed(ctx, target, internalformat)) {
- _mesa_error(ctx, _mesa_is_desktop_gl(ctx)?
- GL_INVALID_ENUM : GL_INVALID_OPERATION,
+ if (_mesa_is_compressed_format(ctx, internalformat)) {
+ GLenum err;
+ if (!_mesa_target_can_be_compressed(ctx, target, internalformat, &err)) {
+ _mesa_error(ctx, err,
"glTex%sStorage%dD(internalformat = %s)", suffix, dims,
_mesa_enum_to_string(internalformat));
- return GL_TRUE;
+ return GL_TRUE;
+ }
}
/* levels check */
@@ -446,6 +452,7 @@ _mesa_texture_storage(struct gl_context *ctx, GLuint dims,
_mesa_set_texture_view_state(ctx, texObj, target, levels);
+ update_fbo_texture(ctx, texObj);
}
}
diff --git a/src/mesa/main/texstorage.h b/src/mesa/main/texstorage.h
index 6f5495f3856..033ecb7edaa 100644
--- a/src/mesa/main/texstorage.h
+++ b/src/mesa/main/texstorage.h
@@ -38,6 +38,27 @@ _mesa_texture_storage(struct gl_context *ctx, GLuint dims,
GLenum internalformat, GLsizei width,
GLsizei height, GLsizei depth, bool dsa);
+/**
+ * Texture width, height and depth check shared with the
+ * multisample variants of TexStorage functions.
+ *
+ * From OpenGL 4.5 Core spec, page 260 (section 8.19)
+ *
+ * "An INVALID_VALUE error is generated if width, height, depth
+ * or levels are less than 1, for commands with the corresponding
+ * parameters."
+ *
+ * (referring to TextureStorage* commands, these also match values
+ * specified for OpenGL ES 3.1.)
+ */
+static inline bool
+_mesa_valid_tex_storage_dim(GLsizei width, GLsizei height, GLsizei depth)
+{
+ if (width < 1 || height < 1 || depth < 1)
+ return false;
+ return true;
+}
+
/*@}*/
/**
diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c
index 37c05690091..fc83310d4e3 100644
--- a/src/mesa/main/texstore.c
+++ b/src/mesa/main/texstore.c
@@ -863,7 +863,7 @@ _mesa_texstore_can_use_memcpy(struct gl_context *ctx,
/* The Mesa format must match the input format and type. */
if (!_mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
- srcPacking->SwapBytes)) {
+ srcPacking->SwapBytes, NULL)) {
return GL_FALSE;
}
diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp
index 036530e91b6..10266189259 100644
--- a/src/mesa/main/uniform_query.cpp
+++ b/src/mesa/main/uniform_query.cpp
@@ -319,24 +319,31 @@ _mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location,
return;
}
+ if ((uni->type->base_type == GLSL_TYPE_DOUBLE &&
+ returnType != GLSL_TYPE_DOUBLE) ||
+ (uni->type->base_type != GLSL_TYPE_DOUBLE &&
+ returnType == GLSL_TYPE_DOUBLE)) {
+ _mesa_error( ctx, GL_INVALID_OPERATION,
+ "glGetnUniform*vARB(incompatible uniform types)");
+ return;
+ }
{
unsigned elements = (uni->type->is_sampler())
? 1 : uni->type->components();
+ const int dmul = uni->type->base_type == GLSL_TYPE_DOUBLE ? 2 : 1;
/* Calculate the source base address *BEFORE* modifying elements to
* account for the size of the user's buffer.
*/
const union gl_constant_value *const src =
- &uni->storage[offset * elements];
+ &uni->storage[offset * elements * dmul];
assert(returnType == GLSL_TYPE_FLOAT || returnType == GLSL_TYPE_INT ||
- returnType == GLSL_TYPE_UINT);
- /* The three (currently) supported types all have the same size,
- * which is of course the same as their union. That'll change
- * with glGetUniformdv()...
- */
- unsigned bytes = sizeof(src[0]) * elements;
+ returnType == GLSL_TYPE_UINT || returnType == GLSL_TYPE_DOUBLE);
+
+ /* doubles have a different size than the other 3 types */
+ unsigned bytes = sizeof(src[0]) * elements * dmul;
if (bufSize < 0 || bytes > (unsigned) bufSize) {
_mesa_error( ctx, GL_INVALID_OPERATION,
"glGetnUniform*vARB(out of bounds: bufSize is %d,"
@@ -677,9 +684,11 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
match = (basicType != GLSL_TYPE_DOUBLE);
break;
case GLSL_TYPE_SAMPLER:
- case GLSL_TYPE_IMAGE:
match = (basicType == GLSL_TYPE_INT);
break;
+ case GLSL_TYPE_IMAGE:
+ match = (basicType == GLSL_TYPE_INT && _mesa_is_desktop_gl(ctx));
+ break;
default:
match = (basicType == uni->type->base_type);
break;
diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index ff1df72e1d6..10819e2e21a 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c
@@ -888,16 +888,7 @@ _mesa_GetnUniformdvARB(GLuint program, GLint location,
{
GET_CURRENT_CONTEXT(ctx);
- (void) program;
- (void) location;
- (void) bufSize;
- (void) params;
-
- /*
_mesa_get_uniform(ctx, program, location, bufSize, GLSL_TYPE_DOUBLE, params);
- */
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformdvARB"
- "(GL_ARB_gpu_shader_fp64 not implemented)");
}
void GLAPIENTRY
diff --git a/src/mesa/program/prog_to_nir.c b/src/mesa/program/prog_to_nir.c
index d54f934247d..d96b7bc8782 100644
--- a/src/mesa/program/prog_to_nir.c
+++ b/src/mesa/program/prog_to_nir.c
@@ -33,6 +33,7 @@
#include "prog_instruction.h"
#include "prog_parameter.h"
#include "prog_print.h"
+#include "program.h"
/**
* \file prog_to_nir.c
@@ -142,7 +143,7 @@ ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
load->variables[0] = nir_deref_var_create(load, c->input_vars[prog_src->Index]);
nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
- nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+ nir_builder_instr_insert(b, &load->instr);
src.src = nir_src_for_ssa(&load->dest.ssa);
break;
@@ -166,6 +167,8 @@ ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
}
/* FALLTHROUGH */
case PROGRAM_STATE_VAR: {
+ assert(c->parameters != NULL);
+
nir_intrinsic_instr *load =
nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_var);
nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
@@ -200,7 +203,7 @@ ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
deref_arr->base_offset = prog_src->Index;
}
- nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+ nir_builder_instr_insert(b, &load->instr);
src.src = nir_src_for_ssa(&load->dest.ssa);
break;
@@ -250,7 +253,7 @@ ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
mov->dest.write_mask = 0x1;
mov->src[0] = src;
mov->src[0].swizzle[0] = swizzle;
- nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr);
+ nir_builder_instr_insert(b, &mov->instr);
chans[i] = &mov->dest.dest.ssa;
}
@@ -278,7 +281,7 @@ ptn_alu(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
instr->src[i].src = nir_src_for_ssa(src[i]);
instr->dest = dest;
- nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+ nir_builder_instr_insert(b, &instr->instr);
}
static void
@@ -297,7 +300,7 @@ ptn_move_dest_masked(nir_builder *b, nir_alu_dest dest,
mov->src[0].src = nir_src_for_ssa(def);
for (unsigned i = def->num_components; i < 4; i++)
mov->src[0].swizzle[i] = def->num_components - 1;
- nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr);
+ nir_builder_instr_insert(b, &mov->instr);
}
static void
@@ -558,7 +561,7 @@ ptn_kil(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
nir_intrinsic_instr *discard =
nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard_if);
discard->src[0] = nir_src_for_ssa(cmp);
- nir_instr_insert_after_cf_list(b->cf_node_list, &discard->instr);
+ nir_builder_instr_insert(b, &discard->instr);
}
static void
@@ -685,7 +688,7 @@ ptn_tex(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src,
assert(src_number == num_srcs);
nir_ssa_dest_init(&instr->instr, &instr->dest, 4, NULL);
- nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+ nir_builder_instr_insert(b, &instr->instr);
/* Resolve the writemask on the texture op. */
ptn_move_dest(b, dest, &instr->dest.ssa);
@@ -941,7 +944,7 @@ ptn_add_output_stores(struct ptn_compile *c)
} else {
store->src[0].reg.reg = c->output_regs[var->data.location];
}
- nir_instr_insert_after_cf_list(c->build.cf_node_list, &store->instr);
+ nir_builder_instr_insert(b, &store->instr);
}
}
@@ -985,7 +988,7 @@ setup_registers_and_variables(struct ptn_compile *c)
load_x->num_components = 1;
load_x->variables[0] = nir_deref_var_create(load_x, var);
nir_ssa_dest_init(&load_x->instr, &load_x->dest, 1, NULL);
- nir_instr_insert_after_cf_list(b->cf_node_list, &load_x->instr);
+ nir_builder_instr_insert(b, &load_x->instr);
nir_ssa_def *f001 = nir_vec4(b, &load_x->dest.ssa, nir_imm_float(b, 0.0),
nir_imm_float(b, 0.0), nir_imm_float(b, 1.0));
@@ -1001,7 +1004,7 @@ setup_registers_and_variables(struct ptn_compile *c)
store->num_components = 4;
store->variables[0] = nir_deref_var_create(store, fullvar);
store->src[0] = nir_src_for_ssa(f001);
- nir_instr_insert_after_cf_list(b->cf_node_list, &store->instr);
+ nir_builder_instr_insert(b, &store->instr);
/* Insert the real input into the list so the driver has real
* inputs, but set c->input_vars[i] to the temporary so we use
@@ -1079,22 +1082,25 @@ prog_to_nir(const struct gl_program *prog,
{
struct ptn_compile *c;
struct nir_shader *s;
+ gl_shader_stage stage = _mesa_program_enum_to_shader_stage(prog->Target);
c = rzalloc(NULL, struct ptn_compile);
if (!c)
return NULL;
- s = nir_shader_create(NULL, options);
+ s = nir_shader_create(NULL, stage, options);
if (!s)
goto fail;
c->prog = prog;
- c->parameters = rzalloc(s, nir_variable);
- c->parameters->type = glsl_array_type(glsl_vec4_type(),
- prog->Parameters->NumParameters);
- c->parameters->name = "parameters";
- c->parameters->data.read_only = true;
- c->parameters->data.mode = nir_var_uniform;
- exec_list_push_tail(&s->uniforms, &c->parameters->node);
+ if (prog->Parameters->NumParameters > 0) {
+ c->parameters = rzalloc(s, nir_variable);
+ c->parameters->type =
+ glsl_array_type(glsl_vec4_type(), prog->Parameters->NumParameters);
+ c->parameters->name = "parameters";
+ c->parameters->data.read_only = true;
+ c->parameters->data.mode = nir_var_uniform;
+ exec_list_push_tail(&s->uniforms, &c->parameters->node);
+ }
nir_function *func = nir_function_create(s, "main");
nir_function_overload *overload = nir_function_overload_create(func);
@@ -1102,7 +1108,7 @@ prog_to_nir(const struct gl_program *prog,
c->build.shader = s;
c->build.impl = impl;
- c->build.cf_node_list = &impl->body;
+ nir_builder_insert_after_cf_list(&c->build, &impl->body);
setup_registers_and_variables(c);
if (unlikely(c->error))
diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c
index 139690615d6..4fdef7fb5a6 100644
--- a/src/mesa/state_tracker/st_cb_blit.c
+++ b/src/mesa/state_tracker/st_cb_blit.c
@@ -192,6 +192,7 @@ st_BlitFramebuffer(struct gl_context *ctx,
blit.filter = pFilter;
blit.render_condition_enable = TRUE;
+ blit.alpha_blend = FALSE;
if (mask & GL_COLOR_BUFFER_BIT) {
struct gl_renderbuffer_attachment *srcAtt =
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
index 18ea43fa71a..6ff6cf6f6d6 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.c
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -139,7 +139,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y,
* in which case the memcpy-based fast path will likely be used and
* we don't have to blit. */
if (_mesa_format_matches_format_and_type(rb->Format, format,
- type, pack->SwapBytes)) {
+ type, pack->SwapBytes, NULL)) {
goto fallback;
}
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 715d69c0c68..93335aefe6c 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -695,7 +695,7 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims,
* in which case the memcpy-based fast path will likely be used and
* we don't have to blit. */
if (_mesa_format_matches_format_and_type(texImage->TexFormat, format,
- type, unpack->SwapBytes)) {
+ type, unpack->SwapBytes, NULL)) {
goto fallback;
}
@@ -963,7 +963,7 @@ st_GetTexSubImage(struct gl_context * ctx,
/* See if the texture format already matches the format and type,
* in which case the memcpy-based fast path will be used. */
if (_mesa_format_matches_format_and_type(texImage->TexFormat, format,
- type, ctx->Pack.SwapBytes)) {
+ type, ctx->Pack.SwapBytes, NULL)) {
goto fallback;
}
@@ -1071,6 +1071,8 @@ st_GetTexSubImage(struct gl_context * ctx,
/* From now on, we need the gallium representation of dimensions. */
if (gl_target == GL_TEXTURE_1D_ARRAY) {
+ zoffset = yoffset;
+ yoffset = 0;
depth = height;
height = 1;
}
@@ -1114,7 +1116,7 @@ st_GetTexSubImage(struct gl_context * ctx,
/* copy/pack data into user buffer */
if (_mesa_format_matches_format_and_type(mesa_format, format, type,
- ctx->Pack.SwapBytes)) {
+ ctx->Pack.SwapBytes, NULL)) {
/* memcpy */
const uint bytesPerRow = width * util_format_get_blocksize(dst_format);
GLuint row, slice;
@@ -1871,6 +1873,31 @@ st_TextureView(struct gl_context *ctx,
return GL_TRUE;
}
+/* HACK: this is only enough for the most basic uses of CopyImage. Must fix
+ * before actually exposing the extension.
+ */
+static void
+st_CopyImageSubData(struct gl_context *ctx,
+ struct gl_texture_image *src_image,
+ int src_x, int src_y, int src_z,
+ struct gl_texture_image *dst_image,
+ int dst_x, int dst_y, int dst_z,
+ int src_width, int src_height)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_context *pipe = st->pipe;
+ struct st_texture_image *src = st_texture_image(src_image);
+ struct st_texture_image *dst = st_texture_image(dst_image);
+
+ struct pipe_box box;
+
+ u_box_2d_zslice(src_x, src_y, src_z, src_width, src_height, &box);
+ pipe->resource_copy_region(pipe, dst->pt, dst_image->Level,
+ dst_x, dst_y, dst_z,
+ src->pt, src_image->Level,
+ &box);
+}
+
void
st_init_texture_functions(struct dd_function_table *functions)
@@ -1903,4 +1930,6 @@ st_init_texture_functions(struct dd_function_table *functions)
functions->AllocTextureStorage = st_AllocTextureStorage;
functions->TextureView = st_TextureView;
+
+ functions->CopyImageSubData = st_CopyImageSubData;
}
diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
index db7b5b71d66..db74184cff4 100644
--- a/src/mesa/state_tracker/st_format.c
+++ b/src/mesa/state_tracker/st_format.c
@@ -1917,7 +1917,7 @@ st_choose_matching_format(struct st_context *st, unsigned bind,
}
if (_mesa_format_matches_format_and_type(mesa_format, format, type,
- swapBytes)) {
+ swapBytes, NULL)) {
enum pipe_format format =
st_mesa_format_to_pipe_format(st, mesa_format);
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 6f007273c73..cba98819718 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -2816,7 +2816,7 @@ glsl_to_tgsi_visitor::visit(ir_assignment *ir)
*/
glsl_to_tgsi_instruction *inst, *new_inst;
inst = (glsl_to_tgsi_instruction *)this->instructions.get_tail();
- new_inst = emit_asm(ir, inst->op, l, inst->src[0], inst->src[1], inst->src[2]);
+ new_inst = emit_asm(ir, inst->op, l, inst->src[0], inst->src[1], inst->src[2], inst->src[3]);
new_inst->saturate = inst->saturate;
inst->dead_mask = inst->dst[0].writemask;
} else {
@@ -4402,12 +4402,12 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp,
* new visitor. */
foreach_in_list(glsl_to_tgsi_instruction, inst, &original->instructions) {
glsl_to_tgsi_instruction *newinst;
- st_src_reg src_regs[3];
+ st_src_reg src_regs[4];
if (inst->dst[0].file == PROGRAM_OUTPUT)
prog->OutputsWritten |= BITFIELD64_BIT(inst->dst[0].index);
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 4; i++) {
src_regs[i] = inst->src[i];
if (src_regs[i].file == PROGRAM_INPUT &&
src_regs[i].index == VARYING_SLOT_COL0) {
@@ -4418,7 +4418,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp,
prog->InputsRead |= BITFIELD64_BIT(src_regs[i].index);
}
- newinst = v->emit_asm(NULL, inst->op, inst->dst[0], src_regs[0], src_regs[1], src_regs[2]);
+ newinst = v->emit_asm(NULL, inst->op, inst->dst[0], src_regs[0], src_regs[1], src_regs[2], src_regs[3]);
newinst->tex_target = inst->tex_target;
newinst->sampler_array_size = inst->sampler_array_size;
}
@@ -4487,18 +4487,18 @@ get_bitmap_visitor(struct st_fragment_program *fp,
* new visitor. */
foreach_in_list(glsl_to_tgsi_instruction, inst, &original->instructions) {
glsl_to_tgsi_instruction *newinst;
- st_src_reg src_regs[3];
+ st_src_reg src_regs[4];
if (inst->dst[0].file == PROGRAM_OUTPUT)
prog->OutputsWritten |= BITFIELD64_BIT(inst->dst[0].index);
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 4; i++) {
src_regs[i] = inst->src[i];
if (src_regs[i].file == PROGRAM_INPUT)
prog->InputsRead |= BITFIELD64_BIT(src_regs[i].index);
}
- newinst = v->emit_asm(NULL, inst->op, inst->dst[0], src_regs[0], src_regs[1], src_regs[2]);
+ newinst = v->emit_asm(NULL, inst->op, inst->dst[0], src_regs[0], src_regs[1], src_regs[2], src_regs[3]);
newinst->tex_target = inst->tex_target;
newinst->sampler_array_size = inst->sampler_array_size;
}
diff --git a/src/mesa/swrast/s_drawpix.c b/src/mesa/swrast/s_drawpix.c
index dc6827ede9f..5393d50ea02 100644
--- a/src/mesa/swrast/s_drawpix.c
+++ b/src/mesa/swrast/s_drawpix.c
@@ -242,7 +242,7 @@ fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y,
}
if (_mesa_format_matches_format_and_type(rb->Format, format, type,
- ctx->Unpack.SwapBytes)) {
+ ctx->Unpack.SwapBytes, NULL)) {
fast_draw_generic_pixels(ctx, rb, x, y, width, height,
format, type, &unpack, pixels);
return GL_TRUE;
diff --git a/src/util/bitset.h b/src/util/bitset.h
index febcddefd97..c452819414f 100644
--- a/src/util/bitset.h
+++ b/src/util/bitset.h
@@ -96,4 +96,40 @@ __bitset_ffs(const BITSET_WORD *x, int n)
#define BITSET_FFS(x) __bitset_ffs(x, ARRAY_SIZE(x))
+static inline unsigned
+__bitset_next_set(unsigned i, BITSET_WORD *tmp,
+ BITSET_WORD *set, unsigned size)
+{
+ unsigned bit, word;
+
+ /* NOTE: The initial conditions for this function are very specific. At
+ * the start of the loop, the tmp variable must be set to *set and the
+ * initial i value set to 0. This way, if there is a bit set in the first
+ * word, we ignore the i-value and just grab that bit (so 0 is ok, even
+ * though 0 may be returned). If the first word is 0, then the value of
+ * `word` will be 0 and we will go on to look at the second word.
+ */
+ word = BITSET_BITWORD(i);
+ while (*tmp == 0) {
+ word++;
+
+ if (word >= BITSET_WORDS(size))
+ return size;
+
+ *tmp = set[word];
+ }
+
+ /* Find the next set bit in the non-zero word */
+ bit = ffs(*tmp) - 1;
+
+ /* Unset the bit */
+ *tmp &= ~(1ull << bit);
+
+ return word * BITSET_WORDBITS + bit;
+}
+
+#define BITSET_FOREACH_SET(__i, __tmp, __set, __size) \
+ for (__tmp = *(__set), __i = 0; \
+ (__i = __bitset_next_set(__i, &__tmp, __set, __size)) < __size;)
+
#endif
diff --git a/src/util/register_allocate.c b/src/util/register_allocate.c
index 436e008b01a..8af93c0406c 100644
--- a/src/util/register_allocate.c
+++ b/src/util/register_allocate.c
@@ -183,7 +183,7 @@ struct ra_graph {
* using ralloc_free().
*/
struct ra_regs *
-ra_alloc_reg_set(void *mem_ctx, unsigned int count)
+ra_alloc_reg_set(void *mem_ctx, unsigned int count, bool need_conflict_lists)
{
unsigned int i;
struct ra_regs *regs;
@@ -197,9 +197,15 @@ ra_alloc_reg_set(void *mem_ctx, unsigned int count)
BITSET_WORDS(count));
BITSET_SET(regs->regs[i].conflicts, i);
- regs->regs[i].conflict_list = ralloc_array(regs->regs, unsigned int, 4);
- regs->regs[i].conflict_list_size = 4;
- regs->regs[i].conflict_list[0] = i;
+ if (need_conflict_lists) {
+ regs->regs[i].conflict_list = ralloc_array(regs->regs,
+ unsigned int, 4);
+ regs->regs[i].conflict_list_size = 4;
+ regs->regs[i].conflict_list[0] = i;
+ } else {
+ regs->regs[i].conflict_list = NULL;
+ regs->regs[i].conflict_list_size = 0;
+ }
regs->regs[i].num_conflicts = 1;
}
@@ -227,12 +233,14 @@ ra_add_conflict_list(struct ra_regs *regs, unsigned int r1, unsigned int r2)
{
struct ra_reg *reg1 = &regs->regs[r1];
- if (reg1->conflict_list_size == reg1->num_conflicts) {
- reg1->conflict_list_size *= 2;
- reg1->conflict_list = reralloc(regs->regs, reg1->conflict_list,
- unsigned int, reg1->conflict_list_size);
+ if (reg1->conflict_list) {
+ if (reg1->conflict_list_size == reg1->num_conflicts) {
+ reg1->conflict_list_size *= 2;
+ reg1->conflict_list = reralloc(regs->regs, reg1->conflict_list,
+ unsigned int, reg1->conflict_list_size);
+ }
+ reg1->conflict_list[reg1->num_conflicts++] = r2;
}
- reg1->conflict_list[reg1->num_conflicts++] = r2;
BITSET_SET(reg1->conflicts, r2);
}
@@ -255,7 +263,7 @@ ra_add_reg_conflict(struct ra_regs *regs, unsigned int r1, unsigned int r2)
*/
void
ra_add_transitive_reg_conflict(struct ra_regs *regs,
- unsigned int base_reg, unsigned int reg)
+ unsigned int base_reg, unsigned int reg)
{
unsigned int i;
@@ -266,13 +274,37 @@ ra_add_transitive_reg_conflict(struct ra_regs *regs,
}
}
+/**
+ * Makes every conflict on the given register transitive. In other words,
+ * every register that conflicts with r will now conflict with every other
+ * register conflicting with r.
+ *
+ * This can simplify code for setting up multiple register classes
+ * which are aggregates of some base hardware registers, compared to
+ * explicitly using ra_add_reg_conflict.
+ */
+void
+ra_make_reg_conflicts_transitive(struct ra_regs *regs, unsigned int r)
+{
+ struct ra_reg *reg = &regs->regs[r];
+ BITSET_WORD tmp;
+ int c;
+
+ BITSET_FOREACH_SET(c, tmp, reg->conflicts, regs->count) {
+ struct ra_reg *other = &regs->regs[c];
+ unsigned i;
+ for (i = 0; i < BITSET_WORDS(regs->count); i++)
+ other->conflicts[i] |= reg->conflicts[i];
+ }
+}
+
unsigned int
ra_alloc_reg_class(struct ra_regs *regs)
{
struct ra_class *class;
regs->classes = reralloc(regs->regs, regs->classes, struct ra_class *,
- regs->class_count + 1);
+ regs->class_count + 1);
class = rzalloc(regs, struct ra_class);
regs->classes[regs->class_count] = class;
@@ -319,7 +351,7 @@ ra_set_finalize(struct ra_regs *regs, unsigned int **q_values)
for (b = 0; b < regs->class_count; b++) {
for (c = 0; c < regs->class_count; c++) {
regs->classes[b]->q[c] = q_values[b][c];
- }
+ }
}
} else {
/* Compute, for each class B and C, how many regs of B an
@@ -410,14 +442,14 @@ ra_alloc_interference_graph(struct ra_regs *regs, unsigned int count)
void
ra_set_node_class(struct ra_graph *g,
- unsigned int n, unsigned int class)
+ unsigned int n, unsigned int class)
{
g->nodes[n].class = class;
}
void
ra_add_node_interference(struct ra_graph *g,
- unsigned int n1, unsigned int n2)
+ unsigned int n1, unsigned int n2)
{
if (!BITSET_TEST(g->nodes[n1].adjacency, n2)) {
ra_add_node_adjacency(g, n1, n2);
@@ -445,7 +477,7 @@ decrement_q(struct ra_graph *g, unsigned int n)
if (n != n2 && !g->nodes[n2].in_stack) {
assert(g->nodes[n2].q_total >= g->regs->classes[n2_class]->q[n_class]);
- g->nodes[n2].q_total -= g->regs->classes[n2_class]->q[n_class];
+ g->nodes[n2].q_total -= g->regs->classes[n2_class]->q[n_class];
}
}
}
diff --git a/src/util/register_allocate.h b/src/util/register_allocate.h
index 61f182eff49..628d2bbbced 100644
--- a/src/util/register_allocate.h
+++ b/src/util/register_allocate.h
@@ -44,13 +44,15 @@ struct ra_regs;
* registers, such as aligned register pairs that conflict with the
* two real registers from which they are composed.
*/
-struct ra_regs *ra_alloc_reg_set(void *mem_ctx, unsigned int count);
+struct ra_regs *ra_alloc_reg_set(void *mem_ctx, unsigned int count,
+ bool need_conflict_lists);
void ra_set_allocate_round_robin(struct ra_regs *regs);
unsigned int ra_alloc_reg_class(struct ra_regs *regs);
void ra_add_reg_conflict(struct ra_regs *regs,
unsigned int r1, unsigned int r2);
void ra_add_transitive_reg_conflict(struct ra_regs *regs,
unsigned int base_reg, unsigned int reg);
+void ra_make_reg_conflicts_transitive(struct ra_regs *regs, unsigned int reg);
void ra_class_add_reg(struct ra_regs *regs, unsigned int c, unsigned int reg);
void ra_set_num_conflicts(struct ra_regs *regs, unsigned int class_a,
unsigned int class_b, unsigned int num_conflicts);
diff --git a/src/util/rounding.h b/src/util/rounding.h
index 7b5608b8a78..afb38fbdb56 100644
--- a/src/util/rounding.h
+++ b/src/util/rounding.h
@@ -24,9 +24,8 @@
#ifndef _ROUNDING_H
#define _ROUNDING_H
-#include "c99_compat.h" // inline
+#include "c99_math.h"
-#include <math.h>
#include <limits.h>
#include <stdint.h>
diff --git a/src/vulkan/anv_compiler.cpp b/src/vulkan/anv_compiler.cpp
index 2dbf59f991e..4cbf98afa1e 100644
--- a/src/vulkan/anv_compiler.cpp
+++ b/src/vulkan/anv_compiler.cpp
@@ -1007,7 +1007,7 @@ anv_compile_shader_spirv(struct anv_compiler *compiler,
mesa_shader->Program->nir =
spirv_to_nir((uint32_t *)shader->module->data, shader->module->size / 4,
- glsl_options->NirOptions);
+ stage_info[stage].stage, glsl_options->NirOptions);
nir_validate_shader(mesa_shader->Program->nir);
brw_process_nir(mesa_shader->Program->nir,