diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index e58e7de3fb8..36698d96357 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -5890,6 +5890,22 @@ get_image_coords(isel_context* ctx, const nir_intrinsic_instr* instr) coords[i] = emit_extract_vector(ctx, src0, i, v1); } + if (ctx->options->key.image_2d_view_of_3d && + dim == GLSL_SAMPLER_DIM_2D && !is_array) { + /* The hw can't bind a slice of a 3D image as a 2D image, because it + * ignores BASE_ARRAY if the target is 3D. The workaround is to read + * BASE_ARRAY and set it as the 3rd address operand for all 2D images. + */ + assert(ctx->options->chip_class == GFX9); + Temp rsrc = bld.as_uniform(get_ssa_temp(ctx, instr->src[0].ssa)); + Temp rsrc_word5 = emit_extract_vector(ctx, rsrc, 5, v1); + /* Extract the BASE_ARRAY field [0:12] from the descriptor. */ + Temp first_layer = + bld.vop3(aco_opcode::v_bfe_u32, bld.def(v1), rsrc_word5, + Operand::c32(0u), Operand::c32(13u)); + coords.emplace_back(first_layer); + } + if (instr->intrinsic == nir_intrinsic_bindless_image_load || instr->intrinsic == nir_intrinsic_bindless_image_sparse_load || instr->intrinsic == nir_intrinsic_bindless_image_store) { diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index 15805a2c971..00070969b81 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -3124,6 +3124,7 @@ radv_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCr bool image_float32_atomics = false; bool vs_prologs = false; bool global_bo_list = false; + bool image_2d_view_of_3d = false; /* Check enabled features */ if (pCreateInfo->pEnabledFeatures) { @@ -3190,6 +3191,12 @@ radv_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCr global_bo_list = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT: { + const VkPhysicalDeviceImage2DViewOf3DFeaturesEXT *features = (const void *)ext; + if (features->image2DViewOf3D) + image_2d_view_of_3d = true; + break; + } default: break; } @@ -3252,6 +3259,8 @@ radv_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCr device->image_float32_atomics = image_float32_atomics; + device->image_2d_view_of_3d = image_2d_view_of_3d; + radv_init_shader_arenas(device); device->overallocation_disallowed = overallocation_disallowed; diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index 92785901a67..2e293fa6e7d 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -3061,6 +3061,9 @@ radv_generate_pipeline_key(const struct radv_pipeline *pipeline, VkPipelineCreat key.disable_aniso_single_level = device->instance->disable_aniso_single_level && device->physical_device->rad_info.chip_class < GFX8; + key.image_2d_view_of_3d = device->image_2d_view_of_3d && + device->physical_device->rad_info.chip_class == GFX9; + return key; } diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index aa94c87c307..53b5a5dd5ba 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -839,6 +839,9 @@ struct radv_device { /* Whether shader image 32-bit float atomics are enabled. */ bool image_float32_atomics; + /* Whether 2D views of 3D image is enabled. */ + bool image_2d_view_of_3d; + /* Whether anisotropy is forced with RADV_TEX_ANISO (-1 is disabled). */ int force_aniso; diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h index 97f21009285..7f7a95e721b 100644 --- a/src/amd/vulkan/radv_shader.h +++ b/src/amd/vulkan/radv_shader.h @@ -65,6 +65,7 @@ struct radv_pipeline_key { uint32_t adjust_frag_coord_z : 1; uint32_t disable_aniso_single_level : 1; uint32_t disable_sinking_load_input_fs : 1; + uint32_t image_2d_view_of_3d : 1; struct { uint32_t instance_rate_inputs;