1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2016 Red Hat 3b8e80941Smrg * based on intel anv code: 4b8e80941Smrg * Copyright © 2015 Intel Corporation 5b8e80941Smrg * 6b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 8b8e80941Smrg * to deal in the Software without restriction, including without limitation 9b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 11b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 12b8e80941Smrg * 13b8e80941Smrg * The above copyright notice and this permission notice (including the next 14b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 15b8e80941Smrg * Software. 16b8e80941Smrg * 17b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23b8e80941Smrg * IN THE SOFTWARE. 24b8e80941Smrg */ 25b8e80941Smrg 26b8e80941Smrg#include "radv_meta.h" 27b8e80941Smrg 28b8e80941Smrg#include <fcntl.h> 29b8e80941Smrg#include <limits.h> 30b8e80941Smrg#include <pwd.h> 31b8e80941Smrg#include <sys/stat.h> 32b8e80941Smrg 33b8e80941Smrgvoid 34b8e80941Smrgradv_meta_save(struct radv_meta_saved_state *state, 35b8e80941Smrg struct radv_cmd_buffer *cmd_buffer, uint32_t flags) 36b8e80941Smrg{ 37b8e80941Smrg VkPipelineBindPoint bind_point = 38b8e80941Smrg flags & RADV_META_SAVE_GRAPHICS_PIPELINE ? 39b8e80941Smrg VK_PIPELINE_BIND_POINT_GRAPHICS : 40b8e80941Smrg VK_PIPELINE_BIND_POINT_COMPUTE; 41b8e80941Smrg struct radv_descriptor_state *descriptors_state = 42b8e80941Smrg radv_get_descriptors_state(cmd_buffer, bind_point); 43b8e80941Smrg 44b8e80941Smrg assert(flags & (RADV_META_SAVE_GRAPHICS_PIPELINE | 45b8e80941Smrg RADV_META_SAVE_COMPUTE_PIPELINE)); 46b8e80941Smrg 47b8e80941Smrg state->flags = flags; 48b8e80941Smrg 49b8e80941Smrg if (state->flags & RADV_META_SAVE_GRAPHICS_PIPELINE) { 50b8e80941Smrg assert(!(state->flags & RADV_META_SAVE_COMPUTE_PIPELINE)); 51b8e80941Smrg 52b8e80941Smrg state->old_pipeline = cmd_buffer->state.pipeline; 53b8e80941Smrg 54b8e80941Smrg /* Save all viewports. */ 55b8e80941Smrg state->viewport.count = cmd_buffer->state.dynamic.viewport.count; 56b8e80941Smrg typed_memcpy(state->viewport.viewports, 57b8e80941Smrg cmd_buffer->state.dynamic.viewport.viewports, 58b8e80941Smrg MAX_VIEWPORTS); 59b8e80941Smrg 60b8e80941Smrg /* Save all scissors. */ 61b8e80941Smrg state->scissor.count = cmd_buffer->state.dynamic.scissor.count; 62b8e80941Smrg typed_memcpy(state->scissor.scissors, 63b8e80941Smrg cmd_buffer->state.dynamic.scissor.scissors, 64b8e80941Smrg MAX_SCISSORS); 65b8e80941Smrg 66b8e80941Smrg /* The most common meta operations all want to have the 67b8e80941Smrg * viewport reset and any scissors disabled. The rest of the 68b8e80941Smrg * dynamic state should have no effect. 69b8e80941Smrg */ 70b8e80941Smrg cmd_buffer->state.dynamic.viewport.count = 0; 71b8e80941Smrg cmd_buffer->state.dynamic.scissor.count = 0; 72b8e80941Smrg cmd_buffer->state.dirty |= 1 << VK_DYNAMIC_STATE_VIEWPORT | 73b8e80941Smrg 1 << VK_DYNAMIC_STATE_SCISSOR; 74b8e80941Smrg } 75b8e80941Smrg 76b8e80941Smrg if (state->flags & RADV_META_SAVE_COMPUTE_PIPELINE) { 77b8e80941Smrg assert(!(state->flags & RADV_META_SAVE_GRAPHICS_PIPELINE)); 78b8e80941Smrg 79b8e80941Smrg state->old_pipeline = cmd_buffer->state.compute_pipeline; 80b8e80941Smrg } 81b8e80941Smrg 82b8e80941Smrg if (state->flags & RADV_META_SAVE_DESCRIPTORS) { 83b8e80941Smrg state->old_descriptor_set0 = descriptors_state->sets[0]; 84b8e80941Smrg if (!(descriptors_state->valid & 1) || !state->old_descriptor_set0) 85b8e80941Smrg state->flags &= ~RADV_META_SAVE_DESCRIPTORS; 86b8e80941Smrg } 87b8e80941Smrg 88b8e80941Smrg if (state->flags & RADV_META_SAVE_CONSTANTS) { 89b8e80941Smrg memcpy(state->push_constants, cmd_buffer->push_constants, 90b8e80941Smrg MAX_PUSH_CONSTANTS_SIZE); 91b8e80941Smrg } 92b8e80941Smrg 93b8e80941Smrg if (state->flags & RADV_META_SAVE_PASS) { 94b8e80941Smrg state->pass = cmd_buffer->state.pass; 95b8e80941Smrg state->subpass = cmd_buffer->state.subpass; 96b8e80941Smrg state->framebuffer = cmd_buffer->state.framebuffer; 97b8e80941Smrg state->attachments = cmd_buffer->state.attachments; 98b8e80941Smrg state->render_area = cmd_buffer->state.render_area; 99b8e80941Smrg } 100b8e80941Smrg} 101b8e80941Smrg 102b8e80941Smrgvoid 103b8e80941Smrgradv_meta_restore(const struct radv_meta_saved_state *state, 104b8e80941Smrg struct radv_cmd_buffer *cmd_buffer) 105b8e80941Smrg{ 106b8e80941Smrg VkPipelineBindPoint bind_point = 107b8e80941Smrg state->flags & RADV_META_SAVE_GRAPHICS_PIPELINE ? 108b8e80941Smrg VK_PIPELINE_BIND_POINT_GRAPHICS : 109b8e80941Smrg VK_PIPELINE_BIND_POINT_COMPUTE; 110b8e80941Smrg 111b8e80941Smrg if (state->flags & RADV_META_SAVE_GRAPHICS_PIPELINE) { 112b8e80941Smrg radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), 113b8e80941Smrg VK_PIPELINE_BIND_POINT_GRAPHICS, 114b8e80941Smrg radv_pipeline_to_handle(state->old_pipeline)); 115b8e80941Smrg 116b8e80941Smrg cmd_buffer->state.dirty |= RADV_CMD_DIRTY_PIPELINE; 117b8e80941Smrg 118b8e80941Smrg /* Restore all viewports. */ 119b8e80941Smrg cmd_buffer->state.dynamic.viewport.count = state->viewport.count; 120b8e80941Smrg typed_memcpy(cmd_buffer->state.dynamic.viewport.viewports, 121b8e80941Smrg state->viewport.viewports, 122b8e80941Smrg MAX_VIEWPORTS); 123b8e80941Smrg 124b8e80941Smrg /* Restore all scissors. */ 125b8e80941Smrg cmd_buffer->state.dynamic.scissor.count = state->scissor.count; 126b8e80941Smrg typed_memcpy(cmd_buffer->state.dynamic.scissor.scissors, 127b8e80941Smrg state->scissor.scissors, 128b8e80941Smrg MAX_SCISSORS); 129b8e80941Smrg 130b8e80941Smrg cmd_buffer->state.dirty |= 1 << VK_DYNAMIC_STATE_VIEWPORT | 131b8e80941Smrg 1 << VK_DYNAMIC_STATE_SCISSOR; 132b8e80941Smrg } 133b8e80941Smrg 134b8e80941Smrg if (state->flags & RADV_META_SAVE_COMPUTE_PIPELINE) { 135b8e80941Smrg radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), 136b8e80941Smrg VK_PIPELINE_BIND_POINT_COMPUTE, 137b8e80941Smrg radv_pipeline_to_handle(state->old_pipeline)); 138b8e80941Smrg } 139b8e80941Smrg 140b8e80941Smrg if (state->flags & RADV_META_SAVE_DESCRIPTORS) { 141b8e80941Smrg radv_set_descriptor_set(cmd_buffer, bind_point, 142b8e80941Smrg state->old_descriptor_set0, 0); 143b8e80941Smrg } 144b8e80941Smrg 145b8e80941Smrg if (state->flags & RADV_META_SAVE_CONSTANTS) { 146b8e80941Smrg memcpy(cmd_buffer->push_constants, state->push_constants, 147b8e80941Smrg MAX_PUSH_CONSTANTS_SIZE); 148b8e80941Smrg cmd_buffer->push_constant_stages |= VK_SHADER_STAGE_COMPUTE_BIT; 149b8e80941Smrg 150b8e80941Smrg if (state->flags & RADV_META_SAVE_GRAPHICS_PIPELINE) { 151b8e80941Smrg cmd_buffer->push_constant_stages |= VK_SHADER_STAGE_ALL_GRAPHICS; 152b8e80941Smrg } 153b8e80941Smrg } 154b8e80941Smrg 155b8e80941Smrg if (state->flags & RADV_META_SAVE_PASS) { 156b8e80941Smrg cmd_buffer->state.pass = state->pass; 157b8e80941Smrg cmd_buffer->state.subpass = state->subpass; 158b8e80941Smrg cmd_buffer->state.framebuffer = state->framebuffer; 159b8e80941Smrg cmd_buffer->state.attachments = state->attachments; 160b8e80941Smrg cmd_buffer->state.render_area = state->render_area; 161b8e80941Smrg if (state->subpass) 162b8e80941Smrg cmd_buffer->state.dirty |= RADV_CMD_DIRTY_FRAMEBUFFER; 163b8e80941Smrg } 164b8e80941Smrg} 165b8e80941Smrg 166b8e80941SmrgVkImageViewType 167b8e80941Smrgradv_meta_get_view_type(const struct radv_image *image) 168b8e80941Smrg{ 169b8e80941Smrg switch (image->type) { 170b8e80941Smrg case VK_IMAGE_TYPE_1D: return VK_IMAGE_VIEW_TYPE_1D; 171b8e80941Smrg case VK_IMAGE_TYPE_2D: return VK_IMAGE_VIEW_TYPE_2D; 172b8e80941Smrg case VK_IMAGE_TYPE_3D: return VK_IMAGE_VIEW_TYPE_3D; 173b8e80941Smrg default: 174b8e80941Smrg unreachable("bad VkImageViewType"); 175b8e80941Smrg } 176b8e80941Smrg} 177b8e80941Smrg 178b8e80941Smrg/** 179b8e80941Smrg * When creating a destination VkImageView, this function provides the needed 180b8e80941Smrg * VkImageViewCreateInfo::subresourceRange::baseArrayLayer. 181b8e80941Smrg */ 182b8e80941Smrguint32_t 183b8e80941Smrgradv_meta_get_iview_layer(const struct radv_image *dest_image, 184b8e80941Smrg const VkImageSubresourceLayers *dest_subresource, 185b8e80941Smrg const VkOffset3D *dest_offset) 186b8e80941Smrg{ 187b8e80941Smrg switch (dest_image->type) { 188b8e80941Smrg case VK_IMAGE_TYPE_1D: 189b8e80941Smrg case VK_IMAGE_TYPE_2D: 190b8e80941Smrg return dest_subresource->baseArrayLayer; 191b8e80941Smrg case VK_IMAGE_TYPE_3D: 192b8e80941Smrg /* HACK: Vulkan does not allow attaching a 3D image to a framebuffer, 193b8e80941Smrg * but meta does it anyway. When doing so, we translate the 194b8e80941Smrg * destination's z offset into an array offset. 195b8e80941Smrg */ 196b8e80941Smrg return dest_offset->z; 197b8e80941Smrg default: 198b8e80941Smrg assert(!"bad VkImageType"); 199b8e80941Smrg return 0; 200b8e80941Smrg } 201b8e80941Smrg} 202b8e80941Smrg 203b8e80941Smrgstatic void * 204b8e80941Smrgmeta_alloc(void* _device, size_t size, size_t alignment, 205b8e80941Smrg VkSystemAllocationScope allocationScope) 206b8e80941Smrg{ 207b8e80941Smrg struct radv_device *device = _device; 208b8e80941Smrg return device->alloc.pfnAllocation(device->alloc.pUserData, size, alignment, 209b8e80941Smrg VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 210b8e80941Smrg} 211b8e80941Smrg 212b8e80941Smrgstatic void * 213b8e80941Smrgmeta_realloc(void* _device, void *original, size_t size, size_t alignment, 214b8e80941Smrg VkSystemAllocationScope allocationScope) 215b8e80941Smrg{ 216b8e80941Smrg struct radv_device *device = _device; 217b8e80941Smrg return device->alloc.pfnReallocation(device->alloc.pUserData, original, 218b8e80941Smrg size, alignment, 219b8e80941Smrg VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 220b8e80941Smrg} 221b8e80941Smrg 222b8e80941Smrgstatic void 223b8e80941Smrgmeta_free(void* _device, void *data) 224b8e80941Smrg{ 225b8e80941Smrg struct radv_device *device = _device; 226b8e80941Smrg return device->alloc.pfnFree(device->alloc.pUserData, data); 227b8e80941Smrg} 228b8e80941Smrg 229b8e80941Smrgstatic bool 230b8e80941Smrgradv_builtin_cache_path(char *path) 231b8e80941Smrg{ 232b8e80941Smrg char *xdg_cache_home = getenv("XDG_CACHE_HOME"); 233b8e80941Smrg const char *suffix = "/radv_builtin_shaders"; 234b8e80941Smrg const char *suffix2 = "/.cache/radv_builtin_shaders"; 235b8e80941Smrg struct passwd pwd, *result; 236b8e80941Smrg char path2[PATH_MAX + 1]; /* PATH_MAX is not a real max,but suffices here. */ 237b8e80941Smrg int ret; 238b8e80941Smrg 239b8e80941Smrg if (xdg_cache_home) { 240b8e80941Smrg ret = snprintf(path, PATH_MAX + 1, "%s%s%zd", 241b8e80941Smrg xdg_cache_home, suffix, sizeof(void *) * 8); 242b8e80941Smrg return ret > 0 && ret < PATH_MAX + 1; 243b8e80941Smrg } 244b8e80941Smrg 245b8e80941Smrg getpwuid_r(getuid(), &pwd, path2, PATH_MAX - strlen(suffix2), &result); 246b8e80941Smrg if (!result) 247b8e80941Smrg return false; 248b8e80941Smrg 249b8e80941Smrg strcpy(path, pwd.pw_dir); 250b8e80941Smrg strcat(path, "/.cache"); 251b8e80941Smrg mkdir(path, 0755); 252b8e80941Smrg 253b8e80941Smrg ret = snprintf(path, PATH_MAX + 1, "%s%s%zd", 254b8e80941Smrg pwd.pw_dir, suffix2, sizeof(void *) * 8); 255b8e80941Smrg return ret > 0 && ret < PATH_MAX + 1; 256b8e80941Smrg} 257b8e80941Smrg 258b8e80941Smrgstatic bool 259b8e80941Smrgradv_load_meta_pipeline(struct radv_device *device) 260b8e80941Smrg{ 261b8e80941Smrg char path[PATH_MAX + 1]; 262b8e80941Smrg struct stat st; 263b8e80941Smrg void *data = NULL; 264b8e80941Smrg bool ret = false; 265b8e80941Smrg 266b8e80941Smrg if (!radv_builtin_cache_path(path)) 267b8e80941Smrg return false; 268b8e80941Smrg 269b8e80941Smrg int fd = open(path, O_RDONLY); 270b8e80941Smrg if (fd < 0) 271b8e80941Smrg return false; 272b8e80941Smrg if (fstat(fd, &st)) 273b8e80941Smrg goto fail; 274b8e80941Smrg data = malloc(st.st_size); 275b8e80941Smrg if (!data) 276b8e80941Smrg goto fail; 277b8e80941Smrg if(read(fd, data, st.st_size) == -1) 278b8e80941Smrg goto fail; 279b8e80941Smrg 280b8e80941Smrg ret = radv_pipeline_cache_load(&device->meta_state.cache, data, st.st_size); 281b8e80941Smrgfail: 282b8e80941Smrg free(data); 283b8e80941Smrg close(fd); 284b8e80941Smrg return ret; 285b8e80941Smrg} 286b8e80941Smrg 287b8e80941Smrgstatic void 288b8e80941Smrgradv_store_meta_pipeline(struct radv_device *device) 289b8e80941Smrg{ 290b8e80941Smrg char path[PATH_MAX + 1], path2[PATH_MAX + 7]; 291b8e80941Smrg size_t size; 292b8e80941Smrg void *data = NULL; 293b8e80941Smrg 294b8e80941Smrg if (!device->meta_state.cache.modified) 295b8e80941Smrg return; 296b8e80941Smrg 297b8e80941Smrg if (radv_GetPipelineCacheData(radv_device_to_handle(device), 298b8e80941Smrg radv_pipeline_cache_to_handle(&device->meta_state.cache), 299b8e80941Smrg &size, NULL)) 300b8e80941Smrg return; 301b8e80941Smrg 302b8e80941Smrg if (!radv_builtin_cache_path(path)) 303b8e80941Smrg return; 304b8e80941Smrg 305b8e80941Smrg strcpy(path2, path); 306b8e80941Smrg strcat(path2, "XXXXXX"); 307b8e80941Smrg int fd = mkstemp(path2);//open(path, O_WRONLY | O_CREAT, 0600); 308b8e80941Smrg if (fd < 0) 309b8e80941Smrg return; 310b8e80941Smrg data = malloc(size); 311b8e80941Smrg if (!data) 312b8e80941Smrg goto fail; 313b8e80941Smrg 314b8e80941Smrg if (radv_GetPipelineCacheData(radv_device_to_handle(device), 315b8e80941Smrg radv_pipeline_cache_to_handle(&device->meta_state.cache), 316b8e80941Smrg &size, data)) 317b8e80941Smrg goto fail; 318b8e80941Smrg if(write(fd, data, size) == -1) 319b8e80941Smrg goto fail; 320b8e80941Smrg 321b8e80941Smrg rename(path2, path); 322b8e80941Smrgfail: 323b8e80941Smrg free(data); 324b8e80941Smrg close(fd); 325b8e80941Smrg unlink(path2); 326b8e80941Smrg} 327b8e80941Smrg 328b8e80941SmrgVkResult 329b8e80941Smrgradv_device_init_meta(struct radv_device *device) 330b8e80941Smrg{ 331b8e80941Smrg VkResult result; 332b8e80941Smrg 333b8e80941Smrg memset(&device->meta_state, 0, sizeof(device->meta_state)); 334b8e80941Smrg 335b8e80941Smrg device->meta_state.alloc = (VkAllocationCallbacks) { 336b8e80941Smrg .pUserData = device, 337b8e80941Smrg .pfnAllocation = meta_alloc, 338b8e80941Smrg .pfnReallocation = meta_realloc, 339b8e80941Smrg .pfnFree = meta_free, 340b8e80941Smrg }; 341b8e80941Smrg 342b8e80941Smrg device->meta_state.cache.alloc = device->meta_state.alloc; 343b8e80941Smrg radv_pipeline_cache_init(&device->meta_state.cache, device); 344b8e80941Smrg bool loaded_cache = radv_load_meta_pipeline(device); 345b8e80941Smrg bool on_demand = !loaded_cache; 346b8e80941Smrg 347b8e80941Smrg mtx_init(&device->meta_state.mtx, mtx_plain); 348b8e80941Smrg 349b8e80941Smrg result = radv_device_init_meta_clear_state(device, on_demand); 350b8e80941Smrg if (result != VK_SUCCESS) 351b8e80941Smrg goto fail_clear; 352b8e80941Smrg 353b8e80941Smrg result = radv_device_init_meta_resolve_state(device, on_demand); 354b8e80941Smrg if (result != VK_SUCCESS) 355b8e80941Smrg goto fail_resolve; 356b8e80941Smrg 357b8e80941Smrg result = radv_device_init_meta_blit_state(device, on_demand); 358b8e80941Smrg if (result != VK_SUCCESS) 359b8e80941Smrg goto fail_blit; 360b8e80941Smrg 361b8e80941Smrg result = radv_device_init_meta_blit2d_state(device, on_demand); 362b8e80941Smrg if (result != VK_SUCCESS) 363b8e80941Smrg goto fail_blit2d; 364b8e80941Smrg 365b8e80941Smrg result = radv_device_init_meta_bufimage_state(device); 366b8e80941Smrg if (result != VK_SUCCESS) 367b8e80941Smrg goto fail_bufimage; 368b8e80941Smrg 369b8e80941Smrg result = radv_device_init_meta_depth_decomp_state(device, on_demand); 370b8e80941Smrg if (result != VK_SUCCESS) 371b8e80941Smrg goto fail_depth_decomp; 372b8e80941Smrg 373b8e80941Smrg result = radv_device_init_meta_buffer_state(device); 374b8e80941Smrg if (result != VK_SUCCESS) 375b8e80941Smrg goto fail_buffer; 376b8e80941Smrg 377b8e80941Smrg result = radv_device_init_meta_query_state(device, on_demand); 378b8e80941Smrg if (result != VK_SUCCESS) 379b8e80941Smrg goto fail_query; 380b8e80941Smrg 381b8e80941Smrg result = radv_device_init_meta_fast_clear_flush_state(device, on_demand); 382b8e80941Smrg if (result != VK_SUCCESS) 383b8e80941Smrg goto fail_fast_clear; 384b8e80941Smrg 385b8e80941Smrg result = radv_device_init_meta_resolve_compute_state(device, on_demand); 386b8e80941Smrg if (result != VK_SUCCESS) 387b8e80941Smrg goto fail_resolve_compute; 388b8e80941Smrg 389b8e80941Smrg result = radv_device_init_meta_resolve_fragment_state(device, on_demand); 390b8e80941Smrg if (result != VK_SUCCESS) 391b8e80941Smrg goto fail_resolve_fragment; 392b8e80941Smrg 393b8e80941Smrg result = radv_device_init_meta_fmask_expand_state(device); 394b8e80941Smrg if (result != VK_SUCCESS) 395b8e80941Smrg goto fail_fmask_expand; 396b8e80941Smrg 397b8e80941Smrg return VK_SUCCESS; 398b8e80941Smrg 399b8e80941Smrgfail_fmask_expand: 400b8e80941Smrg radv_device_finish_meta_resolve_fragment_state(device); 401b8e80941Smrgfail_resolve_fragment: 402b8e80941Smrg radv_device_finish_meta_resolve_compute_state(device); 403b8e80941Smrgfail_resolve_compute: 404b8e80941Smrg radv_device_finish_meta_fast_clear_flush_state(device); 405b8e80941Smrgfail_fast_clear: 406b8e80941Smrg radv_device_finish_meta_query_state(device); 407b8e80941Smrgfail_query: 408b8e80941Smrg radv_device_finish_meta_buffer_state(device); 409b8e80941Smrgfail_buffer: 410b8e80941Smrg radv_device_finish_meta_depth_decomp_state(device); 411b8e80941Smrgfail_depth_decomp: 412b8e80941Smrg radv_device_finish_meta_bufimage_state(device); 413b8e80941Smrgfail_bufimage: 414b8e80941Smrg radv_device_finish_meta_blit2d_state(device); 415b8e80941Smrgfail_blit2d: 416b8e80941Smrg radv_device_finish_meta_blit_state(device); 417b8e80941Smrgfail_blit: 418b8e80941Smrg radv_device_finish_meta_resolve_state(device); 419b8e80941Smrgfail_resolve: 420b8e80941Smrg radv_device_finish_meta_clear_state(device); 421b8e80941Smrgfail_clear: 422b8e80941Smrg mtx_destroy(&device->meta_state.mtx); 423b8e80941Smrg radv_pipeline_cache_finish(&device->meta_state.cache); 424b8e80941Smrg return result; 425b8e80941Smrg} 426b8e80941Smrg 427b8e80941Smrgvoid 428b8e80941Smrgradv_device_finish_meta(struct radv_device *device) 429b8e80941Smrg{ 430b8e80941Smrg radv_device_finish_meta_clear_state(device); 431b8e80941Smrg radv_device_finish_meta_resolve_state(device); 432b8e80941Smrg radv_device_finish_meta_blit_state(device); 433b8e80941Smrg radv_device_finish_meta_blit2d_state(device); 434b8e80941Smrg radv_device_finish_meta_bufimage_state(device); 435b8e80941Smrg radv_device_finish_meta_depth_decomp_state(device); 436b8e80941Smrg radv_device_finish_meta_query_state(device); 437b8e80941Smrg radv_device_finish_meta_buffer_state(device); 438b8e80941Smrg radv_device_finish_meta_fast_clear_flush_state(device); 439b8e80941Smrg radv_device_finish_meta_resolve_compute_state(device); 440b8e80941Smrg radv_device_finish_meta_resolve_fragment_state(device); 441b8e80941Smrg radv_device_finish_meta_fmask_expand_state(device); 442b8e80941Smrg 443b8e80941Smrg radv_store_meta_pipeline(device); 444b8e80941Smrg radv_pipeline_cache_finish(&device->meta_state.cache); 445b8e80941Smrg mtx_destroy(&device->meta_state.mtx); 446b8e80941Smrg} 447b8e80941Smrg 448b8e80941Smrgnir_ssa_def *radv_meta_gen_rect_vertices_comp2(nir_builder *vs_b, nir_ssa_def *comp2) 449b8e80941Smrg{ 450b8e80941Smrg 451b8e80941Smrg nir_intrinsic_instr *vertex_id = nir_intrinsic_instr_create(vs_b->shader, nir_intrinsic_load_vertex_id_zero_base); 452b8e80941Smrg nir_ssa_dest_init(&vertex_id->instr, &vertex_id->dest, 1, 32, "vertexid"); 453b8e80941Smrg nir_builder_instr_insert(vs_b, &vertex_id->instr); 454b8e80941Smrg 455b8e80941Smrg /* vertex 0 - -1.0, -1.0 */ 456b8e80941Smrg /* vertex 1 - -1.0, 1.0 */ 457b8e80941Smrg /* vertex 2 - 1.0, -1.0 */ 458b8e80941Smrg /* so channel 0 is vertex_id != 2 ? -1.0 : 1.0 459b8e80941Smrg channel 1 is vertex id != 1 ? -1.0 : 1.0 */ 460b8e80941Smrg 461b8e80941Smrg nir_ssa_def *c0cmp = nir_ine(vs_b, &vertex_id->dest.ssa, 462b8e80941Smrg nir_imm_int(vs_b, 2)); 463b8e80941Smrg nir_ssa_def *c1cmp = nir_ine(vs_b, &vertex_id->dest.ssa, 464b8e80941Smrg nir_imm_int(vs_b, 1)); 465b8e80941Smrg 466b8e80941Smrg nir_ssa_def *comp[4]; 467b8e80941Smrg comp[0] = nir_bcsel(vs_b, c0cmp, 468b8e80941Smrg nir_imm_float(vs_b, -1.0), 469b8e80941Smrg nir_imm_float(vs_b, 1.0)); 470b8e80941Smrg 471b8e80941Smrg comp[1] = nir_bcsel(vs_b, c1cmp, 472b8e80941Smrg nir_imm_float(vs_b, -1.0), 473b8e80941Smrg nir_imm_float(vs_b, 1.0)); 474b8e80941Smrg comp[2] = comp2; 475b8e80941Smrg comp[3] = nir_imm_float(vs_b, 1.0); 476b8e80941Smrg nir_ssa_def *outvec = nir_vec(vs_b, comp, 4); 477b8e80941Smrg 478b8e80941Smrg return outvec; 479b8e80941Smrg} 480b8e80941Smrg 481b8e80941Smrgnir_ssa_def *radv_meta_gen_rect_vertices(nir_builder *vs_b) 482b8e80941Smrg{ 483b8e80941Smrg return radv_meta_gen_rect_vertices_comp2(vs_b, nir_imm_float(vs_b, 0.0)); 484b8e80941Smrg} 485b8e80941Smrg 486b8e80941Smrg/* vertex shader that generates vertices */ 487b8e80941Smrgnir_shader * 488b8e80941Smrgradv_meta_build_nir_vs_generate_vertices(void) 489b8e80941Smrg{ 490b8e80941Smrg const struct glsl_type *vec4 = glsl_vec4_type(); 491b8e80941Smrg 492b8e80941Smrg nir_builder b; 493b8e80941Smrg nir_variable *v_position; 494b8e80941Smrg 495b8e80941Smrg nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_VERTEX, NULL); 496b8e80941Smrg b.shader->info.name = ralloc_strdup(b.shader, "meta_vs_gen_verts"); 497b8e80941Smrg 498b8e80941Smrg nir_ssa_def *outvec = radv_meta_gen_rect_vertices(&b); 499b8e80941Smrg 500b8e80941Smrg v_position = nir_variable_create(b.shader, nir_var_shader_out, vec4, 501b8e80941Smrg "gl_Position"); 502b8e80941Smrg v_position->data.location = VARYING_SLOT_POS; 503b8e80941Smrg 504b8e80941Smrg nir_store_var(&b, v_position, outvec, 0xf); 505b8e80941Smrg 506b8e80941Smrg return b.shader; 507b8e80941Smrg} 508b8e80941Smrg 509b8e80941Smrgnir_shader * 510b8e80941Smrgradv_meta_build_nir_fs_noop(void) 511b8e80941Smrg{ 512b8e80941Smrg nir_builder b; 513b8e80941Smrg 514b8e80941Smrg nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, NULL); 515b8e80941Smrg b.shader->info.name = ralloc_asprintf(b.shader, 516b8e80941Smrg "meta_noop_fs"); 517b8e80941Smrg 518b8e80941Smrg return b.shader; 519b8e80941Smrg} 520b8e80941Smrg 521b8e80941Smrgvoid radv_meta_build_resolve_shader_core(nir_builder *b, 522b8e80941Smrg bool is_integer, 523b8e80941Smrg int samples, 524b8e80941Smrg nir_variable *input_img, 525b8e80941Smrg nir_variable *color, 526b8e80941Smrg nir_ssa_def *img_coord) 527b8e80941Smrg{ 528b8e80941Smrg /* do a txf_ms on each sample */ 529b8e80941Smrg nir_ssa_def *tmp; 530b8e80941Smrg nir_if *outer_if = NULL; 531b8e80941Smrg 532b8e80941Smrg nir_ssa_def *input_img_deref = &nir_build_deref_var(b, input_img)->dest.ssa; 533b8e80941Smrg 534b8e80941Smrg nir_tex_instr *tex = nir_tex_instr_create(b->shader, 3); 535b8e80941Smrg tex->sampler_dim = GLSL_SAMPLER_DIM_MS; 536b8e80941Smrg tex->op = nir_texop_txf_ms; 537b8e80941Smrg tex->src[0].src_type = nir_tex_src_coord; 538b8e80941Smrg tex->src[0].src = nir_src_for_ssa(img_coord); 539b8e80941Smrg tex->src[1].src_type = nir_tex_src_ms_index; 540b8e80941Smrg tex->src[1].src = nir_src_for_ssa(nir_imm_int(b, 0)); 541b8e80941Smrg tex->src[2].src_type = nir_tex_src_texture_deref; 542b8e80941Smrg tex->src[2].src = nir_src_for_ssa(input_img_deref); 543b8e80941Smrg tex->dest_type = nir_type_float; 544b8e80941Smrg tex->is_array = false; 545b8e80941Smrg tex->coord_components = 2; 546b8e80941Smrg 547b8e80941Smrg nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, "tex"); 548b8e80941Smrg nir_builder_instr_insert(b, &tex->instr); 549b8e80941Smrg 550b8e80941Smrg tmp = &tex->dest.ssa; 551b8e80941Smrg 552b8e80941Smrg if (!is_integer && samples > 1) { 553b8e80941Smrg nir_tex_instr *tex_all_same = nir_tex_instr_create(b->shader, 2); 554b8e80941Smrg tex_all_same->sampler_dim = GLSL_SAMPLER_DIM_MS; 555b8e80941Smrg tex_all_same->op = nir_texop_samples_identical; 556b8e80941Smrg tex_all_same->src[0].src_type = nir_tex_src_coord; 557b8e80941Smrg tex_all_same->src[0].src = nir_src_for_ssa(img_coord); 558b8e80941Smrg tex_all_same->src[1].src_type = nir_tex_src_texture_deref; 559b8e80941Smrg tex_all_same->src[1].src = nir_src_for_ssa(input_img_deref); 560b8e80941Smrg tex_all_same->dest_type = nir_type_float; 561b8e80941Smrg tex_all_same->is_array = false; 562b8e80941Smrg tex_all_same->coord_components = 2; 563b8e80941Smrg 564b8e80941Smrg nir_ssa_dest_init(&tex_all_same->instr, &tex_all_same->dest, 1, 32, "tex"); 565b8e80941Smrg nir_builder_instr_insert(b, &tex_all_same->instr); 566b8e80941Smrg 567b8e80941Smrg nir_ssa_def *all_same = nir_ieq(b, &tex_all_same->dest.ssa, nir_imm_int(b, 0)); 568b8e80941Smrg nir_if *if_stmt = nir_if_create(b->shader); 569b8e80941Smrg if_stmt->condition = nir_src_for_ssa(all_same); 570b8e80941Smrg nir_cf_node_insert(b->cursor, &if_stmt->cf_node); 571b8e80941Smrg 572b8e80941Smrg b->cursor = nir_after_cf_list(&if_stmt->then_list); 573b8e80941Smrg for (int i = 1; i < samples; i++) { 574b8e80941Smrg nir_tex_instr *tex_add = nir_tex_instr_create(b->shader, 3); 575b8e80941Smrg tex_add->sampler_dim = GLSL_SAMPLER_DIM_MS; 576b8e80941Smrg tex_add->op = nir_texop_txf_ms; 577b8e80941Smrg tex_add->src[0].src_type = nir_tex_src_coord; 578b8e80941Smrg tex_add->src[0].src = nir_src_for_ssa(img_coord); 579b8e80941Smrg tex_add->src[1].src_type = nir_tex_src_ms_index; 580b8e80941Smrg tex_add->src[1].src = nir_src_for_ssa(nir_imm_int(b, i)); 581b8e80941Smrg tex_add->src[2].src_type = nir_tex_src_texture_deref; 582b8e80941Smrg tex_add->src[2].src = nir_src_for_ssa(input_img_deref); 583b8e80941Smrg tex_add->dest_type = nir_type_float; 584b8e80941Smrg tex_add->is_array = false; 585b8e80941Smrg tex_add->coord_components = 2; 586b8e80941Smrg 587b8e80941Smrg nir_ssa_dest_init(&tex_add->instr, &tex_add->dest, 4, 32, "tex"); 588b8e80941Smrg nir_builder_instr_insert(b, &tex_add->instr); 589b8e80941Smrg 590b8e80941Smrg tmp = nir_fadd(b, tmp, &tex_add->dest.ssa); 591b8e80941Smrg } 592b8e80941Smrg 593b8e80941Smrg tmp = nir_fdiv(b, tmp, nir_imm_float(b, samples)); 594b8e80941Smrg nir_store_var(b, color, tmp, 0xf); 595b8e80941Smrg b->cursor = nir_after_cf_list(&if_stmt->else_list); 596b8e80941Smrg outer_if = if_stmt; 597b8e80941Smrg } 598b8e80941Smrg nir_store_var(b, color, &tex->dest.ssa, 0xf); 599b8e80941Smrg 600b8e80941Smrg if (outer_if) 601b8e80941Smrg b->cursor = nir_after_cf_node(&outer_if->cf_node); 602b8e80941Smrg} 603