Up to this point we were using the gen8+ structures to program border colors. This commit sets up the correct border colors for HSW & IVB.
On HSW: This fixes 140 failures of : dEQP-VK.pipeline.sampler.view_type.*.format.*.address_modes.all_mode_clamp_to_border_* (11 failures remain out of 840 tests) Failures : - dEQP-VK.pipeline.sampler.view_type.*.format.b4g4r4a4_unorm_pack16.address_modes.all_mode_clamp_to_border_* There is no equivalent of b4g4r4a4_unorm on the GLES31 test suite and the documentation doesn't seem to list this format in any of the 8/16/32bits supported ones. - dEQP-VK.pipeline.sampler.view_type.2d.format.r32g32b32_uint.address_modes.all_mode_clamp_to_border_* Some GLES31 equivalent tests are failing too : dEQP-GLES31.functional.texture.border_clamp.formats.rgba32ui.nearest_size_pot dEQP-GLES31.functional.texture.border_clamp.formats.rgba32ui.nearest_size_npot - dEQP-VK.pipeline.sampler.view_type.2d.format.r32_uint.address_modes.all_mode_clamp_to_border_* Seems to exhibit the same issue as r32g32b32_uint (some of the corners of the sampled texture are missing). On IVB: This fixes 73 failures of : dEQP-VK.pipeline.sampler.view_type.*.format.*.address_modes.all_mode_clamp_to_border_* (139 failures remain out of 795 tests) All tests using *_sfloat, *_unorm, *_snorm formats are passing. Failures : - dEQP-VK.pipeline.sampler.view_type.*.format.r8g8b8_uint.address_modes.all_mode_clamp_to_border_* dEQP-VK.pipeline.sampler.view_type.*.format.r16g16b16_sint.address_modes.all_mode_clamp_to_border_* dEQP-VK.pipeline.sampler.view_type.*.format.r16g16b16_sfloat.address_modes.all_mode_clamp_to_border_* These tests were triggering an assert before and remain broken. This seems to be a hardware limitation we can't express through the Vulkan API. - Most of uint formats produce invalid results (some with invalid border color, some with invalid texture data) with exception of : dEQP-VK.pipeline.sampler.view_type.*.format.r32_sint.address_modes.all_mode_clamp_to_border_* v2: Implement Jason's suggestion to have all sampler configuration ready at sampler cration Also fix remaining issues with 1 & 2 components texture Signed-off-by: Lionel Landwerlin <lionel.g.landwer...@intel.com> --- src/intel/vulkan/anv_device.c | 42 ------- src/intel/vulkan/anv_genX.h | 3 +- src/intel/vulkan/anv_private.h | 11 +- src/intel/vulkan/genX_cmd_buffer.c | 5 +- src/intel/vulkan/genX_state.c | 229 ++++++++++++++++++++++++++++++++++--- 5 files changed, 228 insertions(+), 62 deletions(-) diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index c995630..3ad01b9 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -724,46 +724,6 @@ anv_queue_finish(struct anv_queue *queue) { } -static struct anv_state -anv_state_pool_emit_data(struct anv_state_pool *pool, size_t size, size_t align, const void *p) -{ - struct anv_state state; - - state = anv_state_pool_alloc(pool, size, align); - memcpy(state.map, p, size); - - if (!pool->block_pool->device->info.has_llc) - anv_state_clflush(state); - - return state; -} - -struct gen8_border_color { - union { - float float32[4]; - uint32_t uint32[4]; - }; - /* Pad out to 64 bytes */ - uint32_t _pad[12]; -}; - -static void -anv_device_init_border_colors(struct anv_device *device) -{ - static const struct gen8_border_color border_colors[] = { - [VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK] = { .float32 = { 0.0, 0.0, 0.0, 0.0 } }, - [VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK] = { .float32 = { 0.0, 0.0, 0.0, 1.0 } }, - [VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE] = { .float32 = { 1.0, 1.0, 1.0, 1.0 } }, - [VK_BORDER_COLOR_INT_TRANSPARENT_BLACK] = { .uint32 = { 0, 0, 0, 0 } }, - [VK_BORDER_COLOR_INT_OPAQUE_BLACK] = { .uint32 = { 0, 0, 0, 1 } }, - [VK_BORDER_COLOR_INT_OPAQUE_WHITE] = { .uint32 = { 1, 1, 1, 1 } }, - }; - - device->border_colors = anv_state_pool_emit_data(&device->dynamic_state_pool, - sizeof(border_colors), 64, - border_colors); -} - VkResult anv_device_submit_simple_batch(struct anv_device *device, struct anv_batch *batch) @@ -943,8 +903,6 @@ VkResult anv_CreateDevice( anv_device_init_blorp(device); - anv_device_init_border_colors(device); - *pDevice = anv_device_to_handle(device); return VK_SUCCESS; diff --git a/src/intel/vulkan/anv_genX.h b/src/intel/vulkan/anv_genX.h index d4ed325..ebd0ee7 100644 --- a/src/intel/vulkan/anv_genX.h +++ b/src/intel/vulkan/anv_genX.h @@ -28,7 +28,7 @@ /* * Gen-specific function declarations. This header must *not* be included * directly. Instead, it is included multiple times by anv_private.h. - * + * * In this header file, the usual genx() macro is available. */ @@ -37,6 +37,7 @@ #endif VkResult genX(init_device_state)(struct anv_device *device); +uint32_t genX(sampler_index)(VkFormat format); void genX(cmd_buffer_emit_state_base_address)(struct anv_cmd_buffer *cmd_buffer); diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 0e25827..2cca5c3 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -552,6 +552,7 @@ struct anv_device { struct blorp_context blorp; struct anv_state border_colors; + uint32_t border_color_align; struct anv_queue queue; @@ -1642,7 +1643,15 @@ void anv_buffer_view_fill_image_param(struct anv_device *device, struct brw_image_param *param); struct anv_sampler { - uint32_t state[4]; + /* On Haswell we need to have all samplers declined per number of component + * for each possible integer format (8, 16 and 32 bits) and we also need + * sampler configurations for normalized and floating point formats : + * + * 4 components * 3 integer formats + floats&normalized = 13 configurations + * + * On all other platforms, only state[0] is used. + */ + uint32_t state[13][4]; }; struct anv_framebuffer { diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index 5ea7c5f..88ed284 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -905,8 +905,9 @@ emit_samplers(struct anv_cmd_buffer *cmd_buffer, if (sampler == NULL) continue; - memcpy(state->map + (s * 16), - sampler->state, sizeof(sampler->state)); + uint32_t sampler_index = genX(sampler_index)(desc->image_view->vk_format); + memcpy(state->map + (s * 16), sampler->state[sampler_index], + GENX(SAMPLER_STATE_length) * 4); } if (!cmd_buffer->device->info.has_llc) diff --git a/src/intel/vulkan/genX_state.c b/src/intel/vulkan/genX_state.c index be1bd78..61aeef3 100644 --- a/src/intel/vulkan/genX_state.c +++ b/src/intel/vulkan/genX_state.c @@ -28,11 +28,172 @@ #include <fcntl.h> #include "anv_private.h" +#include "vk_format_info.h" #include "common/gen_sample_positions.h" #include "genxml/gen_macros.h" #include "genxml/genX_pack.h" +uint32_t +genX(sampler_index)(VkFormat format) +{ +#if ! GEN_IS_HASWELL + return 0; +#else + if (!vk_format_is_integer(format)) + return 0; + + uint32_t index = 3 * (vk_format_n_channels(format) - 1); + + switch(vk_format_max_bpc(format)) { + case 8: + index += 1; + break; + + case 10: + case 16: + case 24: + index += 2; + break; + + case 32: + index += 3; + break; + default: + anv_finishme("unsupported sampling format with border color"); + return 0; + } + + return index; +#endif +} + +#define BORDER_COLOR(name, r, g, b, a) { \ + .BorderColor##name##Red = r, \ + .BorderColor##name##Green = g, \ + .BorderColor##name##Blue = b, \ + .BorderColor##name##Alpha = a, \ + } + +static void +border_colors_setup(struct anv_device *device) +{ +#if GEN_IS_HASWELL + /* We order things differently for Haswell and only ever care about the + * color, not whether the color integer or float (see genX(sampler_index)). + * This consumes 13 * 3 * 512 ~= 20kb of memory. */ + static const struct GENX(SAMPLER_BORDER_COLOR_STATE) border_colors[] = { + /* Transparent black: */ + BORDER_COLOR(Float, 0.0, 0.0, 0.0, 0.0), + /* - R textures */ + BORDER_COLOR(8bit, 0, 0, 0, 1), + BORDER_COLOR(16bit, 0, 0, 0, 1), + BORDER_COLOR(32bit, 0, 0, 0, 1), + /* - RG textures */ + BORDER_COLOR(8bit, 0, 0, 0, 1), + BORDER_COLOR(16bit, 0, 0, 0, 1), + BORDER_COLOR(32bit, 0, 0, 0, 1), + /* - RGB textures */ + BORDER_COLOR(8bit, 0, 0, 0, 1), + BORDER_COLOR(16bit, 0, 0, 0, 1), + BORDER_COLOR(32bit, 0, 0, 0, 1), + /* - RBGA textures */ + BORDER_COLOR(8bit, 0, 0, 0, 0), + BORDER_COLOR(16bit, 0, 0, 0, 0), + BORDER_COLOR(32bit, 0, 0, 0, 0), + + /* Opaque black: */ + BORDER_COLOR(Float, 0.0, 0.0, 0.0, 1.0), + /* - R textures */ + BORDER_COLOR(8bit, 0, 0, 0, 1), + BORDER_COLOR(16bit, 0, 0, 0, 1), + BORDER_COLOR(32bit, 0, 0, 0, 1), + /* - RG textures */ + BORDER_COLOR(8bit, 0, 0, 0, 1), + BORDER_COLOR(16bit, 0, 0, 0, 1), + BORDER_COLOR(32bit, 0, 0, 0, 1), + /* - RGB textures */ + BORDER_COLOR(8bit, 0, 0, 0, 1), + BORDER_COLOR(16bit, 0, 0, 0, 1), + BORDER_COLOR(32bit, 0, 0, 0, 1), + /* - RGBA textures */ + BORDER_COLOR(8bit, 0, 0, 0, 1), + BORDER_COLOR(16bit, 0, 0, 0, 1), + BORDER_COLOR(32bit, 0, 0, 0, 1), + + /* Opaque white: */ + BORDER_COLOR(Float, 1.0, 1.0, 1.0, 1.0), + /* - R textures */ + BORDER_COLOR(8bit, 1, 0, 0, 1), + BORDER_COLOR(16bit, 1, 0, 0, 1), + BORDER_COLOR(32bit, 1, 0, 0, 1), + /* - RG textures */ + BORDER_COLOR(8bit, 1, 1, 0, 1), + BORDER_COLOR(16bit, 1, 1, 0, 1), + BORDER_COLOR(32bit, 1, 1, 0, 1), + /* - RGB textures */ + BORDER_COLOR(8bit, 1, 1, 1, 1), + BORDER_COLOR(16bit, 1, 1, 1, 1), + BORDER_COLOR(32bit, 1, 1, 1, 1), + /* - RGBA textures */ + BORDER_COLOR(8bit, 1, 1, 1, 1), + BORDER_COLOR(16bit, 1, 1, 1, 1), + BORDER_COLOR(32bit, 1, 1, 1, 1), + }; + static_assert(sizeof(struct anv_sampler) / (4 * GENX(SAMPLER_STATE_length)) == + ARRAY_SIZE(border_colors) / 3, + "struct anv_sampler size doesn't match border_colors"); + device->border_color_align = 512; +#elif GEN_GEN == 7 + static const struct GENX(SAMPLER_BORDER_COLOR_STATE) border_colors[] = { + [VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK] = + BORDER_COLOR(Float, 0.0, 0.0, 0.0, 0.0), + [VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK] = + BORDER_COLOR(Float, 0.0, 0.0, 0.0, 1.0), + [VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE] = + BORDER_COLOR(Float, 1.0, 1.0, 1.0, 1.0), + [VK_BORDER_COLOR_INT_TRANSPARENT_BLACK] = + BORDER_COLOR(Float, 0.0, 0.0, 0.0, 0.0), + [VK_BORDER_COLOR_INT_OPAQUE_BLACK] = + BORDER_COLOR(Float, 0.0, 0.0, 0.0, 1.0), + [VK_BORDER_COLOR_INT_OPAQUE_WHITE] = + BORDER_COLOR(Float, 1.0, 1.0, 1.0, 1.0) + }; + device->border_color_align = 64; +#else /* GEN_GEN >= 8 */ + static const struct GENX(SAMPLER_BORDER_COLOR_STATE) border_colors[] = { + [VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK] = + BORDER_COLOR(Float, 0.0, 0.0, 0.0, 0.0), + [VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK] = + BORDER_COLOR(Float, 0.0, 0.0, 0.0, 1.0), + [VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE] = + BORDER_COLOR(Float, 1.0, 1.0, 1.0, 1.0), + [VK_BORDER_COLOR_INT_TRANSPARENT_BLACK] = + BORDER_COLOR(32bit, 0, 0, 0, 0), + [VK_BORDER_COLOR_INT_OPAQUE_BLACK] = + BORDER_COLOR(32bit, 0, 0, 0, 1), + [VK_BORDER_COLOR_INT_OPAQUE_WHITE] = + BORDER_COLOR(32bit, 1, 1, 1, 1) + }; + device->border_color_align = 64; +#endif + + device->border_colors = + anv_state_pool_alloc(&device->dynamic_state_pool, + ARRAY_SIZE(border_colors) * device->border_color_align, + device->border_color_align); + + for (uint32_t i = 0; i < ARRAY_SIZE(border_colors); i++) { + GENX(SAMPLER_BORDER_COLOR_STATE_pack)( + NULL, + device->border_colors.map + i * device->border_color_align, + &border_colors[i]); + } + + if (!device->info.has_llc) + anv_state_clflush(device->border_colors); +} + VkResult genX(init_device_state)(struct anv_device *device) { @@ -91,6 +252,8 @@ genX(init_device_state)(struct anv_device *device) assert(batch.next <= batch.end); + border_colors_setup(device); + return anv_device_submit_simple_batch(device, &batch); } @@ -148,24 +311,34 @@ static const uint32_t vk_to_gen_shadow_compare_op[] = { [VK_COMPARE_OP_ALWAYS] = PREFILTEROPNEVER, }; -VkResult genX(CreateSampler)( - VkDevice _device, +static void +pack_sampler_state( + struct anv_device * device, + struct anv_sampler * sampler, const VkSamplerCreateInfo* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSampler* pSampler) + uint32_t offset, + void * dest) { - ANV_FROM_HANDLE(anv_device, device, _device); - struct anv_sampler *sampler; - - assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); +#if GEN_IS_HASWELL + static const uint32_t haswell_border_color_offset[] = { + [VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK] = 0, + [VK_BORDER_COLOR_INT_TRANSPARENT_BLACK] = 0, - sampler = vk_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8, - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - if (!sampler) - return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + [VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK] = 1, + [VK_BORDER_COLOR_INT_OPAQUE_BLACK] = 1, - uint32_t border_color_offset = device->border_colors.offset + - pCreateInfo->borderColor * 64; + [VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE] = 2, + [VK_BORDER_COLOR_INT_OPAQUE_WHITE] = 2, + }; + uint32_t color_index = + ARRAY_SIZE(sampler->state) * + haswell_border_color_offset[pCreateInfo->borderColor] + offset; +#else + uint32_t color_index = pCreateInfo->borderColor; +#endif + uint32_t color_offset = + device->border_colors.offset + + color_index * device->border_color_align; struct GENX(SAMPLER_STATE) sampler_state = { .SamplerDisable = false, @@ -195,7 +368,7 @@ VkResult genX(CreateSampler)( .ShadowFunction = vk_to_gen_shadow_compare_op[pCreateInfo->compareOp], .CubeSurfaceControlMode = OVERRIDE, - .BorderColorPointer = border_color_offset, + .BorderColorPointer = color_offset, #if GEN_GEN >= 8 .LODClampMagnificationMode = MIPNONE, @@ -215,7 +388,31 @@ VkResult genX(CreateSampler)( .TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressModeW], }; - GENX(SAMPLER_STATE_pack)(NULL, sampler->state, &sampler_state); + GENX(SAMPLER_STATE_pack)(NULL, dest, &sampler_state); +} + + +VkResult genX(CreateSampler)( + VkDevice _device, + const VkSamplerCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSampler* pSampler) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + struct anv_sampler *sampler; + + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); + + sampler = vk_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!sampler) + return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + + pack_sampler_state(device, sampler, pCreateInfo, 0, sampler->state[0]); +#if GEN_IS_HASWELL + for (uint32_t i = 1; i < ARRAY_SIZE(sampler->state); i++) + pack_sampler_state(device, sampler, pCreateInfo, i, sampler->state[i]); +#endif *pSampler = anv_sampler_to_handle(sampler); -- 2.9.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev