mirror of
https://github.com/elwrcl/intel-hard-graphics.git
synced 2026-10-31 02:48:03 +03:00
wip: crocus/rusticl/elk/hasvk local changes before h264 cherry-pick
This commit is contained in:
35 files changed
+1177
-191
No files matched your search
Generated
+27
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1784007870,
|
||||||
|
"narHash": "sha256-djcLt/JJphyNt4eDY9XTly+/WbCK5lqWq9lSgCmJkkQ=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "18b9261cb3294b6d2a06d03f96872827b8fe2698",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
@@ -1,58 +1,200 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
description = "intel-hard-graphics / clvk development";
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs =
|
outputs =
|
||||||
|
{ self, nixpkgs }:
|
||||||
|
let
|
||||||
|
system = "x86_64-linux";
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
|
||||||
|
# HD 4000 (Gen7) PCI ID: 8086:0166
|
||||||
|
pciId = "8086:0166";
|
||||||
|
defaultClvkBuildDir = "/home/elars/ProjectsHDD/Drivers/clvk/build";
|
||||||
|
|
||||||
|
commonBuildInputs = with pkgs; [
|
||||||
|
llvmPackages_21.clang-unwrapped
|
||||||
|
llvmPackages_21.llvm.dev
|
||||||
|
llvmPackages_21.libclang
|
||||||
|
llvmPackages_21.bintools
|
||||||
|
python3Packages.packaging
|
||||||
|
python3Packages.pyyaml
|
||||||
|
python3Packages.mako
|
||||||
|
python3
|
||||||
|
cargo
|
||||||
|
meson
|
||||||
|
ninja
|
||||||
|
pkg-config
|
||||||
|
spirv-llvm-translator
|
||||||
|
spirv-tools
|
||||||
|
rust-bindgen
|
||||||
|
rustc
|
||||||
|
vkmark
|
||||||
|
vulkan-headers
|
||||||
|
vulkan-loader
|
||||||
|
vulkan-tools
|
||||||
|
shaderc
|
||||||
|
libpciaccess
|
||||||
|
opencl-headers
|
||||||
|
libclc
|
||||||
|
bison
|
||||||
|
flex
|
||||||
|
libdrm
|
||||||
|
libelf
|
||||||
|
expat
|
||||||
|
zlib
|
||||||
|
zstd
|
||||||
|
libx11
|
||||||
|
ocl-icd
|
||||||
|
libxcb
|
||||||
|
cmake
|
||||||
|
libxext
|
||||||
|
libxfixes
|
||||||
|
libxrandr
|
||||||
|
libxshmfence
|
||||||
|
wayland
|
||||||
|
wayland-protocols
|
||||||
|
wayland-scanner
|
||||||
|
xorgproto
|
||||||
|
xorg.libXxf86vm
|
||||||
|
xorg.xcbutilkeysyms
|
||||||
|
(python3.withPackages (
|
||||||
|
ps: with ps; [
|
||||||
|
pyopencl
|
||||||
|
opencv4
|
||||||
|
numpy
|
||||||
|
]
|
||||||
|
))
|
||||||
|
clinfo
|
||||||
|
strace
|
||||||
|
clpeak
|
||||||
|
pocl
|
||||||
|
gdb
|
||||||
|
];
|
||||||
|
|
||||||
|
commonShellVars = ''
|
||||||
|
export LIBRARY_PATH=${pkgs.llvmPackages_21.clang-unwrapped.lib}/lib:$LIBRARY_PATH
|
||||||
|
export LIBCLANG_PATH=${pkgs.llvmPackages_21.libclang.lib}/lib
|
||||||
|
export BINDGEN_EXTRA_CLANG_ARGS="-I${pkgs.llvmPackages_21.clang-unwrapped}/lib/clang/21/include"
|
||||||
|
export C_INCLUDE_PATH=${pkgs.opencl-headers}/include:$C_INCLUDE_PATH
|
||||||
|
export LIBRARY_PATH=${pkgs.ocl-icd}/lib:$LIBRARY_PATH
|
||||||
|
export LD_LIBRARY_PATH="${pkgs.vulkan-loader}/lib:$LD_LIBRARY_PATH"
|
||||||
|
'';
|
||||||
|
|
||||||
|
# 32-bit (i686) build için: L4D2 gibi 32-bit oyunlarla test amaçlı.
|
||||||
|
# clvk/rusticl/OpenCL burada yok — sadece hasvk (vulkan_hasvk) + crocus
|
||||||
|
# için gereken Vulkan/GL/WSI kütüphaneleri, i686 varyantlarıyla.
|
||||||
|
pkgs32 = pkgs.pkgsi686Linux;
|
||||||
|
|
||||||
|
i686BuildInputs = with pkgs32; [
|
||||||
|
libdrm
|
||||||
|
libelf
|
||||||
|
libpciaccess
|
||||||
|
expat
|
||||||
|
zlib
|
||||||
|
zstd
|
||||||
|
libx11
|
||||||
|
libxcb
|
||||||
|
libxext
|
||||||
|
libxfixes
|
||||||
|
libxrandr
|
||||||
|
libxshmfence
|
||||||
|
wayland
|
||||||
|
wayland-protocols
|
||||||
|
xorgproto
|
||||||
|
xorg.libXxf86vm
|
||||||
|
xorg.xcbutilkeysyms
|
||||||
|
vulkan-headers
|
||||||
|
vulkan-loader
|
||||||
|
llvmPackages_21.llvm.dev
|
||||||
|
llvmPackages_21.clang-unwrapped
|
||||||
|
llvmPackages_21.libclang
|
||||||
|
spirv-llvm-translator
|
||||||
|
spirv-tools
|
||||||
|
libclc
|
||||||
|
# crocus + hasvk (with_driver_using_cl) libclc'ye hard-dependency,
|
||||||
|
# rusticl/opencl kapalı olsa bile gerekiyor
|
||||||
|
];
|
||||||
|
|
||||||
|
# Build araçları (meson/ninja/python/bison/flex/pkg-config vs.) i686'da
|
||||||
|
# da bulunur ama host mimarisinde çalıştırılmaları yeterli; yine de
|
||||||
|
# pkgsi686Linux'tan almak pkg-config'in .pc arama yollarını tutarlı
|
||||||
|
# tutar. cmake/rust burada gerekmiyor (clvk 32-bit hedefi değil).
|
||||||
|
i686NativeBuildInputs = with pkgs32; [
|
||||||
|
meson
|
||||||
|
ninja
|
||||||
|
pkg-config
|
||||||
|
python3
|
||||||
|
python3Packages.packaging
|
||||||
|
python3Packages.pyyaml
|
||||||
|
python3Packages.mako
|
||||||
|
bison
|
||||||
|
flex
|
||||||
|
wayland-scanner
|
||||||
|
];
|
||||||
|
in
|
||||||
{
|
{
|
||||||
self,
|
devShells.${system} = {
|
||||||
nixpkgs,
|
# nix develop = intel-hard-graphics shell
|
||||||
flake-utils,
|
default = pkgs.mkShell {
|
||||||
}:
|
buildInputs = commonBuildInputs;
|
||||||
flake-utils.lib.eachDefaultSystem (
|
|
||||||
system:
|
|
||||||
let
|
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
|
||||||
llvmPkgs = pkgs.llvmPackages_19;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
devShells.default = pkgs.mkShell {
|
|
||||||
name = "mesa-crocus-opencl";
|
|
||||||
|
|
||||||
packages = with pkgs; [
|
|
||||||
# build tools
|
|
||||||
meson
|
|
||||||
ninja
|
|
||||||
pkg-config
|
|
||||||
cmake
|
|
||||||
python3
|
|
||||||
python3Packages.packaging
|
|
||||||
|
|
||||||
# LLVM stack
|
|
||||||
llvmPkgs.llvm.dev
|
|
||||||
llvmPkgs.clang
|
|
||||||
llvmPkgs.libclc
|
|
||||||
|
|
||||||
# Rust
|
|
||||||
rust-bindgen
|
|
||||||
rustc
|
|
||||||
cargo
|
|
||||||
|
|
||||||
# Mesa deps
|
|
||||||
libdrm
|
|
||||||
expat
|
|
||||||
zlib
|
|
||||||
zstd
|
|
||||||
glslang
|
|
||||||
libffi
|
|
||||||
elfutils
|
|
||||||
];
|
|
||||||
|
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
export PKG_CONFIG_PATH=${pkgs.llvmPackages_19.libclc}/share/pkgconfig:$PKG_CONFIG_PATH
|
${commonShellVars}
|
||||||
|
export LD_LIBRARY_PATH=$PWD/build/src/gallium/targets/rusticl:$LD_LIBRARY_PATH
|
||||||
|
export RUSTICL_ENABLE=crocus
|
||||||
|
|
||||||
|
mkdir -p $PWD/.icd-vendors
|
||||||
|
ln -sf $PWD/build/src/gallium/targets/rusticl/rusticl.icd $PWD/.icd-vendors/rusticl.icd
|
||||||
|
ln -sf ${pkgs.pocl}/etc/OpenCL/vendors/pocl.icd $PWD/.icd-vendors/pocl.icd
|
||||||
|
export OCL_ICD_VENDORS=$PWD/.icd-vendors
|
||||||
|
|
||||||
|
echo "=== intel-hard-graphics ==="
|
||||||
|
echo "OCL_ICD_VENDORS=$OCL_ICD_VENDORS"
|
||||||
|
echo "RUSTICL_ENABLE=$RUSTICL_ENABLE"
|
||||||
|
echo ""
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
# nix develop .#clvk = clvk shell
|
||||||
);
|
clvk = pkgs.mkShell {
|
||||||
|
buildInputs = commonBuildInputs;
|
||||||
|
shellHook = ''
|
||||||
|
${commonShellVars}
|
||||||
|
|
||||||
|
CLVK_BUILD_DIR="''${CLVK_BUILD_DIR:-${defaultClvkBuildDir}}"
|
||||||
|
|
||||||
|
if [ ! -d "$CLVK_BUILD_DIR" ]; then
|
||||||
|
echo "UYARI: clvk build dizini bulunamadi: $CLVK_BUILD_DIR"
|
||||||
|
echo "CLVK_BUILD_DIR ortam degiskeniyle dogru yolu ver, ornek:"
|
||||||
|
echo " CLVK_BUILD_DIR=/gercek/yol nix develop .#clvk"
|
||||||
|
else
|
||||||
|
export LD_LIBRARY_PATH="$CLVK_BUILD_DIR:$LD_LIBRARY_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
export MESA_VK_DEVICE_SELECT="${pciId}"
|
||||||
|
|
||||||
|
echo "=== clvk ==="
|
||||||
|
echo "CLVK_BUILD_DIR=$CLVK_BUILD_DIR"
|
||||||
|
echo "MESA_VK_DEVICE_SELECT=$MESA_VK_DEVICE_SELECT"
|
||||||
|
echo ""
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
# nix develop .#i686 = 32-bit hasvk/crocus build shell (L4D2 testi için)
|
||||||
|
i686 = pkgs32.mkShell {
|
||||||
|
buildInputs = i686BuildInputs;
|
||||||
|
nativeBuildInputs = i686NativeBuildInputs;
|
||||||
|
shellHook = ''
|
||||||
|
export MESA_VK_DEVICE_SELECT="${pciId}"
|
||||||
|
|
||||||
|
echo "=== intel-hard-graphics (i686 / 32-bit) ==="
|
||||||
|
echo "CC=$CC"
|
||||||
|
echo "meson setup build32 --buildtype=debugoptimized \\"
|
||||||
|
echo " -Dgallium-drivers=crocus -Dvulkan-drivers=intel_hasvk \\"
|
||||||
|
echo " -Dplatforms=x11 -Degl=disabled -Dglx=disabled -Dgbm=disabled \\"
|
||||||
|
echo " -Dopengl=false -Dgles1=disabled -Dgles2=disabled \\"
|
||||||
|
echo " -Dgallium-rusticl=false -Dmicrosoft-clc=disabled -Dllvm=enabled"
|
||||||
|
echo ""
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -301,7 +301,7 @@ ensure_exec_obj_space(struct crocus_batch *batch, uint32_t count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct drm_i915_gem_exec_object2 *
|
struct drm_i915_gem_exec_object2 *
|
||||||
crocus_use_bo(struct crocus_batch *batch, struct crocus_bo *bo, bool writable)
|
crocus_use_bo(struct crocus_batch *batch, struct crocus_bo *bo, bool writable)
|
||||||
{
|
{
|
||||||
assert(bo->bufmgr == batch->command.bo->bufmgr);
|
assert(bo->bufmgr == batch->command.bo->bufmgr);
|
||||||
@@ -458,7 +458,10 @@ recreate_growing_buffer(struct crocus_batch *batch,
|
|||||||
struct crocus_screen *screen = batch->screen;
|
struct crocus_screen *screen = batch->screen;
|
||||||
struct crocus_bufmgr *bufmgr = screen->bufmgr;
|
struct crocus_bufmgr *bufmgr = screen->bufmgr;
|
||||||
grow->bo = crocus_bo_alloc(bufmgr, name, size);
|
grow->bo = crocus_bo_alloc(bufmgr, name, size);
|
||||||
grow->bo->kflags |= EXEC_OBJECT_CAPTURE;
|
static uint64_t next_grow_pin = 0x20000000ULL; /* 512MB */
|
||||||
|
grow->bo->gtt_offset = next_grow_pin;
|
||||||
|
next_grow_pin += align64(size, 4096);
|
||||||
|
grow->bo->kflags |= EXEC_OBJECT_CAPTURE | EXEC_OBJECT_PINNED;
|
||||||
grow->partial_bo = NULL;
|
grow->partial_bo = NULL;
|
||||||
grow->partial_bo_map = NULL;
|
grow->partial_bo_map = NULL;
|
||||||
grow->partial_bytes = 0;
|
grow->partial_bytes = 0;
|
||||||
@@ -903,8 +906,9 @@ submit_batch(struct crocus_batch *batch)
|
|||||||
DBG("BO %d migrated: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
|
DBG("BO %d migrated: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
|
||||||
bo->gem_handle, bo->gtt_offset,
|
bo->gem_handle, bo->gtt_offset,
|
||||||
(uint64_t)batch->validation_list[i].offset);
|
(uint64_t)batch->validation_list[i].offset);
|
||||||
assert(!(bo->kflags & EXEC_OBJECT_PINNED));
|
if (!(bo->kflags & EXEC_OBJECT_PINNED)) {
|
||||||
bo->gtt_offset = batch->validation_list[i].offset;
|
bo->gtt_offset = batch->validation_list[i].offset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ bool crocus_batch_prepare_noop(struct crocus_batch *batch, bool noop_enable);
|
|||||||
/* Inverted meaning, but using the same bit...emit_reloc will flip it. */
|
/* Inverted meaning, but using the same bit...emit_reloc will flip it. */
|
||||||
#define RELOC_32BIT EXEC_OBJECT_SUPPORTS_48B_ADDRESS
|
#define RELOC_32BIT EXEC_OBJECT_SUPPORTS_48B_ADDRESS
|
||||||
|
|
||||||
|
struct drm_i915_gem_exec_object2 *crocus_use_bo(struct crocus_batch *batch, struct crocus_bo *bo, bool writable);
|
||||||
void crocus_use_pinned_bo(struct crocus_batch *batch, struct crocus_bo *bo,
|
void crocus_use_pinned_bo(struct crocus_batch *batch, struct crocus_bo *bo,
|
||||||
bool writable);
|
bool writable);
|
||||||
uint64_t crocus_command_reloc(struct crocus_batch *batch, uint32_t batch_offset,
|
uint64_t crocus_command_reloc(struct crocus_batch *batch, uint32_t batch_offset,
|
||||||
|
|||||||
@@ -339,6 +339,7 @@ enum crocus_surface_group {
|
|||||||
CROCUS_SURFACE_GROUP_IMAGE,
|
CROCUS_SURFACE_GROUP_IMAGE,
|
||||||
CROCUS_SURFACE_GROUP_UBO,
|
CROCUS_SURFACE_GROUP_UBO,
|
||||||
CROCUS_SURFACE_GROUP_SSBO,
|
CROCUS_SURFACE_GROUP_SSBO,
|
||||||
|
CROCUS_SURFACE_GROUP_GLOBAL,
|
||||||
|
|
||||||
CROCUS_SURFACE_GROUP_COUNT,
|
CROCUS_SURFACE_GROUP_COUNT,
|
||||||
};
|
};
|
||||||
@@ -608,6 +609,7 @@ struct crocus_context {
|
|||||||
struct crocus_state_ref grid_size;
|
struct crocus_state_ref grid_size;
|
||||||
/** Global bindings for compute */
|
/** Global bindings for compute */
|
||||||
struct pipe_resource *global_bindings[CROCUS_MAX_GLOBAL_BINDINGS];
|
struct pipe_resource *global_bindings[CROCUS_MAX_GLOBAL_BINDINGS];
|
||||||
|
uint32_t *global_binding_handles[CROCUS_MAX_GLOBAL_BINDINGS];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of aux usages for drawing, altered to account for any
|
* Array of aux usages for drawing, altered to account for any
|
||||||
|
|||||||
@@ -517,9 +517,16 @@ crocus_launch_grid(struct pipe_context *ctx, const struct pipe_grid_info *grid)
|
|||||||
|
|
||||||
crocus_handle_always_flush_cache(batch);
|
crocus_handle_always_flush_cache(batch);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < CROCUS_MAX_GLOBAL_BINDINGS; i++) {
|
||||||
|
if (ice->state.global_bindings[i]) {
|
||||||
|
struct crocus_resource *res = (struct crocus_resource *)ice->state.global_bindings[i];
|
||||||
|
crocus_use_bo(batch, res->bo, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
screen->vtbl.upload_compute_state(ice, batch, grid);
|
screen->vtbl.upload_compute_state(ice, batch, grid);
|
||||||
|
|
||||||
crocus_handle_always_flush_cache(batch);
|
crocus_flush_all_caches(batch);
|
||||||
|
|
||||||
ice->state.dirty &= ~CROCUS_ALL_DIRTY_FOR_COMPUTE;
|
ice->state.dirty &= ~CROCUS_ALL_DIRTY_FOR_COMPUTE;
|
||||||
ice->state.stage_dirty &= ~CROCUS_ALL_STAGE_DIRTY_FOR_COMPUTE;
|
ice->state.stage_dirty &= ~CROCUS_ALL_STAGE_DIRTY_FOR_COMPUTE;
|
||||||
|
|||||||
@@ -509,10 +509,18 @@ crocus_is_format_supported(struct pipe_screen *pscreen,
|
|||||||
/* Dataport doesn't support compression, and we can't resolve an MCS
|
/* Dataport doesn't support compression, and we can't resolve an MCS
|
||||||
* compressed surface. (Buffer images may have sample count of 0.)
|
* compressed surface. (Buffer images may have sample count of 0.)
|
||||||
*/
|
*/
|
||||||
supported &= sample_count == 0;
|
bool sc_ok = sample_count == 0;
|
||||||
|
bool tw_ok = isl_format_supports_typed_writes(devinfo, format);
|
||||||
|
bool ts_ok = isl_has_matching_typed_storage_image_format(devinfo, format);
|
||||||
|
supported &= sc_ok && tw_ok && ts_ok;
|
||||||
|
|
||||||
supported &= isl_format_supports_typed_writes(devinfo, format);
|
FILE *dbgf = fopen("/tmp/crocus_debug.log", "a");
|
||||||
supported &= isl_has_matching_typed_storage_image_format(devinfo, format);
|
if (dbgf) {
|
||||||
|
fprintf(dbgf, "CROCUS_DBG: shader_image check pformat=%d target=%d sample_count=%u "
|
||||||
|
"isl_format=%d sc_ok=%d tw_ok=%d ts_ok=%d supported=%d\n",
|
||||||
|
pformat, target, sample_count, format, sc_ok, tw_ok, ts_ok, supported);
|
||||||
|
fclose(dbgf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usage & PIPE_BIND_SAMPLER_VIEW) {
|
if (usage & PIPE_BIND_SAMPLER_VIEW) {
|
||||||
|
|||||||
@@ -714,6 +714,7 @@ static const char *surface_group_names[] = {
|
|||||||
[CROCUS_SURFACE_GROUP_UBO] = "ubo",
|
[CROCUS_SURFACE_GROUP_UBO] = "ubo",
|
||||||
[CROCUS_SURFACE_GROUP_SSBO] = "ssbo",
|
[CROCUS_SURFACE_GROUP_SSBO] = "ssbo",
|
||||||
[CROCUS_SURFACE_GROUP_IMAGE] = "image",
|
[CROCUS_SURFACE_GROUP_IMAGE] = "image",
|
||||||
|
[CROCUS_SURFACE_GROUP_GLOBAL] = "global (IVB)",
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -842,7 +843,8 @@ crocus_setup_binding_table(const struct intel_device_info *devinfo,
|
|||||||
bt->used_mask[CROCUS_SURFACE_GROUP_RENDER_TARGET_READ] =
|
bt->used_mask[CROCUS_SURFACE_GROUP_RENDER_TARGET_READ] =
|
||||||
BITFIELD64_MASK(num_render_targets);
|
BITFIELD64_MASK(num_render_targets);
|
||||||
}
|
}
|
||||||
} else if (info->stage == MESA_SHADER_COMPUTE) {
|
} else if (info->stage == MESA_SHADER_COMPUTE ||
|
||||||
|
info->stage == MESA_SHADER_KERNEL) {
|
||||||
bt->sizes[CROCUS_SURFACE_GROUP_CS_WORK_GROUPS] = 1;
|
bt->sizes[CROCUS_SURFACE_GROUP_CS_WORK_GROUPS] = 1;
|
||||||
} else if (info->stage == MESA_SHADER_GEOMETRY) {
|
} else if (info->stage == MESA_SHADER_GEOMETRY) {
|
||||||
/* In gfx6 we reserve the first ELK_MAX_SOL_BINDINGS entries for transform
|
/* In gfx6 we reserve the first ELK_MAX_SOL_BINDINGS entries for transform
|
||||||
@@ -2504,6 +2506,335 @@ crocus_update_compiled_shaders(struct crocus_context *ice)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* IVB Gen7 doesn't support stateless global memory access (BTI 255 is only
|
||||||
|
* valid on Haswell+ / Gen7.5+). Instead of a dedicated global-memory BTI
|
||||||
|
* (limited to 64 slots, and unable to distinguish multiple __global buffer
|
||||||
|
* arguments since their kernel_input handles all resolve to address 0),
|
||||||
|
* redirect every load_global/store_global to load_ssbo/store_ssbo.
|
||||||
|
*
|
||||||
|
* The address of a global access is always kernel_input UBO offset N
|
||||||
|
* (optionally + a relative offset expression). N corresponds 1:1, in
|
||||||
|
* increasing order, to rusticl's start_slot ordering in
|
||||||
|
* crocus_set_global_binding() -- both are "the Nth __global buffer
|
||||||
|
* argument that's actually used", skipping dead/scalar arguments. So we
|
||||||
|
* assign SSBO index = rank of N among all distinct offsets seen.
|
||||||
|
*/
|
||||||
|
/* Pass 1 helper: find N in load_ubo(0,N), without building any new
|
||||||
|
* instructions (safe to call speculatively during discovery). Handles
|
||||||
|
* arbitrarily nested iadd chains, e.g. iadd(iadd(load_ubo(0,N), i*8), 4)
|
||||||
|
* which occurs for struct field access (out[i].b). */
|
||||||
|
/* Recursively determines whether following iadd chains from `def`
|
||||||
|
* eventually reaches a load_ubo intrinsic. Unlike a shallow type check,
|
||||||
|
* this actually walks the chain so mul/bcsel/etc. on the *other* branch
|
||||||
|
* don't cause a false positive. */
|
||||||
|
static bool
|
||||||
|
crocus_def_leads_to_ubo(nir_def *def)
|
||||||
|
{
|
||||||
|
nir_instr *instr = nir_def_instr(def);
|
||||||
|
|
||||||
|
if (instr->type == nir_instr_type_intrinsic &&
|
||||||
|
nir_instr_as_intrinsic(instr)->intrinsic == nir_intrinsic_load_ubo)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (instr->type == nir_instr_type_phi) {
|
||||||
|
nir_phi_instr *phi = nir_instr_as_phi(instr);
|
||||||
|
nir_foreach_phi_src(phi_src, phi) {
|
||||||
|
if (!crocus_def_leads_to_ubo(phi_src->src.ssa))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instr->type != nir_instr_type_alu)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nir_alu_instr *alu = nir_instr_as_alu(instr);
|
||||||
|
if (alu->op != nir_op_iadd)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nir_def *lhs = alu->src[0].src.ssa;
|
||||||
|
nir_def *rhs = alu->src[1].src.ssa;
|
||||||
|
|
||||||
|
return crocus_def_leads_to_ubo(lhs) || crocus_def_leads_to_ubo(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
crocus_global_addr_find_ubo_offset(nir_src *addr_src, uint32_t *out_offset)
|
||||||
|
{
|
||||||
|
nir_def *cur = addr_src->ssa;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (nir_def_instr(cur)->type == nir_instr_type_intrinsic &&
|
||||||
|
nir_instr_as_intrinsic(nir_def_instr(cur))->intrinsic ==
|
||||||
|
nir_intrinsic_load_ubo) {
|
||||||
|
nir_intrinsic_instr *ld_ubo = nir_instr_as_intrinsic(nir_def_instr(cur));
|
||||||
|
if (!nir_src_is_const(ld_ubo->src[1]))
|
||||||
|
return false;
|
||||||
|
*out_offset = nir_src_as_uint(ld_ubo->src[1]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Control-flow merge: all phi sources must resolve to the
|
||||||
|
* same underlying UBO offset (i.e. the same buffer), only
|
||||||
|
* the runtime-computed relative offset may differ per branch. */
|
||||||
|
if (nir_def_instr(cur)->type == nir_instr_type_phi) {
|
||||||
|
nir_phi_instr *phi = nir_instr_as_phi(nir_def_instr(cur));
|
||||||
|
uint32_t phi_off;
|
||||||
|
bool first = true;
|
||||||
|
nir_foreach_phi_src(phi_src, phi) {
|
||||||
|
uint32_t src_off;
|
||||||
|
if (!crocus_global_addr_find_ubo_offset(&phi_src->src, &src_off))
|
||||||
|
return false;
|
||||||
|
if (first) {
|
||||||
|
phi_off = src_off;
|
||||||
|
first = false;
|
||||||
|
} else if (src_off != phi_off) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out_offset = phi_off;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nir_def_instr(cur)->type != nir_instr_type_alu)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nir_alu_instr *alu = nir_instr_as_alu(nir_def_instr(cur));
|
||||||
|
if (alu->op != nir_op_iadd)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nir_def *lhs = alu->src[0].src.ssa;
|
||||||
|
nir_def *rhs = alu->src[1].src.ssa;
|
||||||
|
|
||||||
|
if (crocus_def_leads_to_ubo(lhs))
|
||||||
|
cur = lhs;
|
||||||
|
else if (crocus_def_leads_to_ubo(rhs))
|
||||||
|
cur = rhs;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pass 2 helper: rebuild the full relative offset expression (sum of
|
||||||
|
* everything peeled off while descending to the load_ubo leaf). Must
|
||||||
|
* only be called with b.cursor already positioned before the real
|
||||||
|
* instruction being rewritten. */
|
||||||
|
static nir_def *
|
||||||
|
crocus_global_addr_build_rel_offset(nir_builder *b, nir_src *addr_src)
|
||||||
|
{
|
||||||
|
nir_def *cur = addr_src->ssa;
|
||||||
|
nir_def *sum = NULL;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (nir_def_instr(cur)->type == nir_instr_type_intrinsic &&
|
||||||
|
nir_instr_as_intrinsic(nir_def_instr(cur))->intrinsic ==
|
||||||
|
nir_intrinsic_load_ubo) {
|
||||||
|
return sum ? sum : nir_imm_int(b, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nir_def_instr(cur)->type == nir_instr_type_phi) {
|
||||||
|
nir_phi_instr *phi = nir_instr_as_phi(nir_def_instr(cur));
|
||||||
|
nir_phi_instr *new_phi = nir_phi_instr_create(b->shader);
|
||||||
|
nir_def_init(&new_phi->instr, &new_phi->def, 1, 32);
|
||||||
|
|
||||||
|
nir_foreach_phi_src(phi_src, phi) {
|
||||||
|
nir_builder pb = *b;
|
||||||
|
pb.cursor = nir_after_block_before_jump(phi_src->pred);
|
||||||
|
nir_def *branch_off =
|
||||||
|
crocus_global_addr_build_rel_offset(&pb, &phi_src->src);
|
||||||
|
nir_phi_instr_add_src(new_phi, phi_src->pred, branch_off);
|
||||||
|
}
|
||||||
|
|
||||||
|
nir_instr_insert_before(&phi->instr, &new_phi->instr);
|
||||||
|
nir_def *phi_result = &new_phi->def;
|
||||||
|
return sum ? nir_iadd(b, sum, phi_result) : phi_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nir_alu_instr *alu = nir_instr_as_alu(nir_def_instr(cur));
|
||||||
|
nir_def *lhs = alu->src[0].src.ssa;
|
||||||
|
nir_def *rhs = alu->src[1].src.ssa;
|
||||||
|
|
||||||
|
bool follow_lhs = crocus_def_leads_to_ubo(lhs);
|
||||||
|
nir_def *peeled = follow_lhs ? rhs : lhs;
|
||||||
|
sum = sum ? nir_iadd(b, sum, peeled) : peeled;
|
||||||
|
cur = follow_lhs ? lhs : rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
crocus_lower_cs_global_to_ssbo(nir_shader *nir)
|
||||||
|
{
|
||||||
|
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
|
||||||
|
|
||||||
|
uint32_t offsets[64];
|
||||||
|
unsigned num_offsets = 0;
|
||||||
|
|
||||||
|
/* Pass 1: discover every distinct kernel_input offset used as a
|
||||||
|
* load_global/store_global base. */
|
||||||
|
nir_foreach_block(block, impl) {
|
||||||
|
nir_foreach_instr(instr, block) {
|
||||||
|
if (instr->type != nir_instr_type_intrinsic)
|
||||||
|
continue;
|
||||||
|
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
|
||||||
|
|
||||||
|
nir_src *addr_src;
|
||||||
|
switch (intrin->intrinsic) {
|
||||||
|
case nir_intrinsic_load_global:
|
||||||
|
case nir_intrinsic_load_global_constant:
|
||||||
|
addr_src = &intrin->src[0];
|
||||||
|
break;
|
||||||
|
case nir_intrinsic_store_global:
|
||||||
|
addr_src = &intrin->src[1];
|
||||||
|
break;
|
||||||
|
case nir_intrinsic_global_atomic:
|
||||||
|
case nir_intrinsic_global_atomic_swap:
|
||||||
|
addr_src = &intrin->src[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t off;
|
||||||
|
if (!crocus_global_addr_find_ubo_offset(addr_src, &off)) {
|
||||||
|
fprintf(stderr, "=== UNRECOGNIZED GLOBAL PATTERN (intrinsic: %s) ===\n",
|
||||||
|
nir_intrinsic_infos[intrin->intrinsic].name);
|
||||||
|
nir_print_instr(&intrin->instr, stderr);
|
||||||
|
fprintf(stderr, "\n--- addr_src def ---\n");
|
||||||
|
nir_print_instr(nir_def_instr(addr_src->ssa), stderr);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fflush(stderr);
|
||||||
|
assert(!"crocus: unrecognized __global address pattern on IVB");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (unsigned i = 0; i < num_offsets; i++) {
|
||||||
|
if (offsets[i] == off) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
assert(num_offsets < ARRAY_SIZE(offsets));
|
||||||
|
offsets[num_offsets++] = off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_offsets == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Sort ascending: SSBO index = rank, matching rusticl's start_slot order */
|
||||||
|
for (unsigned i = 1; i < num_offsets; i++) {
|
||||||
|
uint32_t key = offsets[i];
|
||||||
|
int j = i - 1;
|
||||||
|
while (j >= 0 && offsets[j] > key) {
|
||||||
|
offsets[j + 1] = offsets[j];
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
offsets[j + 1] = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pass 2: rewrite load_global/store_global -> load_ssbo/store_ssbo */
|
||||||
|
nir_builder b = nir_builder_create(impl);
|
||||||
|
|
||||||
|
nir_foreach_block_safe(block, impl) {
|
||||||
|
nir_foreach_instr_safe(instr, block) {
|
||||||
|
if (instr->type != nir_instr_type_intrinsic)
|
||||||
|
continue;
|
||||||
|
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
|
||||||
|
|
||||||
|
nir_src *addr_src;
|
||||||
|
enum { OP_LOAD, OP_STORE, OP_ATOMIC, OP_ATOMIC_SWAP } kind;
|
||||||
|
|
||||||
|
switch (intrin->intrinsic) {
|
||||||
|
case nir_intrinsic_load_global:
|
||||||
|
case nir_intrinsic_load_global_constant:
|
||||||
|
kind = OP_LOAD;
|
||||||
|
addr_src = &intrin->src[0];
|
||||||
|
break;
|
||||||
|
case nir_intrinsic_store_global:
|
||||||
|
kind = OP_STORE;
|
||||||
|
addr_src = &intrin->src[1];
|
||||||
|
break;
|
||||||
|
case nir_intrinsic_global_atomic:
|
||||||
|
kind = OP_ATOMIC;
|
||||||
|
addr_src = &intrin->src[0];
|
||||||
|
break;
|
||||||
|
case nir_intrinsic_global_atomic_swap:
|
||||||
|
kind = OP_ATOMIC_SWAP;
|
||||||
|
addr_src = &intrin->src[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
b.cursor = nir_before_instr(instr);
|
||||||
|
|
||||||
|
uint32_t off;
|
||||||
|
if (!crocus_global_addr_find_ubo_offset(addr_src, &off))
|
||||||
|
assert(!"crocus: unrecognized __global address pattern on IVB");
|
||||||
|
|
||||||
|
nir_def *rel = crocus_global_addr_build_rel_offset(&b, addr_src);
|
||||||
|
|
||||||
|
unsigned ssbo_idx = 0;
|
||||||
|
bool found = false;
|
||||||
|
for (unsigned i = 0; i < num_offsets; i++) {
|
||||||
|
if (offsets[i] == off) {
|
||||||
|
ssbo_idx = i;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(found);
|
||||||
|
|
||||||
|
nir_def *idx_ssa = nir_imm_int(&b, ssbo_idx);
|
||||||
|
nir_def *off_ssa = rel ? rel : nir_imm_int(&b, 0);
|
||||||
|
|
||||||
|
switch (kind) {
|
||||||
|
case OP_LOAD: {
|
||||||
|
nir_def *result =
|
||||||
|
nir_load_ssbo(&b, intrin->def.num_components,
|
||||||
|
intrin->def.bit_size, idx_ssa, off_ssa,
|
||||||
|
.access = nir_intrinsic_access(intrin),
|
||||||
|
.align_mul = nir_intrinsic_align_mul(intrin),
|
||||||
|
.align_offset = nir_intrinsic_align_offset(intrin));
|
||||||
|
nir_def_replace(&intrin->def, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OP_STORE:
|
||||||
|
nir_store_ssbo(&b, intrin->src[0].ssa, idx_ssa, off_ssa,
|
||||||
|
.write_mask = nir_intrinsic_write_mask(intrin),
|
||||||
|
.access = nir_intrinsic_access(intrin),
|
||||||
|
.align_mul = nir_intrinsic_align_mul(intrin),
|
||||||
|
.align_offset = nir_intrinsic_align_offset(intrin));
|
||||||
|
nir_instr_remove(instr);
|
||||||
|
break;
|
||||||
|
case OP_ATOMIC: {
|
||||||
|
nir_def *result =
|
||||||
|
nir_ssbo_atomic(&b, intrin->def.bit_size, idx_ssa, off_ssa,
|
||||||
|
intrin->src[1].ssa,
|
||||||
|
.atomic_op = nir_intrinsic_atomic_op(intrin));
|
||||||
|
nir_def_replace(&intrin->def, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OP_ATOMIC_SWAP: {
|
||||||
|
nir_def *result =
|
||||||
|
nir_ssbo_atomic_swap(&b, intrin->def.bit_size, idx_ssa, off_ssa,
|
||||||
|
intrin->src[1].ssa, intrin->src[2].ssa,
|
||||||
|
.atomic_op = nir_intrinsic_atomic_op(intrin));
|
||||||
|
nir_def_replace(&intrin->def, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nir->info.num_ssbos = num_offsets;
|
||||||
|
nir_progress(true, impl, nir_metadata_none);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static struct crocus_compiled_shader *
|
static struct crocus_compiled_shader *
|
||||||
crocus_compile_cs(struct crocus_context *ice,
|
crocus_compile_cs(struct crocus_context *ice,
|
||||||
struct crocus_uncompiled_shader *ish,
|
struct crocus_uncompiled_shader *ish,
|
||||||
@@ -2522,6 +2853,9 @@ crocus_compile_cs(struct crocus_context *ice,
|
|||||||
|
|
||||||
nir_shader *nir = nir_shader_clone(mem_ctx, ish->nir);
|
nir_shader *nir = nir_shader_clone(mem_ctx, ish->nir);
|
||||||
|
|
||||||
|
if (devinfo->ver < 8)
|
||||||
|
NIR_PASS(_, nir, crocus_lower_cs_global_to_ssbo);
|
||||||
|
|
||||||
NIR_PASS(_, nir, elk_nir_lower_cs_intrinsics, devinfo, cs_prog_data);
|
NIR_PASS(_, nir, elk_nir_lower_cs_intrinsics, devinfo, cs_prog_data);
|
||||||
|
|
||||||
crocus_setup_uniforms(devinfo, mem_ctx, nir, prog_data, &system_values,
|
crocus_setup_uniforms(devinfo, mem_ctx, nir, prog_data, &system_values,
|
||||||
@@ -2620,11 +2954,14 @@ crocus_fill_cs_push_const_buffer(struct elk_cs_prog_data *cs_prog_data,
|
|||||||
uint32_t *dst)
|
uint32_t *dst)
|
||||||
{
|
{
|
||||||
assert(elk_cs_push_const_total_size(cs_prog_data, threads) > 0);
|
assert(elk_cs_push_const_total_size(cs_prog_data, threads) > 0);
|
||||||
assert(cs_prog_data->push.cross_thread.size == 0);
|
|
||||||
assert(cs_prog_data->push.per_thread.dwords == 1);
|
/* per_thread: subgroup_id -- cross_thread dwords'den sonra yaz */
|
||||||
assert(cs_prog_data->base.param[0] == ELK_PARAM_BUILTIN_SUBGROUP_ID);
|
if (cs_prog_data->push.per_thread.dwords == 1 &&
|
||||||
for (unsigned t = 0; t < threads; t++)
|
cs_prog_data->base.param[0] == ELK_PARAM_BUILTIN_SUBGROUP_ID) {
|
||||||
dst[8 * t] = t;
|
unsigned cross_dwords = cs_prog_data->push.cross_thread.dwords;
|
||||||
|
for (unsigned t = 0; t < threads; t++)
|
||||||
|
dst[cross_dwords + 8 * t] = t;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2906,6 +3243,9 @@ crocus_create_compute_state(struct pipe_context *ctx,
|
|||||||
struct crocus_uncompiled_shader *ish =
|
struct crocus_uncompiled_shader *ish =
|
||||||
crocus_create_uncompiled_shader(ctx, (void *) state->prog, NULL);
|
crocus_create_uncompiled_shader(ctx, (void *) state->prog, NULL);
|
||||||
|
|
||||||
|
if (ish->nir->info.stage == MESA_SHADER_KERNEL)
|
||||||
|
ish->nir->info.stage = MESA_SHADER_COMPUTE;
|
||||||
|
|
||||||
ish->nos |= (1ull << CROCUS_NOS_TEXTURES);
|
ish->nos |= (1ull << CROCUS_NOS_TEXTURES);
|
||||||
// XXX: disallow more than 64KB of shared variables
|
// XXX: disallow more than 64KB of shared variables
|
||||||
|
|
||||||
@@ -3112,11 +3452,14 @@ crocus_get_compute_state_info(struct pipe_context *ctx, void *state,
|
|||||||
struct pipe_compute_state_object_info *info)
|
struct pipe_compute_state_object_info *info)
|
||||||
{
|
{
|
||||||
struct crocus_screen *screen = (void *) ctx->screen;
|
struct crocus_screen *screen = (void *) ctx->screen;
|
||||||
info->max_threads = screen->devinfo.max_cs_threads *
|
const struct intel_device_info *devinfo = &screen->devinfo;
|
||||||
screen->devinfo.subslice_total;
|
|
||||||
|
const uint32_t simd_width = devinfo->ver >= 8 ? 32 : 8;
|
||||||
|
|
||||||
|
info->max_threads = simd_width * devinfo->max_cs_workgroup_threads;
|
||||||
info->private_memory = 0;
|
info->private_memory = 0;
|
||||||
info->preferred_simd_size = 16;
|
info->preferred_simd_size = simd_width;
|
||||||
info->simd_sizes = 8 | 16;
|
info->simd_sizes = devinfo->ver >= 8 ? (8 | 16 | 32) : (8 | 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -203,7 +203,12 @@ crocus_init_compute_caps(struct crocus_screen *screen)
|
|||||||
if (devinfo->ver < 7)
|
if (devinfo->ver < 7)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const uint32_t max_invocations = 32 * devinfo->max_cs_workgroup_threads;
|
/* Gen7 (IVB/BYT/HSW) compute dispatch max SIMD width is 8;
|
||||||
|
* Gfx9+ can reach SIMD32. Using 32 unconditionally overreports
|
||||||
|
* the work-group size on Gen7 (2048 instead of the real 512).
|
||||||
|
*/
|
||||||
|
const uint32_t simd_width = devinfo->ver >= 8 ? 32 : 8;
|
||||||
|
const uint32_t max_invocations = simd_width * devinfo->max_cs_workgroup_threads;
|
||||||
|
|
||||||
caps->address_bits = 32;
|
caps->address_bits = 32;
|
||||||
|
|
||||||
@@ -227,6 +232,22 @@ crocus_init_compute_caps(struct crocus_screen *screen)
|
|||||||
caps->subgroup_sizes = ELK_SUBGROUP_SIZE;
|
caps->subgroup_sizes = ELK_SUBGROUP_SIZE;
|
||||||
|
|
||||||
caps->max_variable_threads_per_block = max_invocations;
|
caps->max_variable_threads_per_block = max_invocations;
|
||||||
|
|
||||||
|
caps->max_compute_units = intel_device_info_eu_total(devinfo) > 0
|
||||||
|
? intel_device_info_eu_total(devinfo)
|
||||||
|
: (devinfo->gt == 2 ? 16 : 6);
|
||||||
|
|
||||||
|
/* Gen7 supports up to 2GB (1 << 31) buffers via stateless access.
|
||||||
|
* Limit to 1GB to be safe with 32-bit addressing.
|
||||||
|
*/
|
||||||
|
caps->max_global_size = 1ULL << 30; /* 1 GB */
|
||||||
|
caps->max_mem_alloc_size = 1ULL << 29; /* 512 MB — meets CL min for non-CUSTOM */
|
||||||
|
|
||||||
|
caps->max_clock_frequency = 1300; /* MHz, approximate for IVB GT2 */
|
||||||
|
/* Gen7+ has a real, physically separate Shared Local Memory block
|
||||||
|
* (accessed via Binding Table Index 254), unlike architectures where
|
||||||
|
* "local" memory is just a region of global memory. */
|
||||||
|
caps->has_dedicated_local_mem = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -289,6 +310,7 @@ crocus_init_screen_caps(struct crocus_screen *screen)
|
|||||||
caps->gl_clamp = true;
|
caps->gl_clamp = true;
|
||||||
caps->legacy_math_rules = true;
|
caps->legacy_math_rules = true;
|
||||||
caps->native_fence_fd = true;
|
caps->native_fence_fd = true;
|
||||||
|
caps->cl_gl_sharing = true;
|
||||||
|
|
||||||
caps->int64 =
|
caps->int64 =
|
||||||
caps->shader_ballot =
|
caps->shader_ballot =
|
||||||
@@ -493,63 +515,7 @@ crocus_query_memory_info(struct pipe_screen *pscreen,
|
|||||||
info->avail_staging_memory = info->total_staging_memory;
|
info->avail_staging_memory = info->total_staging_memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
crocus_get_compute_param(struct pipe_screen *pscreen,
|
|
||||||
enum pipe_shader_ir ir_type,
|
|
||||||
enum pipe_compute_cap param,
|
|
||||||
void *ret)
|
|
||||||
{
|
|
||||||
struct crocus_screen *screen = (struct crocus_screen *) pscreen;
|
|
||||||
const struct intel_device_info *devinfo = &screen->devinfo;
|
|
||||||
|
|
||||||
switch (param) {
|
|
||||||
case PIPE_COMPUTE_CAP_MAX_COMPUTE_UNITS:
|
|
||||||
if (ret) {
|
|
||||||
uint32_t num_eu = devinfo->num_eu_total > 0 ? devinfo->num_eu_total : ((devinfo->gt == 2) ? 16 : 6);
|
|
||||||
((uint32_t *)ret)[0] = num_eu;
|
|
||||||
}
|
|
||||||
return sizeof(uint32_t);
|
|
||||||
|
|
||||||
case PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK:
|
|
||||||
if (ret)
|
|
||||||
((uint64_t *)ret)[0] = 1024;
|
|
||||||
return sizeof(uint64_t);
|
|
||||||
|
|
||||||
case PIPE_COMPUTE_CAP_MAX_GRID_SIZE:
|
|
||||||
if (ret) {
|
|
||||||
((uint64_t *)ret)[0] = 65535;
|
|
||||||
((uint64_t *)ret)[1] = 65535;
|
|
||||||
((uint64_t *)ret)[2] = 65535;
|
|
||||||
}
|
|
||||||
return 3 * sizeof(uint64_t);
|
|
||||||
|
|
||||||
case PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE:
|
|
||||||
if (ret) {
|
|
||||||
((uint64_t *)ret)[0] = 1024;
|
|
||||||
((uint64_t *)ret)[1] = 1024;
|
|
||||||
((uint64_t *)ret)[2] = 1024;
|
|
||||||
}
|
|
||||||
return 3 * sizeof(uint64_t);
|
|
||||||
|
|
||||||
case PIPE_COMPUTE_CAP_PREFERRED_BLOCK_SIZE:
|
|
||||||
if (ret)
|
|
||||||
((uint64_t *)ret)[0] = 256;
|
|
||||||
return sizeof(uint64_t);
|
|
||||||
|
|
||||||
case PIPE_COMPUTE_CAP_IMAGES_SUPPORTED:
|
|
||||||
if (ret)
|
|
||||||
((uint32_t *)ret)[0] = 1;
|
|
||||||
return sizeof(uint32_t);
|
|
||||||
|
|
||||||
case PIPE_COMPUTE_CAP_SUBGROUP_SIZE:
|
|
||||||
if (ret)
|
|
||||||
((uint32_t *)ret)[0] = devinfo->subgroup_size ? devinfo->subgroup_size : 16;
|
|
||||||
return sizeof(uint32_t);
|
|
||||||
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct disk_cache *
|
static struct disk_cache *
|
||||||
crocus_get_disk_shader_cache(struct pipe_screen *pscreen)
|
crocus_get_disk_shader_cache(struct pipe_screen *pscreen)
|
||||||
@@ -720,8 +686,6 @@ crocus_screen_create(int fd, const struct pipe_screen_config *config)
|
|||||||
pscreen->query_memory_info = crocus_query_memory_info;
|
pscreen->query_memory_info = crocus_query_memory_info;
|
||||||
pscreen->get_driver_query_group_info = crocus_get_monitor_group_info;
|
pscreen->get_driver_query_group_info = crocus_get_monitor_group_info;
|
||||||
pscreen->get_driver_query_info = crocus_get_monitor_info;
|
pscreen->get_driver_query_info = crocus_get_monitor_info;
|
||||||
pscreen->get_compute_param = crocus_get_compute_param;
|
|
||||||
|
|
||||||
crocus_init_shader_caps(screen);
|
crocus_init_shader_caps(screen);
|
||||||
crocus_init_compute_caps(screen);
|
crocus_init_compute_caps(screen);
|
||||||
crocus_init_screen_caps(screen);
|
crocus_init_screen_caps(screen);
|
||||||
|
|||||||
@@ -5513,6 +5513,35 @@ crocus_populate_binding_table(struct crocus_context *ice,
|
|||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* IVB Gen7: emit one surface per global binding using actual BO address.
|
||||||
|
* handle[] holds relative offset (0), surface base = BO gtt address.
|
||||||
|
* store_global(val, abs_addr) works because abs_addr = gtt_offset + rel,
|
||||||
|
* and surface base = gtt_offset, so hw writes to gtt_offset + rel. */
|
||||||
|
foreach_surface_used(i, CROCUS_SURFACE_GROUP_GLOBAL) {
|
||||||
|
struct isl_device *isl_dev_g = &batch->screen->isl_dev;
|
||||||
|
uint32_t g_offset = 0;
|
||||||
|
uint32_t *g_surf = stream_state(batch, isl_dev_g->ss.size,
|
||||||
|
isl_dev_g->ss.align, &g_offset);
|
||||||
|
struct pipe_resource *global_res = ice->state.global_bindings[i];
|
||||||
|
if (global_res) {
|
||||||
|
struct crocus_resource *gres = (struct crocus_resource *) global_res;
|
||||||
|
isl_buffer_fill_state(isl_dev_g, g_surf,
|
||||||
|
.address = crocus_state_reloc(batch,
|
||||||
|
g_offset + isl_dev_g->ss.addr_offset,
|
||||||
|
gres->bo, 0,
|
||||||
|
RELOC_32BIT | RELOC_WRITE),
|
||||||
|
.size_B = gres->bo->size,
|
||||||
|
.format = ISL_FORMAT_RAW,
|
||||||
|
.swizzle = ISL_SWIZZLE_IDENTITY,
|
||||||
|
.stride_B = 1,
|
||||||
|
.mocs = crocus_mocs(gres->bo, isl_dev_g));
|
||||||
|
} else {
|
||||||
|
emit_null_surface(batch, &g_offset);
|
||||||
|
}
|
||||||
|
surf_offsets[s] = g_offset;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/* ------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------- */
|
||||||
static uint32_t
|
static uint32_t
|
||||||
@@ -5544,6 +5573,7 @@ crocus_update_surface_base_address(struct crocus_batch *batch)
|
|||||||
crocus_emit_cmd(batch, GENX(STATE_BASE_ADDRESS), sba) {
|
crocus_emit_cmd(batch, GENX(STATE_BASE_ADDRESS), sba) {
|
||||||
/* Set base addresses */
|
/* Set base addresses */
|
||||||
sba.GeneralStateBaseAddressModifyEnable = true;
|
sba.GeneralStateBaseAddressModifyEnable = true;
|
||||||
|
sba.GeneralStateBaseAddress = ro_bo(batch->state.bo, 0);
|
||||||
|
|
||||||
#if GFX_VER >= 6
|
#if GFX_VER >= 6
|
||||||
sba.DynamicStateBaseAddressModifyEnable = true;
|
sba.DynamicStateBaseAddressModifyEnable = true;
|
||||||
@@ -5587,6 +5617,7 @@ crocus_update_surface_base_address(struct crocus_batch *batch)
|
|||||||
*/
|
*/
|
||||||
sba.DynamicStateAccessUpperBound = ro_bo(NULL, 0xfffff000);
|
sba.DynamicStateAccessUpperBound = ro_bo(NULL, 0xfffff000);
|
||||||
sba.DynamicStateAccessUpperBoundModifyEnable = true;
|
sba.DynamicStateAccessUpperBoundModifyEnable = true;
|
||||||
|
sba.GeneralStateAccessUpperBound = ro_bo(NULL, 0xfffff000);
|
||||||
#else
|
#else
|
||||||
/* Same idea but using General State Base Address on Gen4-5 */
|
/* Same idea but using General State Base Address on Gen4-5 */
|
||||||
sba.GeneralStateAccessUpperBound = ro_bo(NULL, 0xfffff000);
|
sba.GeneralStateAccessUpperBound = ro_bo(NULL, 0xfffff000);
|
||||||
@@ -5598,7 +5629,10 @@ crocus_update_surface_base_address(struct crocus_batch *batch)
|
|||||||
* if you don't set the "Address Modify Enable" bit for the base.
|
* if you don't set the "Address Modify Enable" bit for the base.
|
||||||
*/
|
*/
|
||||||
sba.GeneralStateMOCS = mocs;
|
sba.GeneralStateMOCS = mocs;
|
||||||
sba.StatelessDataPortAccessMOCS = mocs;
|
sba.StatelessDataPortAccessMOCS = mocs ? mocs : 1; /* Try L3 cacheable if 0 */
|
||||||
|
#if GFX_VERx10 == 70
|
||||||
|
sba.StatelessDataPortAccessForceWriteThru = true;
|
||||||
|
#endif
|
||||||
sba.DynamicStateMOCS = mocs;
|
sba.DynamicStateMOCS = mocs;
|
||||||
sba.IndirectObjectMOCS = mocs;
|
sba.IndirectObjectMOCS = mocs;
|
||||||
sba.InstructionMOCS = mocs;
|
sba.InstructionMOCS = mocs;
|
||||||
@@ -8073,8 +8107,15 @@ crocus_upload_compute_state(struct crocus_context *ice,
|
|||||||
elk_cs_get_dispatch_info(devinfo, cs_prog_data, grid->block);
|
elk_cs_get_dispatch_info(devinfo, cs_prog_data, grid->block);
|
||||||
|
|
||||||
crocus_update_surface_base_address(batch);
|
crocus_update_surface_base_address(batch);
|
||||||
if ((stage_dirty & CROCUS_STAGE_DIRTY_CONSTANTS_CS) && shs->sysvals_need_upload)
|
if ((stage_dirty & CROCUS_STAGE_DIRTY_CONSTANTS_CS) && shs->sysvals_need_upload) {
|
||||||
|
for (unsigned i = 0; i < CROCUS_MAX_GLOBAL_BINDINGS; i++) {
|
||||||
|
if (ice->state.global_bindings[i]) {
|
||||||
|
struct crocus_resource *res = (struct crocus_resource *) ice->state.global_bindings[i];
|
||||||
|
crocus_use_bo(batch, res->bo, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
upload_sysvals(ice, MESA_SHADER_COMPUTE);
|
upload_sysvals(ice, MESA_SHADER_COMPUTE);
|
||||||
|
}
|
||||||
|
|
||||||
if (stage_dirty & CROCUS_STAGE_DIRTY_BINDINGS_CS) {
|
if (stage_dirty & CROCUS_STAGE_DIRTY_BINDINGS_CS) {
|
||||||
crocus_populate_binding_table(ice, batch, MESA_SHADER_COMPUTE, false);
|
crocus_populate_binding_table(ice, batch, MESA_SHADER_COMPUTE, false);
|
||||||
@@ -8145,13 +8186,10 @@ crocus_upload_compute_state(struct crocus_context *ice,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Combine subgroup-id with cbuf0 so we can push regular uniforms */
|
/* Push cross_thread (kernel args) + per_thread (subgroup_id) to CURBE */
|
||||||
if ((stage_dirty & CROCUS_STAGE_DIRTY_CS) ||
|
if ((stage_dirty & CROCUS_STAGE_DIRTY_CS) ||
|
||||||
cs_prog_data->local_size[0] == 0 /* Variable local group size */) {
|
cs_prog_data->local_size[0] == 0 /* Variable local group size */) {
|
||||||
uint32_t curbe_data_offset = 0;
|
uint32_t curbe_data_offset = 0;
|
||||||
assert(cs_prog_data->push.cross_thread.dwords == 0 &&
|
|
||||||
cs_prog_data->push.per_thread.dwords == 1 &&
|
|
||||||
cs_prog_data->base.param[0] == ELK_PARAM_BUILTIN_SUBGROUP_ID);
|
|
||||||
const unsigned push_const_size =
|
const unsigned push_const_size =
|
||||||
elk_cs_push_const_total_size(cs_prog_data, dispatch.threads);
|
elk_cs_push_const_total_size(cs_prog_data, dispatch.threads);
|
||||||
uint32_t *curbe_data_map =
|
uint32_t *curbe_data_map =
|
||||||
@@ -8160,6 +8198,24 @@ crocus_upload_compute_state(struct crocus_context *ice,
|
|||||||
&curbe_data_offset);
|
&curbe_data_offset);
|
||||||
assert(curbe_data_map);
|
assert(curbe_data_map);
|
||||||
memset(curbe_data_map, 0x5a, align(push_const_size, 64));
|
memset(curbe_data_map, 0x5a, align(push_const_size, 64));
|
||||||
|
|
||||||
|
if (cs_prog_data->push.cross_thread.size > 0) {
|
||||||
|
struct pipe_constant_buffer *cbuf = &shs->constbufs[0];
|
||||||
|
if (cbuf->user_buffer) {
|
||||||
|
memcpy(curbe_data_map, cbuf->user_buffer,
|
||||||
|
cs_prog_data->push.cross_thread.size);
|
||||||
|
} else if (cbuf->buffer) {
|
||||||
|
struct crocus_resource *res =
|
||||||
|
(struct crocus_resource *) cbuf->buffer;
|
||||||
|
void *map = crocus_bo_map(NULL, res->bo, MAP_READ);
|
||||||
|
if (map) {
|
||||||
|
memcpy(curbe_data_map,
|
||||||
|
(uint8_t *)map + cbuf->buffer_offset,
|
||||||
|
cs_prog_data->push.cross_thread.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
crocus_fill_cs_push_const_buffer(cs_prog_data, dispatch.threads,
|
crocus_fill_cs_push_const_buffer(cs_prog_data, dispatch.threads,
|
||||||
curbe_data_map);
|
curbe_data_map);
|
||||||
|
|
||||||
@@ -8184,7 +8240,8 @@ crocus_upload_compute_state(struct crocus_context *ice,
|
|||||||
idd.ConstantURBEntryReadLength = cs_prog_data->push.per_thread.regs;
|
idd.ConstantURBEntryReadLength = cs_prog_data->push.per_thread.regs;
|
||||||
idd.BarrierEnable = cs_prog_data->uses_barrier;
|
idd.BarrierEnable = cs_prog_data->uses_barrier;
|
||||||
idd.SharedLocalMemorySize = intel_compute_slm_encode_size(GFX_VER,
|
idd.SharedLocalMemorySize = intel_compute_slm_encode_size(GFX_VER,
|
||||||
prog_data->total_shared);
|
prog_data->total_shared +
|
||||||
|
grid->variable_shared_mem);
|
||||||
#if GFX_VERx10 >= 75
|
#if GFX_VERx10 >= 75
|
||||||
idd.CrossThreadConstantDataReadLength = cs_prog_data->push.cross_thread.regs;
|
idd.CrossThreadConstantDataReadLength = cs_prog_data->push.cross_thread.regs;
|
||||||
#endif
|
#endif
|
||||||
@@ -8279,6 +8336,11 @@ crocus_upload_compute_state(struct crocus_context *ice,
|
|||||||
|
|
||||||
crocus_emit_cmd(batch, GENX(MEDIA_STATE_FLUSH), msf);
|
crocus_emit_cmd(batch, GENX(MEDIA_STATE_FLUSH), msf);
|
||||||
|
|
||||||
|
crocus_emit_pipe_control_flush(batch,
|
||||||
|
"compute: flush DC after GPGPU_WALKER",
|
||||||
|
PIPE_CONTROL_DATA_CACHE_FLUSH |
|
||||||
|
PIPE_CONTROL_CS_STALL);
|
||||||
|
|
||||||
batch->contains_draw = true;
|
batch->contains_draw = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8286,23 +8348,40 @@ static void
|
|||||||
crocus_set_global_binding(struct pipe_context *ctx,
|
crocus_set_global_binding(struct pipe_context *ctx,
|
||||||
unsigned start_slot, unsigned count,
|
unsigned start_slot, unsigned count,
|
||||||
struct pipe_resource **resources,
|
struct pipe_resource **resources,
|
||||||
uint32_t **handles)
|
uint32_t **handles) {
|
||||||
{
|
|
||||||
struct crocus_context *ice = (struct crocus_context *) ctx;
|
struct crocus_context *ice = (struct crocus_context *) ctx;
|
||||||
assert(start_slot + count <= CROCUS_MAX_GLOBAL_BINDINGS);
|
assert(start_slot + count <= CROCUS_MAX_GLOBAL_BINDINGS);
|
||||||
|
|
||||||
for (unsigned i = 0; i < count; i++) {
|
for (unsigned i = 0; i < count; i++) {
|
||||||
if (resources && resources[i]) {
|
if (resources && resources[i]) {
|
||||||
pipe_resource_reference(&ice->state.global_bindings[start_slot + i],
|
pipe_resource_reference(&ice->state.global_bindings[start_slot + i],
|
||||||
resources[i]);
|
resources[i]);
|
||||||
struct crocus_resource *res = (struct crocus_resource *) resources[i];
|
struct crocus_resource *res = (struct crocus_resource *) resources[i];
|
||||||
assert(res->base.b.target == PIPE_BUFFER);
|
assert(res->base.b.target == PIPE_BUFFER);
|
||||||
uint32_t addr = 0;
|
/* IVB: handle = 0 (offset from BO base = 0).
|
||||||
memcpy(&addr, handles[i], sizeof(addr));
|
* Surface base = BO real address via reloc.
|
||||||
addr += res->bo->gtt_offset;
|
* store_global(val, 0 + i*4) -> surface[base=real_addr][offset=i*4] */
|
||||||
memcpy(handles[i], &addr, sizeof(addr));
|
|
||||||
|
uint32_t addr = 0;
|
||||||
|
memcpy(handles[i], &addr, sizeof(addr));
|
||||||
|
ice->state.global_binding_handles[start_slot + i] = NULL;
|
||||||
|
|
||||||
|
/* IVB: also bind as SSBO at the same index, for the load_global ->
|
||||||
|
* load_ssbo NIR redirect pass (crocus_lower_cs_global_to_ssbo). */
|
||||||
|
struct crocus_shader_state *cs_shs =
|
||||||
|
&ice->state.shaders[MESA_SHADER_COMPUTE];
|
||||||
|
struct pipe_shader_buffer *ssbo = &cs_shs->ssbo[start_slot + i];
|
||||||
|
pipe_resource_reference(&ssbo->buffer, &res->base.b);
|
||||||
|
ssbo->buffer_offset = res->offset;
|
||||||
|
ssbo->buffer_size = res->bo->size - res->offset;
|
||||||
|
cs_shs->bound_ssbos |= 1u << (start_slot + i);
|
||||||
|
cs_shs->writable_ssbos |= 1u << (start_slot + i);
|
||||||
|
res->bind_history |= PIPE_BIND_SHADER_BUFFER;
|
||||||
|
res->bind_stages |= 1u << MESA_SHADER_COMPUTE;
|
||||||
} else {
|
} else {
|
||||||
pipe_resource_reference(&ice->state.global_bindings[start_slot + i],
|
pipe_resource_reference(&ice->state.global_bindings[start_slot + i],
|
||||||
NULL);
|
NULL);
|
||||||
|
ice->state.global_binding_handles[start_slot + i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_BINDINGS_CS;
|
ice->state.stage_dirty |= CROCUS_STAGE_DIRTY_BINDINGS_CS;
|
||||||
|
|||||||
@@ -20,6 +20,14 @@ use std::ffi::c_void;
|
|||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
|
fn rusticl_dbg(msg: &str) {
|
||||||
|
use std::io::Write;
|
||||||
|
if let Ok(mut f) = std::fs::OpenOptions::new().create(true).append(true).open("/tmp/rusticl_debug.log") {
|
||||||
|
let _ = writeln!(f, "{}", msg);
|
||||||
|
let _ = f.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cl_info_entrypoint(clGetContextInfo)]
|
#[cl_info_entrypoint(clGetContextInfo)]
|
||||||
unsafe impl CLInfo<cl_context_info> for cl_context {
|
unsafe impl CLInfo<cl_context_info> for cl_context {
|
||||||
fn query(&self, q: cl_context_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
fn query(&self, q: cl_context_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
|
||||||
@@ -99,7 +107,9 @@ pub fn get_gl_context_info_khr(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rusticl_dbg(&format!("RUSTICL_DBG: gl_context={:?} glx_display={:?} egl_display={:?}", gl_context, glx_display, egl_display));
|
||||||
let gl_ctx_manager = GLCtxManager::new(gl_context, glx_display, egl_display)?;
|
let gl_ctx_manager = GLCtxManager::new(gl_context, glx_display, egl_display)?;
|
||||||
|
rusticl_dbg(&format!("RUSTICL_DBG: GLCtxManager::new result is_some={}", gl_ctx_manager.is_some()));
|
||||||
unsafe {
|
unsafe {
|
||||||
gl_ctx_manager
|
gl_ctx_manager
|
||||||
.ok_or(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR)?
|
.ok_or(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR)?
|
||||||
@@ -175,28 +185,24 @@ fn create_context(
|
|||||||
|
|
||||||
let gl_ctx_manager = GLCtxManager::new(gl_context, glx_display, egl_display)?;
|
let gl_ctx_manager = GLCtxManager::new(gl_context, glx_display, egl_display)?;
|
||||||
if let Some(gl_ctx_manager) = &gl_ctx_manager {
|
if let Some(gl_ctx_manager) = &gl_ctx_manager {
|
||||||
// errcode_ret returns CL_INVALID_OPERATION if a context was specified as described above
|
|
||||||
// and any of the following conditions hold:
|
|
||||||
// ...
|
|
||||||
// Any of the devices specified in the devices argument cannot support OpenCL objects which
|
|
||||||
// share the data store of an OpenGL object.
|
|
||||||
|
|
||||||
let [dev] = devs.as_slice() else {
|
let [dev] = devs.as_slice() else {
|
||||||
|
rusticl_dbg(&format!("RUSTICL_DBG: create_context fail at (B) - multiple devices with gl sharing"));
|
||||||
return Err(CL_INVALID_OPERATION);
|
return Err(CL_INVALID_OPERATION);
|
||||||
};
|
};
|
||||||
|
|
||||||
if !dev.is_gl_sharing_supported() {
|
if !dev.is_gl_sharing_supported() {
|
||||||
|
rusticl_dbg(&format!("RUSTICL_DBG: create_context fail at (C) - gl sharing not supported on this device"));
|
||||||
return Err(CL_INVALID_OPERATION);
|
return Err(CL_INVALID_OPERATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
// gl sharing is only supported on devices with an UUID, so we can simply unwrap it
|
|
||||||
let dev_uuid: [c_char; UUID_SIZE] = dev
|
let dev_uuid: [c_char; UUID_SIZE] = dev
|
||||||
.screen()
|
.screen()
|
||||||
.device_uuid()
|
.device_uuid()
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.map(|val| val as c_char);
|
.map(|val| val as c_char);
|
||||||
if gl_ctx_manager.interop_dev_info.device_uuid != dev_uuid {
|
if gl_ctx_manager.interop_dev_info.device_uuid != dev_uuid {
|
||||||
// we only support gl_sharing on the same device
|
eprintln!("RUSTICL_DBG: create_context fail at (D) - uuid mismatch: gl_ctx={:?} dev={:?}",
|
||||||
|
gl_ctx_manager.interop_dev_info.device_uuid, dev_uuid);
|
||||||
return Err(CL_INVALID_OPERATION);
|
return Err(CL_INVALID_OPERATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,8 +165,14 @@ unsafe impl CLInfo<cl_device_info> for cl_device_id {
|
|||||||
}
|
}
|
||||||
CL_DEVICE_LINKER_AVAILABLE => v.write::<bool>(true),
|
CL_DEVICE_LINKER_AVAILABLE => v.write::<bool>(true),
|
||||||
CL_DEVICE_LOCAL_MEM_SIZE => v.write::<cl_ulong>(dev.local_mem_size()),
|
CL_DEVICE_LOCAL_MEM_SIZE => v.write::<cl_ulong>(dev.local_mem_size()),
|
||||||
// TODO add query for CL_LOCAL vs CL_GLOBAL
|
CL_DEVICE_LOCAL_MEM_TYPE => {
|
||||||
CL_DEVICE_LOCAL_MEM_TYPE => v.write::<cl_device_local_mem_type>(CL_GLOBAL),
|
let local_type = if dev.screen().compute_caps().has_dedicated_local_mem {
|
||||||
|
CL_LOCAL
|
||||||
|
} else {
|
||||||
|
CL_GLOBAL
|
||||||
|
};
|
||||||
|
v.write::<cl_device_local_mem_type>(local_type)
|
||||||
|
}
|
||||||
CL_DEVICE_LUID => v.write::<[cl_uchar; CL_LUID_SIZE as usize]>(
|
CL_DEVICE_LUID => v.write::<[cl_uchar; CL_LUID_SIZE as usize]>(
|
||||||
dev.screen().device_luid().unwrap_or_default(),
|
dev.screen().device_luid().unwrap_or_default(),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -916,6 +916,23 @@ fn create_image_with_properties(
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let filtered_flags = filter_image_access_flags(flags);
|
let filtered_flags = filter_image_access_flags(flags);
|
||||||
|
{
|
||||||
|
use std::io::Write;
|
||||||
|
if let Ok(mut dbgf) = std::fs::OpenOptions::new().create(true).append(true).open("/tmp/rusticl_debug.log") {
|
||||||
|
let img_fmt = unsafe { *image_format };
|
||||||
|
let _ = writeln!(dbgf, "RUSTICL_DBG: create_image format={:?} channel_order={} channel_data_type={} image_type={} filtered_flags={:#x}",
|
||||||
|
format, img_fmt.image_channel_order, img_fmt.image_channel_data_type, desc.image_type, filtered_flags);
|
||||||
|
for d in &c.devs {
|
||||||
|
match d.formats.get(format) {
|
||||||
|
None => { let _ = writeln!(dbgf, "RUSTICL_DBG: device has NO entry for this pipe_format at all"); }
|
||||||
|
Some(f) => {
|
||||||
|
let _ = writeln!(dbgf, "RUSTICL_DBG: device format map: {:?}", f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = dbgf.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
// CL_IMAGE_FORMAT_NOT_SUPPORTED if there are no devices in context that support image_format.
|
// CL_IMAGE_FORMAT_NOT_SUPPORTED if there are no devices in context that support image_format.
|
||||||
c.devs
|
c.devs
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
@@ -935,12 +935,21 @@ impl DeviceBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_gl_sharing_supported(&self) -> bool {
|
pub fn is_gl_sharing_supported(&self) -> bool {
|
||||||
self.screen.caps().cl_gl_sharing
|
let c1 = self.screen.caps().cl_gl_sharing;
|
||||||
&& self.screen.caps().dmabuf != 0
|
let c2 = self.screen.caps().dmabuf != 0;
|
||||||
&& !self.is_device_software()
|
let c3 = !self.is_device_software();
|
||||||
&& self.screen.is_res_handle_supported()
|
let c4 = self.screen.is_res_handle_supported();
|
||||||
&& self.screen.device_uuid().is_some()
|
let c5 = self.screen.device_uuid().is_some();
|
||||||
&& self.caps.has_create_fence_fd
|
let c6 = self.caps.has_create_fence_fd;
|
||||||
|
{
|
||||||
|
use std::io::Write;
|
||||||
|
if let Ok(mut f) = std::fs::OpenOptions::new().create(true).append(true).open("/tmp/rusticl_debug.log") {
|
||||||
|
let _ = writeln!(f, "RUSTICL_DBG: is_gl_sharing_supported: cl_gl_sharing={} dmabuf={} !is_sw={} res_handle={} uuid_some={} fence_fd={}",
|
||||||
|
c1, c2, c3, c4, c5, c6);
|
||||||
|
let _ = f.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c1 && c2 && c3 && c4 && c5 && c6
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_device_software(&self) -> bool {
|
pub fn is_device_software(&self) -> bool {
|
||||||
|
|||||||
@@ -1801,6 +1801,9 @@ impl Kernel {
|
|||||||
// subtract the shader local_size as we only request something on top of that.
|
// subtract the shader local_size as we only request something on top of that.
|
||||||
variable_local_size -= static_local_size;
|
variable_local_size -= static_local_size;
|
||||||
|
|
||||||
|
let input_ptr_before = exec_builder.input().as_ptr();
|
||||||
|
let input_len_before = exec_builder.input().len();
|
||||||
|
|
||||||
let (resources, mut globals) = exec_builder.get_resources_and_globals();
|
let (resources, mut globals) = exec_builder.get_resources_and_globals();
|
||||||
|
|
||||||
ctx.bind_kernel(&nir_kernel_builds, variant)?;
|
ctx.bind_kernel(&nir_kernel_builds, variant)?;
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ impl<'c> QueueContextWithState<'c> {
|
|||||||
pub fn update_cb0(&self, data: &[u8]) -> CLResult<()> {
|
pub fn update_cb0(&self, data: &[u8]) -> CLResult<()> {
|
||||||
// only update if we actually bind data
|
// only update if we actually bind data
|
||||||
if !data.is_empty() {
|
if !data.is_empty() {
|
||||||
|
eprintln!("update_cb0: use_stream={} len={}", self.use_stream, data.len());
|
||||||
if self.use_stream {
|
if self.use_stream {
|
||||||
if !self.ctx.set_constant_buffer_stream(0, data) {
|
if !self.ctx.set_constant_buffer_stream(0, data) {
|
||||||
return Err(CL_OUT_OF_RESOURCES);
|
return Err(CL_OUT_OF_RESOURCES);
|
||||||
|
|||||||
@@ -825,6 +825,7 @@ struct pipe_compute_caps {
|
|||||||
unsigned max_variable_threads_per_block;
|
unsigned max_variable_threads_per_block;
|
||||||
uint64_t max_mem_alloc_size;
|
uint64_t max_mem_alloc_size;
|
||||||
uint64_t max_global_size;
|
uint64_t max_global_size;
|
||||||
|
bool has_dedicated_local_mem; /* true if SLM is physically separate from global memory */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pipe_mesh_caps {
|
struct pipe_mesh_caps {
|
||||||
|
|||||||
@@ -172,6 +172,10 @@ elk_get_compiler_config_value(const struct elk_compiler *compiler)
|
|||||||
unsigned
|
unsigned
|
||||||
elk_prog_data_size(mesa_shader_stage stage)
|
elk_prog_data_size(mesa_shader_stage stage)
|
||||||
{
|
{
|
||||||
|
if (stage == MESA_SHADER_KERNEL) {
|
||||||
|
stage = MESA_SHADER_COMPUTE;
|
||||||
|
}
|
||||||
|
|
||||||
static const size_t stage_sizes[] = {
|
static const size_t stage_sizes[] = {
|
||||||
[MESA_SHADER_VERTEX] = sizeof(struct elk_vs_prog_data),
|
[MESA_SHADER_VERTEX] = sizeof(struct elk_vs_prog_data),
|
||||||
[MESA_SHADER_TESS_CTRL] = sizeof(struct elk_tcs_prog_data),
|
[MESA_SHADER_TESS_CTRL] = sizeof(struct elk_tcs_prog_data),
|
||||||
|
|||||||
@@ -1053,6 +1053,7 @@ struct elk_cs_prog_data {
|
|||||||
* surface indices the CS-specific surfaces
|
* surface indices the CS-specific surfaces
|
||||||
*/
|
*/
|
||||||
uint32_t work_groups_start;
|
uint32_t work_groups_start;
|
||||||
|
uint32_t global_start; /* IVB: BTI for full-GTT global surface */
|
||||||
/** @} */
|
/** @} */
|
||||||
} binding_table;
|
} binding_table;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5114,6 +5114,31 @@ fs_nir_emit_intrinsic(nir_to_elk_state &ntb,
|
|||||||
|
|
||||||
case nir_intrinsic_load_global:
|
case nir_intrinsic_load_global:
|
||||||
case nir_intrinsic_load_global_constant: {
|
case nir_intrinsic_load_global_constant: {
|
||||||
|
if (devinfo->ver < 8) {
|
||||||
|
elk_fs_reg dest = get_nir_def(ntb, instr->def);
|
||||||
|
const unsigned bit_size = instr->def.bit_size;
|
||||||
|
elk_fs_reg srcs[SURFACE_LOGICAL_NUM_SRCS];
|
||||||
|
/* IVB: use dedicated full-GTT surface for global access */
|
||||||
|
const struct elk_cs_prog_data *cs_pd =
|
||||||
|
elk_cs_prog_data(ntb.s.prog_data);
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_SURFACE] = elk_imm_ud(cs_pd->binding_table.global_start);
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_ADDRESS] = get_nir_src(ntb, instr->src[0]);
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_IMM_DIMS] = elk_imm_ud(1);
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_ALLOW_SAMPLE_MASK] = elk_imm_ud(0);
|
||||||
|
dest.type = elk_reg_type_from_bit_size(bit_size, ELK_REGISTER_TYPE_UD);
|
||||||
|
|
||||||
|
if (bit_size == 32 && nir_intrinsic_align(instr) >= 4) {
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_IMM_ARG] = elk_imm_ud(instr->num_components);
|
||||||
|
elk_fs_inst *inst = bld.emit(ELK_SHADER_OPCODE_UNTYPED_SURFACE_READ_LOGICAL, dest, srcs, SURFACE_LOGICAL_NUM_SRCS);
|
||||||
|
inst->size_written = instr->num_components * s.dispatch_width * 4;
|
||||||
|
} else {
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_IMM_ARG] = elk_imm_ud(bit_size);
|
||||||
|
elk_fs_reg read_result = bld.vgrf(ELK_REGISTER_TYPE_UD);
|
||||||
|
bld.emit(ELK_SHADER_OPCODE_BYTE_SCATTERED_READ_LOGICAL, read_result, srcs, SURFACE_LOGICAL_NUM_SRCS);
|
||||||
|
bld.MOV(dest, subscript(read_result, dest.type, 0));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
assert(devinfo->ver >= 8);
|
assert(devinfo->ver >= 8);
|
||||||
|
|
||||||
assert(instr->def.bit_size <= 32);
|
assert(instr->def.bit_size <= 32);
|
||||||
@@ -5150,13 +5175,34 @@ fs_nir_emit_intrinsic(nir_to_elk_state &ntb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case nir_intrinsic_store_global: {
|
case nir_intrinsic_store_global: {
|
||||||
|
if (devinfo->ver < 8) {
|
||||||
|
const unsigned bit_size = nir_src_bit_size(instr->src[0]);
|
||||||
|
elk_fs_reg srcs[SURFACE_LOGICAL_NUM_SRCS];
|
||||||
|
/* IVB: use dedicated full-GTT surface for global access */
|
||||||
|
const struct elk_cs_prog_data *cs_pd =
|
||||||
|
elk_cs_prog_data(ntb.s.prog_data);
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_SURFACE] = elk_imm_ud(cs_pd->binding_table.global_start);
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_ADDRESS] = get_nir_src(ntb, instr->src[1]);
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_IMM_DIMS] = elk_imm_ud(1);
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_ALLOW_SAMPLE_MASK] = elk_imm_ud(1);
|
||||||
|
|
||||||
|
elk_fs_reg data = get_nir_src(ntb, instr->src[0]);
|
||||||
|
data.type = elk_reg_type_from_bit_size(bit_size, ELK_REGISTER_TYPE_UD);
|
||||||
|
|
||||||
|
if (bit_size == 32 && nir_intrinsic_align(instr) >= 4) {
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_DATA] = data;
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_IMM_ARG] = elk_imm_ud(instr->num_components);
|
||||||
|
bld.emit(ELK_SHADER_OPCODE_UNTYPED_SURFACE_WRITE_LOGICAL, elk_fs_reg(), srcs, SURFACE_LOGICAL_NUM_SRCS);
|
||||||
|
} else {
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_IMM_ARG] = elk_imm_ud(bit_size);
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_DATA] = bld.vgrf(ELK_REGISTER_TYPE_UD);
|
||||||
|
bld.MOV(srcs[SURFACE_LOGICAL_SRC_DATA], data);
|
||||||
|
bld.emit(ELK_SHADER_OPCODE_BYTE_SCATTERED_WRITE_LOGICAL, elk_fs_reg(), srcs, SURFACE_LOGICAL_NUM_SRCS);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
assert(devinfo->ver >= 8);
|
assert(devinfo->ver >= 8);
|
||||||
|
|
||||||
assert(nir_src_bit_size(instr->src[0]) <= 32);
|
|
||||||
assert(nir_intrinsic_write_mask(instr) ==
|
|
||||||
(1u << instr->num_components) - 1);
|
|
||||||
assert(nir_intrinsic_align(instr) > 0);
|
|
||||||
|
|
||||||
elk_fs_reg srcs[A64_LOGICAL_NUM_SRCS];
|
elk_fs_reg srcs[A64_LOGICAL_NUM_SRCS];
|
||||||
srcs[A64_LOGICAL_ADDRESS] = get_nir_src(ntb, instr->src[1]);
|
srcs[A64_LOGICAL_ADDRESS] = get_nir_src(ntb, instr->src[1]);
|
||||||
srcs[A64_LOGICAL_ENABLE_HELPERS] =
|
srcs[A64_LOGICAL_ENABLE_HELPERS] =
|
||||||
@@ -5523,6 +5569,7 @@ fs_nir_emit_intrinsic(nir_to_elk_state &ntb,
|
|||||||
srcs[SURFACE_LOGICAL_SRC_SURFACE] =
|
srcs[SURFACE_LOGICAL_SRC_SURFACE] =
|
||||||
elk_imm_ud(GFX8_BTI_STATELESS_NON_COHERENT);
|
elk_imm_ud(GFX8_BTI_STATELESS_NON_COHERENT);
|
||||||
} else {
|
} else {
|
||||||
|
/* IVB: use dedicated full-GTT surface instead of stateless BTI 255 */
|
||||||
srcs[SURFACE_LOGICAL_SRC_SURFACE] = elk_imm_ud(ELK_BTI_STATELESS);
|
srcs[SURFACE_LOGICAL_SRC_SURFACE] = elk_imm_ud(ELK_BTI_STATELESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6241,6 +6288,7 @@ static void
|
|||||||
fs_nir_emit_global_atomic(nir_to_elk_state &ntb, const fs_builder &bld,
|
fs_nir_emit_global_atomic(nir_to_elk_state &ntb, const fs_builder &bld,
|
||||||
nir_intrinsic_instr *instr)
|
nir_intrinsic_instr *instr)
|
||||||
{
|
{
|
||||||
|
const intel_device_info *devinfo = ntb.devinfo;
|
||||||
enum elk_lsc_opcode op = elk_lsc_aop_for_nir_intrinsic(instr);
|
enum elk_lsc_opcode op = elk_lsc_aop_for_nir_intrinsic(instr);
|
||||||
int num_data = lsc_op_num_data_values(op);
|
int num_data = lsc_op_num_data_values(op);
|
||||||
|
|
||||||
@@ -6262,6 +6310,20 @@ fs_nir_emit_global_atomic(nir_to_elk_state &ntb, const fs_builder &bld,
|
|||||||
data = tmp;
|
data = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (devinfo->ver < 8) {
|
||||||
|
elk_fs_reg srcs[SURFACE_LOGICAL_NUM_SRCS];
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_SURFACE] = elk_imm_ud(ELK_BTI_STATELESS);
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_ADDRESS] = addr;
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_IMM_DIMS] = elk_imm_ud(1);
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_ALLOW_SAMPLE_MASK] = elk_imm_ud(1);
|
||||||
|
if (num_data >= 1)
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_DATA] = data;
|
||||||
|
srcs[SURFACE_LOGICAL_SRC_IMM_ARG] = elk_imm_ud(op);
|
||||||
|
|
||||||
|
bld.emit(ELK_SHADER_OPCODE_UNTYPED_ATOMIC_LOGICAL, dest, srcs, SURFACE_LOGICAL_NUM_SRCS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
elk_fs_reg srcs[A64_LOGICAL_NUM_SRCS];
|
elk_fs_reg srcs[A64_LOGICAL_NUM_SRCS];
|
||||||
srcs[A64_LOGICAL_ADDRESS] = addr;
|
srcs[A64_LOGICAL_ADDRESS] = addr;
|
||||||
srcs[A64_LOGICAL_SRC] = data;
|
srcs[A64_LOGICAL_SRC] = data;
|
||||||
@@ -6853,6 +6915,7 @@ fs_nir_emit_instr(nir_to_elk_state &ntb, nir_instr *instr)
|
|||||||
fs_nir_emit_fs_intrinsic(ntb, nir_instr_as_intrinsic(instr));
|
fs_nir_emit_fs_intrinsic(ntb, nir_instr_as_intrinsic(instr));
|
||||||
break;
|
break;
|
||||||
case MESA_SHADER_COMPUTE:
|
case MESA_SHADER_COMPUTE:
|
||||||
|
case MESA_SHADER_KERNEL:
|
||||||
fs_nir_emit_cs_intrinsic(ntb, nir_instr_as_intrinsic(instr));
|
fs_nir_emit_cs_intrinsic(ntb, nir_instr_as_intrinsic(instr));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1199,8 +1199,7 @@ lower_surface_logical_send(const fs_builder &bld, elk_fs_inst *inst)
|
|||||||
if (is_typed_access || is_stateless) {
|
if (is_typed_access || is_stateless) {
|
||||||
fs_builder ubld = bld.exec_all().group(8, 0);
|
fs_builder ubld = bld.exec_all().group(8, 0);
|
||||||
header = ubld.vgrf(ELK_REGISTER_TYPE_UD);
|
header = ubld.vgrf(ELK_REGISTER_TYPE_UD);
|
||||||
if (is_stateless) {
|
if (is_stateless && !is_surface_access) {
|
||||||
assert(!is_surface_access);
|
|
||||||
ubld.emit(ELK_SHADER_OPCODE_SCRATCH_HEADER, header);
|
ubld.emit(ELK_SHADER_OPCODE_SCRATCH_HEADER, header);
|
||||||
} else {
|
} else {
|
||||||
ubld.MOV(header, elk_imm_d(0));
|
ubld.MOV(header, elk_imm_d(0));
|
||||||
|
|||||||
@@ -766,9 +766,12 @@ elk_nir_optimize(nir_shader *nir, bool is_scalar,
|
|||||||
OPT(nir_remove_dead_variables, nir_var_function_temp, NULL);
|
OPT(nir_remove_dead_variables, nir_var_function_temp, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned
|
static unsigned
|
||||||
lower_bit_size_callback(const nir_instr *instr, UNUSED void *data)
|
lower_bit_size_callback(const nir_instr *instr, void *data)
|
||||||
{
|
{
|
||||||
|
const struct elk_compiler *compiler = data;
|
||||||
|
const struct intel_device_info *devinfo = compiler->devinfo;
|
||||||
|
|
||||||
switch (instr->type) {
|
switch (instr->type) {
|
||||||
case nir_instr_type_alu: {
|
case nir_instr_type_alu: {
|
||||||
nir_alu_instr *alu = nir_instr_as_alu(instr);
|
nir_alu_instr *alu = nir_instr_as_alu(instr);
|
||||||
@@ -785,9 +788,19 @@ lower_bit_size_callback(const nir_instr *instr, UNUSED void *data)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (alu->def.bit_size == 16 &&
|
||||||
if (alu->def.bit_size >= 32)
|
devinfo->ver < 8 &&
|
||||||
return 0;
|
nir_op_infos[alu->op].output_type == nir_type_float) {
|
||||||
|
/* Gen7 has no native FP16 ALU/register support at all (see the
|
||||||
|
* empty HF entry in gfx7_hw_3src_type[] / gfx7_hw_type[] in
|
||||||
|
* elk_reg_type.c) -- unlike >=Gfx8, it cannot represent a
|
||||||
|
* 16-bit float operand or result under ANY circumstance, not
|
||||||
|
* just when inputs are mixed-width. Lower unconditionally,
|
||||||
|
* regardless of the source bit sizes, or elk_reg_type_to_hw_type()
|
||||||
|
* will hit an unencodable HF register type and assert.
|
||||||
|
*/
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
/* Note: nir_op_iabs and nir_op_ineg are not lowered here because the
|
/* Note: nir_op_iabs and nir_op_ineg are not lowered here because the
|
||||||
* 8-bit ABS or NEG instruction should eventually get copy propagated
|
* 8-bit ABS or NEG instruction should eventually get copy propagated
|
||||||
@@ -805,7 +818,7 @@ lower_bit_size_callback(const nir_instr *instr, UNUSED void *data)
|
|||||||
case nir_op_ffract:
|
case nir_op_ffract:
|
||||||
case nir_op_fround_even:
|
case nir_op_fround_even:
|
||||||
case nir_op_ftrunc:
|
case nir_op_ftrunc:
|
||||||
return 32;
|
return alu->def.bit_size < 32 ? 32 : 0;
|
||||||
case nir_op_frcp:
|
case nir_op_frcp:
|
||||||
case nir_op_frsq:
|
case nir_op_frsq:
|
||||||
case nir_op_fsqrt:
|
case nir_op_fsqrt:
|
||||||
@@ -814,7 +827,13 @@ lower_bit_size_callback(const nir_instr *instr, UNUSED void *data)
|
|||||||
case nir_op_flog2:
|
case nir_op_flog2:
|
||||||
case nir_op_fsin:
|
case nir_op_fsin:
|
||||||
case nir_op_fcos:
|
case nir_op_fcos:
|
||||||
return 32;
|
/* Same issue as the idiv/umod/fceil group above: these
|
||||||
|
* transcendental ops need >=32-bit precision on Gen7, but if
|
||||||
|
* the source is already >=32-bit, unconditionally returning
|
||||||
|
* 32 here trips the nir_lower_bit_size assert (src->bit_size
|
||||||
|
* < bit_size fails when equal or the source is 64-bit).
|
||||||
|
*/
|
||||||
|
return alu->def.bit_size < 32 ? 32 : 0;
|
||||||
case nir_op_isign:
|
case nir_op_isign:
|
||||||
UNREACHABLE("Should have been lowered by nir_opt_algebraic.");
|
UNREACHABLE("Should have been lowered by nir_opt_algebraic.");
|
||||||
default:
|
default:
|
||||||
@@ -1310,8 +1329,26 @@ get_mem_access_size_align(nir_intrinsic_op intrin, uint8_t bytes,
|
|||||||
bool offset_is_const, enum gl_access_qualifier access,
|
bool offset_is_const, enum gl_access_qualifier access,
|
||||||
const void *cb_data)
|
const void *cb_data)
|
||||||
{
|
{
|
||||||
|
const struct intel_device_info *devinfo = cb_data;
|
||||||
const uint32_t align = nir_combined_align(align_mul, align_offset);
|
const uint32_t align = nir_combined_align(align_mul, align_offset);
|
||||||
|
|
||||||
|
/* IVB (Gen7, verx10=70) has no byte-scattered dataport message --
|
||||||
|
* elk_dp_byte_scattered_rw_desc() asserts verx10 >= 75 (Haswell+).
|
||||||
|
* This is a real HW limitation, not a missing BTI like the global
|
||||||
|
* stateless case. Never request a sub-dword access on this hardware;
|
||||||
|
* always request dword granularity. nir_lower_mem_access_bit_sizes
|
||||||
|
* turns the mismatch into a shift+extract on the load side, and an
|
||||||
|
* atomic iand/ior read-modify-write on the store side (both already
|
||||||
|
* generic in the pass, we just need to ask for them). */
|
||||||
|
if (devinfo->verx10 < 75 && (align < 4 || bytes < 4)) {
|
||||||
|
return (nir_mem_access_size_align) {
|
||||||
|
.bit_size = 32,
|
||||||
|
.num_components = 1,
|
||||||
|
.align = 4,
|
||||||
|
.shift = nir_mem_access_shift_method_scalar,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
switch (intrin) {
|
switch (intrin) {
|
||||||
case nir_intrinsic_load_ssbo:
|
case nir_intrinsic_load_ssbo:
|
||||||
case nir_intrinsic_load_shared:
|
case nir_intrinsic_load_shared:
|
||||||
@@ -1401,6 +1438,7 @@ elk_vectorize_lower_mem_access(nir_shader *nir,
|
|||||||
OPT(nir_opt_load_store_vectorize, &options);
|
OPT(nir_opt_load_store_vectorize, &options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct intel_device_info *devinfo = compiler->devinfo;
|
||||||
nir_lower_mem_access_bit_sizes_options mem_access_options = {
|
nir_lower_mem_access_bit_sizes_options mem_access_options = {
|
||||||
.modes = nir_var_mem_ssbo |
|
.modes = nir_var_mem_ssbo |
|
||||||
nir_var_mem_constant |
|
nir_var_mem_constant |
|
||||||
@@ -1409,6 +1447,8 @@ elk_vectorize_lower_mem_access(nir_shader *nir,
|
|||||||
nir_var_mem_global |
|
nir_var_mem_global |
|
||||||
nir_var_mem_shared,
|
nir_var_mem_shared,
|
||||||
.callback = get_mem_access_size_align,
|
.callback = get_mem_access_size_align,
|
||||||
|
.cb_data = devinfo,
|
||||||
|
.may_lower_unaligned_stores_to_atomics = devinfo->verx10 < 75,
|
||||||
};
|
};
|
||||||
OPT(nir_lower_mem_access_bit_sizes, &mem_access_options);
|
OPT(nir_lower_mem_access_bit_sizes, &mem_access_options);
|
||||||
|
|
||||||
|
|||||||
@@ -220,10 +220,16 @@ elk_reg_type_to_hw_type(const struct intel_device_info *devinfo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (file == ELK_IMMEDIATE_VALUE) {
|
if (file == ELK_IMMEDIATE_VALUE) {
|
||||||
assert(table[type].imm_type != (enum hw_imm_type)INVALID);
|
if (table[type].imm_type == (enum hw_imm_type)INVALID) {
|
||||||
|
fprintf(stderr, "elk_reg_type_to_hw_type: INVALID imm_type! type=%d\n", type);
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
return table[type].imm_type;
|
return table[type].imm_type;
|
||||||
} else {
|
} else {
|
||||||
assert(table[type].reg_type != (enum hw_reg_type)INVALID);
|
if (table[type].reg_type == (enum hw_reg_type)INVALID) {
|
||||||
|
fprintf(stderr, "elk_reg_type_to_hw_type: INVALID reg_type! type=%d\n", type);
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
return table[type].reg_type;
|
return table[type].reg_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -274,9 +274,62 @@ anv_reloc_list_append(struct anv_reloc_list *list,
|
|||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*
|
/* Like anv_reloc_list_append(), but only copies/rebases the relocations
|
||||||
* Functions related to anv_batch
|
* whose offset falls at or after @skip_bytes -- i.e. the ones that belong
|
||||||
*-----------------------------------------------------------------------*/
|
* to the suffix of @other starting at that byte, which is what
|
||||||
|
* anv_batch_emit_batch_suffix() actually copies into @batch. Relocations
|
||||||
|
* before @skip_bytes belong to a region we are deliberately NOT emitting
|
||||||
|
* and must not be added (their target offset would land outside what we
|
||||||
|
* copied, corrupting the batch).
|
||||||
|
*/
|
||||||
|
static VkResult
|
||||||
|
anv_reloc_list_append_range(struct anv_reloc_list *list,
|
||||||
|
const VkAllocationCallbacks *alloc,
|
||||||
|
struct anv_reloc_list *other,
|
||||||
|
uint32_t skip_bytes, uint32_t offset)
|
||||||
|
{
|
||||||
|
uint32_t n = 0;
|
||||||
|
for (uint32_t i = 0; i < other->num_relocs; i++) {
|
||||||
|
if (other->relocs[i].offset >= skip_bytes)
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
/* Still need to propagate BO dependencies: shaders/state referenced
|
||||||
|
* only from the skipped prefix may not be otherwise declared as
|
||||||
|
* used by this command buffer submission if this is the very first
|
||||||
|
* time this pipeline's group is touched in it.
|
||||||
|
*/
|
||||||
|
anv_reloc_list_grow_deps(list, alloc, other->dep_words);
|
||||||
|
for (uint32_t w = 0; w < other->dep_words; w++)
|
||||||
|
list->deps[w] |= other->deps[w];
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult result = anv_reloc_list_grow(list, alloc, n);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
uint32_t j = list->num_relocs;
|
||||||
|
for (uint32_t i = 0; i < other->num_relocs; i++) {
|
||||||
|
if (other->relocs[i].offset < skip_bytes)
|
||||||
|
continue;
|
||||||
|
list->relocs[j] = other->relocs[i];
|
||||||
|
list->relocs[j].offset += offset - skip_bytes;
|
||||||
|
list->reloc_bos[j] = other->reloc_bos[i];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
assert(j == list->num_relocs + n);
|
||||||
|
list->num_relocs = j;
|
||||||
|
|
||||||
|
anv_reloc_list_grow_deps(list, alloc, other->dep_words);
|
||||||
|
for (uint32_t w = 0; w < other->dep_words; w++)
|
||||||
|
list->deps[w] |= other->deps[w];
|
||||||
|
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
void *
|
||||||
anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords)
|
anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords)
|
||||||
@@ -340,7 +393,45 @@ anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other)
|
|||||||
batch->next += size;
|
batch->next += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*
|
void
|
||||||
|
anv_batch_emit_batch_suffix(struct anv_batch *batch, struct anv_batch *other,
|
||||||
|
uint32_t skip_bytes)
|
||||||
|
{
|
||||||
|
uint32_t full_size = other->next - other->start;
|
||||||
|
assert(skip_bytes <= full_size);
|
||||||
|
assert(skip_bytes % 4 == 0);
|
||||||
|
uint32_t size = full_size - skip_bytes;
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
return;
|
||||||
|
assert(size % 4 == 0);
|
||||||
|
|
||||||
|
if (batch->next + size > batch->end) {
|
||||||
|
VkResult result = batch->extend_cb(batch, batch->user_data);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
anv_batch_set_error(batch, result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(batch->next + size <= batch->end);
|
||||||
|
|
||||||
|
VG(VALGRIND_CHECK_MEM_IS_DEFINED(other->start + skip_bytes, size));
|
||||||
|
memcpy(batch->next, other->start + skip_bytes, size);
|
||||||
|
|
||||||
|
uint32_t offset = batch->next - batch->start;
|
||||||
|
VkResult result = anv_reloc_list_append_range(batch->relocs, batch->alloc,
|
||||||
|
other->relocs,
|
||||||
|
skip_bytes, offset);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
anv_batch_set_error(batch, result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
batch->next += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------
|
||||||
* Functions related to anv_batch_bo
|
* Functions related to anv_batch_bo
|
||||||
*-----------------------------------------------------------------------*/
|
*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|||||||
@@ -569,17 +569,12 @@ add_aux_surface_if_supported(struct anv_device *device,
|
|||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device->info->ver == 7) {
|
|
||||||
anv_perf_warn(VK_LOG_OBJS(&image->vk.base), "Implement gfx7 HiZ");
|
|
||||||
return VK_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image->vk.mip_levels > 1) {
|
if (image->vk.mip_levels > 1) {
|
||||||
anv_perf_warn(VK_LOG_OBJS(&image->vk.base), "Enable multi-LOD HiZ");
|
anv_perf_warn(VK_LOG_OBJS(&image->vk.base), "Enable multi-LOD HiZ");
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device->info->ver == 8 && image->vk.samples > 1) {
|
if (device->info->ver <= 8 && image->vk.samples > 1) {
|
||||||
anv_perf_warn(VK_LOG_OBJS(&image->vk.base),
|
anv_perf_warn(VK_LOG_OBJS(&image->vk.base),
|
||||||
"Enable gfx8 multisampled HiZ");
|
"Enable gfx8 multisampled HiZ");
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
|
|||||||
@@ -1339,6 +1339,17 @@ struct anv_batch {
|
|||||||
|
|
||||||
void *anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords);
|
void *anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords);
|
||||||
void anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other);
|
void anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other);
|
||||||
|
|
||||||
|
/* Like anv_batch_emit_batch(), but only copies the suffix of @other
|
||||||
|
* starting at byte offset @skip_bytes (and only appends/rebases the
|
||||||
|
* relocations that fall within that suffix). Gen7-only: used to skip
|
||||||
|
* re-emitting a pipeline's VS-stage instruction group when it is
|
||||||
|
* byte-identical to what's already programmed for the previous bind
|
||||||
|
* (see cmd_buffer_flush_gfx_state).
|
||||||
|
*/
|
||||||
|
void anv_batch_emit_batch_suffix(struct anv_batch *batch,
|
||||||
|
struct anv_batch *other,
|
||||||
|
uint32_t skip_bytes);
|
||||||
struct anv_address anv_batch_address(struct anv_batch *batch, void *batch_location);
|
struct anv_address anv_batch_address(struct anv_batch *batch, void *batch_location);
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@@ -2399,6 +2410,30 @@ struct anv_cmd_graphics_state {
|
|||||||
|
|
||||||
struct anv_graphics_pipeline *pipeline;
|
struct anv_graphics_pipeline *pipeline;
|
||||||
|
|
||||||
|
/** Last emitted URB configuration (Gen7 stall optimization) */
|
||||||
|
struct intel_urb_config last_urb_cfg;
|
||||||
|
bool urb_cfg_valid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gen7 VS-stage instruction group cache. Tracks the VS/TCS/TES/GS
|
||||||
|
* shader binaries AND the effective URB config (see last_urb_cfg
|
||||||
|
* above) of the pipeline for which the group (URB + VS + HS + DS +
|
||||||
|
* GS, plus the PRM-mandated depth-stall PIPE_CONTROL before them) was
|
||||||
|
* last fully emitted into this command buffer, so a subsequent bind
|
||||||
|
* can skip re-emitting the whole group when both match the previous
|
||||||
|
* bind. Shader pointers alone are not sufficient -- URB layout also
|
||||||
|
* depends on l3_config. Always present (not #if-guarded) so this
|
||||||
|
* struct's layout doesn't depend on GFX_VER; only read/written by
|
||||||
|
* Gen7 code paths, inert everywhere else.
|
||||||
|
*/
|
||||||
|
struct anv_shader_bin *vs_stage_key[4];
|
||||||
|
bool vs_stage_key_valid;
|
||||||
|
/** True once a stall satisfying the PRM's VS-associated-3DSTATE rule
|
||||||
|
* has been emitted for the *current* draw's pipeline flush. Used to
|
||||||
|
* decide whether a later VS-descriptor/push-constant update still
|
||||||
|
* needs its own stall (see cmd_buffer_flush_gfx_state). */
|
||||||
|
bool vs_stage_stall_emitted;
|
||||||
|
|
||||||
VkRenderingFlags rendering_flags;
|
VkRenderingFlags rendering_flags;
|
||||||
VkRect2D render_area;
|
VkRect2D render_area;
|
||||||
uint32_t layer_count;
|
uint32_t layer_count;
|
||||||
@@ -2790,6 +2825,22 @@ struct anv_pipeline {
|
|||||||
struct anv_graphics_pipeline {
|
struct anv_graphics_pipeline {
|
||||||
struct anv_pipeline base;
|
struct anv_pipeline base;
|
||||||
|
|
||||||
|
/* URB configuration computed at pipeline creation time.
|
||||||
|
* Used to skip redundant URB re-emission and PIPE_CONTROL stalls on Gen7.
|
||||||
|
*/
|
||||||
|
struct intel_urb_config urb_cfg;
|
||||||
|
|
||||||
|
/* Byte length, from the start of base.batch, of the VS-stage
|
||||||
|
* instruction group (3DSTATE_URB_* + 3DSTATE_VS + 3DSTATE_HS +
|
||||||
|
* 3DSTATE_DS + 3DSTATE_GS, plus the PRM-mandated depth-stall
|
||||||
|
* PIPE_CONTROL emitted just before them). Computed unconditionally in
|
||||||
|
* genX(graphics_pipeline_emit) so this struct's layout doesn't depend
|
||||||
|
* on GFX_VER; only meaningful/consumed on Gen7 (0 elsewhere, since the
|
||||||
|
* reordering that makes the group a contiguous prefix of base.batch
|
||||||
|
* only happens for GFX_VER <= 7).
|
||||||
|
*/
|
||||||
|
uint32_t vs_stage_batch_size;
|
||||||
|
|
||||||
/* Shaders */
|
/* Shaders */
|
||||||
struct anv_shader_bin * shaders[ANV_GRAPHICS_SHADER_STAGE_COUNT];
|
struct anv_shader_bin * shaders[ANV_GRAPHICS_SHADER_STAGE_COUNT];
|
||||||
|
|
||||||
|
|||||||
@@ -3352,8 +3352,84 @@ genX(cmd_buffer_flush_gfx_state)(struct anv_cmd_buffer *cmd_buffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GFX_VER <= 7
|
||||||
|
/* Reset for this flush cycle; set true below the moment a stall
|
||||||
|
* covering the PRM's VS-associated-3DSTATE rule has actually been
|
||||||
|
* emitted, whichever path ends up doing it. */
|
||||||
|
cmd_buffer->state.gfx.vs_stage_stall_emitted = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_PIPELINE) {
|
if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_PIPELINE) {
|
||||||
|
#if GFX_VER <= 7
|
||||||
|
/* Skip re-emitting the VS-stage instruction group (URB + VS + HS +
|
||||||
|
* DS + GS, plus its PRM-mandated depth-stall PIPE_CONTROL, all kept
|
||||||
|
* contiguous at the front of the pipeline's static batch -- see
|
||||||
|
* genX(graphics_pipeline_emit)) when it is byte-identical to what's
|
||||||
|
* already programmed. This requires BOTH the same VS/TCS/TES/GS
|
||||||
|
* shader binaries AND the same effective URB config as the last
|
||||||
|
* pipeline for which we fully emitted the group -- shader pointers
|
||||||
|
* alone are not enough, since URB start/entry-count also depends on
|
||||||
|
* l3_config (see the urb_unchanged check below). Two different
|
||||||
|
* VkPipeline objects that share the same shaders and l3_config
|
||||||
|
* (e.g. VulkanMod's opaque vs. cutout terrain pipelines, which only
|
||||||
|
* differ in rasterizer cull mode) hit this path every switch.
|
||||||
|
*/
|
||||||
|
struct anv_cmd_graphics_state *gfx_state = &cmd_buffer->state.gfx;
|
||||||
|
struct anv_shader_bin *new_key[4] = {
|
||||||
|
pipeline->shaders[MESA_SHADER_VERTEX],
|
||||||
|
pipeline->shaders[MESA_SHADER_TESS_CTRL],
|
||||||
|
pipeline->shaders[MESA_SHADER_TESS_EVAL],
|
||||||
|
pipeline->shaders[MESA_SHADER_GEOMETRY],
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Same shaders alone is NOT sufficient: the actual URB byte layout
|
||||||
|
* (VSURBStartingAddress / VSNumberofURBEntries) also depends on
|
||||||
|
* l3_config (e.g. render target/attachment count shifts L3
|
||||||
|
* partitioning -- see intel_get_urb_config()), so two pipelines
|
||||||
|
* with byte-identical VS/HS/DS/GS shaders can still need a
|
||||||
|
* different URB layout. Must check both.
|
||||||
|
*/
|
||||||
|
bool urb_unchanged = gfx_state->urb_cfg_valid;
|
||||||
|
if (urb_unchanged) {
|
||||||
|
for (int s = MESA_SHADER_VERTEX; s <= MESA_SHADER_GEOMETRY; s++) {
|
||||||
|
if (intel_urb_setup_changed(&gfx_state->last_urb_cfg,
|
||||||
|
&pipeline->urb_cfg, s)) {
|
||||||
|
urb_unchanged = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool vs_stage_unchanged =
|
||||||
|
gfx_state->vs_stage_key_valid &&
|
||||||
|
memcmp(gfx_state->vs_stage_key, new_key, sizeof(new_key)) == 0 &&
|
||||||
|
urb_unchanged;
|
||||||
|
vs_stage_unchanged = false; /* DIAGNOSTIC: force full emit, see script header */
|
||||||
|
|
||||||
|
if (vs_stage_unchanged) {
|
||||||
|
anv_batch_emit_batch_suffix(&cmd_buffer->batch, &pipeline->base.batch,
|
||||||
|
pipeline->vs_stage_batch_size);
|
||||||
|
/* We skipped the group -- no stall owed for URB/VS/HS/DS/GS
|
||||||
|
* themselves, but if descriptors/push-constants are ALSO dirty
|
||||||
|
* this flush cycle, 3DSTATE_CONSTANT_VS /
|
||||||
|
* 3DSTATE_BINDING_TABLE_POINTER_VS are still about to be emitted
|
||||||
|
* below and are covered by the SAME PRM rule -- so do NOT mark
|
||||||
|
* vs_stage_stall_emitted here; let the check below decide.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->base.batch);
|
||||||
|
memcpy(gfx_state->vs_stage_key, new_key, sizeof(new_key));
|
||||||
|
gfx_state->vs_stage_key_valid = true;
|
||||||
|
gfx_state->last_urb_cfg = pipeline->urb_cfg;
|
||||||
|
gfx_state->urb_cfg_valid = true;
|
||||||
|
/* Full emit -- the PIPE_CONTROL baked into the pipeline's static
|
||||||
|
* batch (by emit_urb_setup) was actually sent, covering the
|
||||||
|
* whole PRM-mandated group for this flush cycle. */
|
||||||
|
gfx_state->vs_stage_stall_emitted = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->base.batch);
|
anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->base.batch);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If the pipeline changed, we may need to re-allocate push constant
|
/* If the pipeline changed, we may need to re-allocate push constant
|
||||||
* space in the URB.
|
* space in the URB.
|
||||||
@@ -3362,8 +3438,9 @@ genX(cmd_buffer_flush_gfx_state)(struct anv_cmd_buffer *cmd_buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if GFX_VER <= 7
|
#if GFX_VER <= 7
|
||||||
if (cmd_buffer->state.descriptors_dirty & VK_SHADER_STAGE_VERTEX_BIT ||
|
if (!cmd_buffer->state.gfx.vs_stage_stall_emitted &&
|
||||||
cmd_buffer->state.push_constants_dirty & VK_SHADER_STAGE_VERTEX_BIT) {
|
(cmd_buffer->state.descriptors_dirty & VK_SHADER_STAGE_VERTEX_BIT ||
|
||||||
|
cmd_buffer->state.push_constants_dirty & VK_SHADER_STAGE_VERTEX_BIT)) {
|
||||||
/* From the IVB PRM Vol. 2, Part 1, Section 3.2.1:
|
/* From the IVB PRM Vol. 2, Part 1, Section 3.2.1:
|
||||||
*
|
*
|
||||||
* "A PIPE_CONTROL with Post-Sync Operation set to 1h and a depth
|
* "A PIPE_CONTROL with Post-Sync Operation set to 1h and a depth
|
||||||
@@ -3380,6 +3457,7 @@ genX(cmd_buffer_flush_gfx_state)(struct anv_cmd_buffer *cmd_buffer)
|
|||||||
pc.Address = cmd_buffer->device->workaround_address;
|
pc.Address = cmd_buffer->device->workaround_address;
|
||||||
anv_debug_dump_pc(pc);
|
anv_debug_dump_pc(pc);
|
||||||
}
|
}
|
||||||
|
cmd_buffer->state.gfx.vs_stage_stall_emitted = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -325,6 +325,28 @@ emit_urb_setup(struct anv_graphics_pipeline *pipeline)
|
|||||||
entry_size[i] = prog_data ? prog_data->urb_entry_size : 1;
|
entry_size[i] = prog_data ? prog_data->urb_entry_size : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GFX_VER <= 7
|
||||||
|
/* Compute and cache the *actual* URB config -- not just the shaders'
|
||||||
|
* requested entry sizes, but the real per-stage start offsets and
|
||||||
|
* entry counts, which also depend on l3_config (e.g. attachment/RT
|
||||||
|
* count can shift L3 partitioning). This is the correct, complete key
|
||||||
|
* for cmd_buffer_flush_gfx_state() to decide whether the VS-stage
|
||||||
|
* instruction group can be skipped on a later bind: two pipelines
|
||||||
|
* with byte-identical VS/HS/DS/GS shaders can still require a
|
||||||
|
* different URB layout if their l3_config differs -- comparing shader
|
||||||
|
* pointers alone is not sufficient.
|
||||||
|
*/
|
||||||
|
pipeline->urb_cfg = (struct intel_urb_config) {
|
||||||
|
.size = { entry_size[0], entry_size[1], entry_size[2], entry_size[3] },
|
||||||
|
};
|
||||||
|
bool urb_constrained;
|
||||||
|
intel_get_urb_config(pipeline->base.device->info, pipeline->base.l3_config,
|
||||||
|
pipeline->active_stages &
|
||||||
|
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
|
||||||
|
pipeline->active_stages & VK_SHADER_STAGE_GEOMETRY_BIT,
|
||||||
|
&pipeline->urb_cfg, &urb_constrained);
|
||||||
|
#endif
|
||||||
|
|
||||||
genX(emit_urb_setup)(pipeline->base.device, &pipeline->base.batch,
|
genX(emit_urb_setup)(pipeline->base.device, &pipeline->base.batch,
|
||||||
pipeline->base.l3_config,
|
pipeline->base.l3_config,
|
||||||
pipeline->active_stages, entry_size);
|
pipeline->active_stages, entry_size);
|
||||||
@@ -1827,6 +1849,16 @@ genX(graphics_pipeline_emit)(struct anv_graphics_pipeline *pipeline,
|
|||||||
{
|
{
|
||||||
emit_urb_setup(pipeline);
|
emit_urb_setup(pipeline);
|
||||||
|
|
||||||
|
/* DIAGNOSTIC v2: VS/HS/DS/GS reordering reverted -- back to vanilla
|
||||||
|
* emission position (after vertex_input, below). vs_stage_batch_size
|
||||||
|
* is set to 0 here since it's meaningless with the group no longer
|
||||||
|
* contiguous with URB; this is fine because diagnostic v1 already
|
||||||
|
* force-disabled the skip path that would have used it.
|
||||||
|
*/
|
||||||
|
#if GFX_VER <= 7
|
||||||
|
pipeline->vs_stage_batch_size = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(state->rs != NULL);
|
assert(state->rs != NULL);
|
||||||
emit_rs_state(pipeline, state->ia, state->rs, state->ms, state->rp);
|
emit_rs_state(pipeline, state->ia, state->rs, state->ms, state->rp);
|
||||||
emit_ms_state(pipeline, state->ms);
|
emit_ms_state(pipeline, state->ms);
|
||||||
@@ -1856,6 +1888,8 @@ genX(graphics_pipeline_emit)(struct anv_graphics_pipeline *pipeline,
|
|||||||
|
|
||||||
emit_vertex_input(pipeline, state->vi);
|
emit_vertex_input(pipeline, state->vi);
|
||||||
|
|
||||||
|
/* DIAGNOSTIC v2: always emit here (both Gen7 and Gen8+), matching
|
||||||
|
* vanilla hasvk's original position exactly. */
|
||||||
emit_3dstate_vs(pipeline);
|
emit_3dstate_vs(pipeline);
|
||||||
emit_3dstate_hs_te_ds(pipeline, state->ts);
|
emit_3dstate_hs_te_ds(pipeline, state->ts);
|
||||||
emit_3dstate_gs(pipeline, state->rs);
|
emit_3dstate_gs(pipeline, state->rs);
|
||||||
|
|||||||
@@ -232,7 +232,8 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
|
|||||||
*/
|
*/
|
||||||
if ((cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_PIPELINE) ||
|
if ((cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_PIPELINE) ||
|
||||||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_IA_PRIMITIVE_TOPOLOGY) ||
|
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_IA_PRIMITIVE_TOPOLOGY) ||
|
||||||
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES)) {
|
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES) ||
|
||||||
|
BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_RS_LINE_STIPPLE)) {
|
||||||
VkPolygonMode dynamic_raster_mode =
|
VkPolygonMode dynamic_raster_mode =
|
||||||
genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline,
|
genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline,
|
||||||
dyn->ia.primitive_topology);
|
dyn->ia.primitive_topology);
|
||||||
@@ -243,10 +244,13 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer)
|
|||||||
|
|
||||||
.ThreadDispatchEnable = anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT) &&
|
.ThreadDispatchEnable = anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT) &&
|
||||||
(pipeline->force_fragment_thread_dispatch ||
|
(pipeline->force_fragment_thread_dispatch ||
|
||||||
!anv_cmd_buffer_all_color_write_masked(cmd_buffer)),
|
!anv_cmd_buffer_all_color_write_masked(cmd_buffer)),
|
||||||
.MultisampleRasterizationMode =
|
.MultisampleRasterizationMode =
|
||||||
genX(ms_rasterization_mode)(pipeline,
|
genX(ms_rasterization_mode)(pipeline,
|
||||||
dynamic_raster_mode),
|
dynamic_raster_mode),
|
||||||
|
#if GFX_VERx10 == 70
|
||||||
|
.LineStippleEnable = dyn->rs.line.stipple.enable,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
GENX(3DSTATE_WM_pack)(NULL, dwords, &wm);
|
GENX(3DSTATE_WM_pack)(NULL, dwords, &wm);
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user