1/* 2 * Copyright © 2015 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include <assert.h> 25#include <stdbool.h> 26#include <string.h> 27#include <unistd.h> 28#include <fcntl.h> 29 30#include "anv_private.h" 31#include "anv_measure.h" 32 33#include "vk_util.h" 34 35/** \file anv_cmd_buffer.c 36 * 37 * This file contains all of the stuff for emitting commands into a command 38 * buffer. This includes implementations of most of the vkCmd* 39 * entrypoints. This file is concerned entirely with state emission and 40 * not with the command buffer data structure itself. As far as this file 41 * is concerned, most of anv_cmd_buffer is magic. 42 */ 43 44/* TODO: These are taken from GLES. We should check the Vulkan spec */ 45const struct anv_dynamic_state default_dynamic_state = { 46 .viewport = { 47 .count = 0, 48 }, 49 .scissor = { 50 .count = 0, 51 }, 52 .line_width = 1.0f, 53 .depth_bias = { 54 .bias = 0.0f, 55 .clamp = 0.0f, 56 .slope = 0.0f, 57 }, 58 .blend_constants = { 0.0f, 0.0f, 0.0f, 0.0f }, 59 .depth_bounds = { 60 .min = 0.0f, 61 .max = 1.0f, 62 }, 63 .stencil_compare_mask = { 64 .front = ~0u, 65 .back = ~0u, 66 }, 67 .stencil_write_mask = { 68 .front = ~0u, 69 .back = ~0u, 70 }, 71 .stencil_reference = { 72 .front = 0u, 73 .back = 0u, 74 }, 75 .stencil_op = { 76 .front = { 77 .fail_op = 0, 78 .pass_op = 0, 79 .depth_fail_op = 0, 80 .compare_op = 0, 81 }, 82 .back = { 83 .fail_op = 0, 84 .pass_op = 0, 85 .depth_fail_op = 0, 86 .compare_op = 0, 87 }, 88 }, 89 .line_stipple = { 90 .factor = 0u, 91 .pattern = 0u, 92 }, 93 .cull_mode = 0, 94 .front_face = 0, 95 .primitive_topology = 0, 96 .depth_test_enable = 0, 97 .depth_write_enable = 0, 98 .depth_compare_op = 0, 99 .depth_bounds_test_enable = 0, 100 .stencil_test_enable = 0, 101 .dyn_vbo_stride = 0, 102 .dyn_vbo_size = 0, 103 .color_writes = 0xff, 104 .raster_discard = 0, 105 .depth_bias_enable = 0, 106 .primitive_restart_enable = 0, 107 .logic_op = 0, 108}; 109 110/** 111 * Copy the dynamic state from src to dest based on the copy_mask. 112 * 113 * Avoid copying states that have not changed, except for VIEWPORT, SCISSOR and 114 * BLEND_CONSTANTS (always copy them if they are in the copy_mask). 115 * 116 * Returns a mask of the states which changed. 117 */ 118anv_cmd_dirty_mask_t 119anv_dynamic_state_copy(struct anv_dynamic_state *dest, 120 const struct anv_dynamic_state *src, 121 anv_cmd_dirty_mask_t copy_mask) 122{ 123 anv_cmd_dirty_mask_t changed = 0; 124 125 if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_VIEWPORT) { 126 dest->viewport.count = src->viewport.count; 127 typed_memcpy(dest->viewport.viewports, src->viewport.viewports, 128 src->viewport.count); 129 changed |= ANV_CMD_DIRTY_DYNAMIC_VIEWPORT; 130 } 131 132 if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_SCISSOR) { 133 dest->scissor.count = src->scissor.count; 134 typed_memcpy(dest->scissor.scissors, src->scissor.scissors, 135 src->scissor.count); 136 changed |= ANV_CMD_DIRTY_DYNAMIC_SCISSOR; 137 } 138 139 if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS) { 140 typed_memcpy(dest->blend_constants, src->blend_constants, 4); 141 changed |= ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS; 142 } 143 144#define ANV_CMP_COPY(field, flag) \ 145 if (copy_mask & flag) { \ 146 if (dest->field != src->field) { \ 147 dest->field = src->field; \ 148 changed |= flag; \ 149 } \ 150 } 151 152 ANV_CMP_COPY(line_width, ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH); 153 154 ANV_CMP_COPY(depth_bias.bias, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS); 155 ANV_CMP_COPY(depth_bias.clamp, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS); 156 ANV_CMP_COPY(depth_bias.slope, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS); 157 158 ANV_CMP_COPY(depth_bounds.min, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS); 159 ANV_CMP_COPY(depth_bounds.max, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS); 160 161 ANV_CMP_COPY(stencil_compare_mask.front, ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK); 162 ANV_CMP_COPY(stencil_compare_mask.back, ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK); 163 164 ANV_CMP_COPY(stencil_write_mask.front, ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK); 165 ANV_CMP_COPY(stencil_write_mask.back, ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK); 166 167 ANV_CMP_COPY(stencil_reference.front, ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE); 168 ANV_CMP_COPY(stencil_reference.back, ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE); 169 170 ANV_CMP_COPY(line_stipple.factor, ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE); 171 ANV_CMP_COPY(line_stipple.pattern, ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE); 172 173 ANV_CMP_COPY(cull_mode, ANV_CMD_DIRTY_DYNAMIC_CULL_MODE); 174 ANV_CMP_COPY(front_face, ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE); 175 ANV_CMP_COPY(primitive_topology, ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY); 176 ANV_CMP_COPY(depth_test_enable, ANV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE); 177 ANV_CMP_COPY(depth_write_enable, ANV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE); 178 ANV_CMP_COPY(depth_compare_op, ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP); 179 ANV_CMP_COPY(depth_bounds_test_enable, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE); 180 ANV_CMP_COPY(stencil_test_enable, ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE); 181 182 if (copy_mask & VK_DYNAMIC_STATE_STENCIL_OP_EXT) { 183 ANV_CMP_COPY(stencil_op.front.fail_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP); 184 ANV_CMP_COPY(stencil_op.front.pass_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP); 185 ANV_CMP_COPY(stencil_op.front.depth_fail_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP); 186 ANV_CMP_COPY(stencil_op.front.compare_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP); 187 ANV_CMP_COPY(stencil_op.back.fail_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP); 188 ANV_CMP_COPY(stencil_op.back.pass_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP); 189 ANV_CMP_COPY(stencil_op.back.depth_fail_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP); 190 ANV_CMP_COPY(stencil_op.back.compare_op, ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP); 191 } 192 193 ANV_CMP_COPY(dyn_vbo_stride, ANV_CMD_DIRTY_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE); 194 ANV_CMP_COPY(dyn_vbo_size, ANV_CMD_DIRTY_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE); 195 196 ANV_CMP_COPY(raster_discard, ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE); 197 ANV_CMP_COPY(depth_bias_enable, ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE); 198 ANV_CMP_COPY(primitive_restart_enable, ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE); 199 ANV_CMP_COPY(logic_op, ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP); 200 201 if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) { 202 dest->sample_locations.samples = src->sample_locations.samples; 203 typed_memcpy(dest->sample_locations.locations, 204 src->sample_locations.locations, 205 dest->sample_locations.samples); 206 changed |= ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS; 207 } 208 209 ANV_CMP_COPY(color_writes, ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE); 210 211 ANV_CMP_COPY(fragment_shading_rate.width, ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE); 212 ANV_CMP_COPY(fragment_shading_rate.height, ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE); 213 214#undef ANV_CMP_COPY 215 216 return changed; 217} 218 219static void 220anv_cmd_state_init(struct anv_cmd_buffer *cmd_buffer) 221{ 222 struct anv_cmd_state *state = &cmd_buffer->state; 223 224 memset(state, 0, sizeof(*state)); 225 226 state->current_pipeline = UINT32_MAX; 227 state->restart_index = UINT32_MAX; 228 state->gfx.dynamic = default_dynamic_state; 229} 230 231static void 232anv_cmd_pipeline_state_finish(struct anv_cmd_buffer *cmd_buffer, 233 struct anv_cmd_pipeline_state *pipe_state) 234{ 235 for (uint32_t i = 0; i < ARRAY_SIZE(pipe_state->push_descriptors); i++) { 236 if (pipe_state->push_descriptors[i]) { 237 anv_descriptor_set_layout_unref(cmd_buffer->device, 238 pipe_state->push_descriptors[i]->set.layout); 239 vk_free(&cmd_buffer->pool->alloc, pipe_state->push_descriptors[i]); 240 } 241 } 242} 243 244static void 245anv_cmd_state_finish(struct anv_cmd_buffer *cmd_buffer) 246{ 247 struct anv_cmd_state *state = &cmd_buffer->state; 248 249 anv_cmd_pipeline_state_finish(cmd_buffer, &state->gfx.base); 250 anv_cmd_pipeline_state_finish(cmd_buffer, &state->compute.base); 251 252 vk_free(&cmd_buffer->pool->alloc, state->attachments); 253} 254 255static void 256anv_cmd_state_reset(struct anv_cmd_buffer *cmd_buffer) 257{ 258 anv_cmd_state_finish(cmd_buffer); 259 anv_cmd_state_init(cmd_buffer); 260} 261 262static VkResult anv_create_cmd_buffer( 263 struct anv_device * device, 264 struct anv_cmd_pool * pool, 265 VkCommandBufferLevel level, 266 VkCommandBuffer* pCommandBuffer) 267{ 268 struct anv_cmd_buffer *cmd_buffer; 269 VkResult result; 270 271 cmd_buffer = vk_alloc2(&device->vk.alloc, &pool->alloc, sizeof(*cmd_buffer), 272 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 273 if (cmd_buffer == NULL) 274 return vk_error(pool, VK_ERROR_OUT_OF_HOST_MEMORY); 275 276 result = vk_command_buffer_init(&cmd_buffer->vk, &device->vk); 277 if (result != VK_SUCCESS) 278 goto fail_alloc; 279 280 cmd_buffer->batch.status = VK_SUCCESS; 281 282 cmd_buffer->device = device; 283 cmd_buffer->pool = pool; 284 cmd_buffer->level = level; 285 286 result = anv_cmd_buffer_init_batch_bo_chain(cmd_buffer); 287 if (result != VK_SUCCESS) 288 goto fail_vk; 289 290 anv_state_stream_init(&cmd_buffer->surface_state_stream, 291 &device->surface_state_pool, 4096); 292 anv_state_stream_init(&cmd_buffer->dynamic_state_stream, 293 &device->dynamic_state_pool, 16384); 294 anv_state_stream_init(&cmd_buffer->general_state_stream, 295 &device->general_state_pool, 16384); 296 297 cmd_buffer->self_mod_locations = NULL; 298 299 anv_cmd_state_init(cmd_buffer); 300 301 list_addtail(&cmd_buffer->pool_link, &pool->cmd_buffers); 302 303 anv_measure_init(cmd_buffer); 304 305 *pCommandBuffer = anv_cmd_buffer_to_handle(cmd_buffer); 306 307 return VK_SUCCESS; 308 309 fail_vk: 310 vk_command_buffer_finish(&cmd_buffer->vk); 311 fail_alloc: 312 vk_free2(&device->vk.alloc, &pool->alloc, cmd_buffer); 313 314 return result; 315} 316 317VkResult anv_AllocateCommandBuffers( 318 VkDevice _device, 319 const VkCommandBufferAllocateInfo* pAllocateInfo, 320 VkCommandBuffer* pCommandBuffers) 321{ 322 ANV_FROM_HANDLE(anv_device, device, _device); 323 ANV_FROM_HANDLE(anv_cmd_pool, pool, pAllocateInfo->commandPool); 324 325 VkResult result = VK_SUCCESS; 326 uint32_t i; 327 328 for (i = 0; i < pAllocateInfo->commandBufferCount; i++) { 329 result = anv_create_cmd_buffer(device, pool, pAllocateInfo->level, 330 &pCommandBuffers[i]); 331 if (result != VK_SUCCESS) 332 break; 333 } 334 335 if (result != VK_SUCCESS) { 336 anv_FreeCommandBuffers(_device, pAllocateInfo->commandPool, 337 i, pCommandBuffers); 338 for (i = 0; i < pAllocateInfo->commandBufferCount; i++) 339 pCommandBuffers[i] = VK_NULL_HANDLE; 340 } 341 342 return result; 343} 344 345static void 346anv_cmd_buffer_destroy(struct anv_cmd_buffer *cmd_buffer) 347{ 348 anv_measure_destroy(cmd_buffer); 349 350 list_del(&cmd_buffer->pool_link); 351 352 anv_cmd_buffer_fini_batch_bo_chain(cmd_buffer); 353 354 anv_state_stream_finish(&cmd_buffer->surface_state_stream); 355 anv_state_stream_finish(&cmd_buffer->dynamic_state_stream); 356 anv_state_stream_finish(&cmd_buffer->general_state_stream); 357 358 anv_cmd_state_finish(cmd_buffer); 359 360 vk_free(&cmd_buffer->pool->alloc, cmd_buffer->self_mod_locations); 361 362 vk_command_buffer_finish(&cmd_buffer->vk); 363 vk_free2(&cmd_buffer->device->vk.alloc, &cmd_buffer->pool->alloc, 364 cmd_buffer); 365} 366 367void anv_FreeCommandBuffers( 368 VkDevice device, 369 VkCommandPool commandPool, 370 uint32_t commandBufferCount, 371 const VkCommandBuffer* pCommandBuffers) 372{ 373 for (uint32_t i = 0; i < commandBufferCount; i++) { 374 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, pCommandBuffers[i]); 375 376 if (!cmd_buffer) 377 continue; 378 379 anv_cmd_buffer_destroy(cmd_buffer); 380 } 381} 382 383VkResult 384anv_cmd_buffer_reset(struct anv_cmd_buffer *cmd_buffer) 385{ 386 vk_command_buffer_reset(&cmd_buffer->vk); 387 388 cmd_buffer->usage_flags = 0; 389 cmd_buffer->perf_query_pool = NULL; 390 anv_cmd_buffer_reset_batch_bo_chain(cmd_buffer); 391 anv_cmd_state_reset(cmd_buffer); 392 393 anv_state_stream_finish(&cmd_buffer->surface_state_stream); 394 anv_state_stream_init(&cmd_buffer->surface_state_stream, 395 &cmd_buffer->device->surface_state_pool, 4096); 396 397 anv_state_stream_finish(&cmd_buffer->dynamic_state_stream); 398 anv_state_stream_init(&cmd_buffer->dynamic_state_stream, 399 &cmd_buffer->device->dynamic_state_pool, 16384); 400 401 anv_state_stream_finish(&cmd_buffer->general_state_stream); 402 anv_state_stream_init(&cmd_buffer->general_state_stream, 403 &cmd_buffer->device->general_state_pool, 16384); 404 405 anv_measure_reset(cmd_buffer); 406 return VK_SUCCESS; 407} 408 409VkResult anv_ResetCommandBuffer( 410 VkCommandBuffer commandBuffer, 411 VkCommandBufferResetFlags flags) 412{ 413 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 414 return anv_cmd_buffer_reset(cmd_buffer); 415} 416 417void 418anv_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer) 419{ 420 const struct intel_device_info *devinfo = &cmd_buffer->device->info; 421 anv_genX(devinfo, cmd_buffer_emit_state_base_address)(cmd_buffer); 422} 423 424void 425anv_cmd_buffer_mark_image_written(struct anv_cmd_buffer *cmd_buffer, 426 const struct anv_image *image, 427 VkImageAspectFlagBits aspect, 428 enum isl_aux_usage aux_usage, 429 uint32_t level, 430 uint32_t base_layer, 431 uint32_t layer_count) 432{ 433 const struct intel_device_info *devinfo = &cmd_buffer->device->info; 434 anv_genX(devinfo, cmd_buffer_mark_image_written)(cmd_buffer, image, 435 aspect, aux_usage, 436 level, base_layer, 437 layer_count); 438} 439 440void 441anv_cmd_emit_conditional_render_predicate(struct anv_cmd_buffer *cmd_buffer) 442{ 443 const struct intel_device_info *devinfo = &cmd_buffer->device->info; 444 anv_genX(devinfo, cmd_emit_conditional_render_predicate)(cmd_buffer); 445} 446 447static bool 448mem_update(void *dst, const void *src, size_t size) 449{ 450 if (memcmp(dst, src, size) == 0) 451 return false; 452 453 memcpy(dst, src, size); 454 return true; 455} 456 457static void 458set_dirty_for_bind_map(struct anv_cmd_buffer *cmd_buffer, 459 gl_shader_stage stage, 460 const struct anv_pipeline_bind_map *map) 461{ 462 assert(stage < ARRAY_SIZE(cmd_buffer->state.surface_sha1s)); 463 if (mem_update(cmd_buffer->state.surface_sha1s[stage], 464 map->surface_sha1, sizeof(map->surface_sha1))) 465 cmd_buffer->state.descriptors_dirty |= mesa_to_vk_shader_stage(stage); 466 467 assert(stage < ARRAY_SIZE(cmd_buffer->state.sampler_sha1s)); 468 if (mem_update(cmd_buffer->state.sampler_sha1s[stage], 469 map->sampler_sha1, sizeof(map->sampler_sha1))) 470 cmd_buffer->state.descriptors_dirty |= mesa_to_vk_shader_stage(stage); 471 472 assert(stage < ARRAY_SIZE(cmd_buffer->state.push_sha1s)); 473 if (mem_update(cmd_buffer->state.push_sha1s[stage], 474 map->push_sha1, sizeof(map->push_sha1))) 475 cmd_buffer->state.push_constants_dirty |= mesa_to_vk_shader_stage(stage); 476} 477 478void anv_CmdBindPipeline( 479 VkCommandBuffer commandBuffer, 480 VkPipelineBindPoint pipelineBindPoint, 481 VkPipeline _pipeline) 482{ 483 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 484 ANV_FROM_HANDLE(anv_pipeline, pipeline, _pipeline); 485 486 switch (pipelineBindPoint) { 487 case VK_PIPELINE_BIND_POINT_COMPUTE: { 488 struct anv_compute_pipeline *compute_pipeline = 489 anv_pipeline_to_compute(pipeline); 490 if (cmd_buffer->state.compute.pipeline == compute_pipeline) 491 return; 492 493 cmd_buffer->state.compute.pipeline = compute_pipeline; 494 cmd_buffer->state.compute.pipeline_dirty = true; 495 set_dirty_for_bind_map(cmd_buffer, MESA_SHADER_COMPUTE, 496 &compute_pipeline->cs->bind_map); 497 break; 498 } 499 500 case VK_PIPELINE_BIND_POINT_GRAPHICS: { 501 struct anv_graphics_pipeline *gfx_pipeline = 502 anv_pipeline_to_graphics(pipeline); 503 if (cmd_buffer->state.gfx.pipeline == gfx_pipeline) 504 return; 505 506 cmd_buffer->state.gfx.pipeline = gfx_pipeline; 507 cmd_buffer->state.gfx.vb_dirty |= gfx_pipeline->vb_used; 508 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_PIPELINE; 509 510 anv_foreach_stage(stage, gfx_pipeline->active_stages) { 511 set_dirty_for_bind_map(cmd_buffer, stage, 512 &gfx_pipeline->shaders[stage]->bind_map); 513 } 514 515 /* Apply the dynamic state from the pipeline */ 516 cmd_buffer->state.gfx.dirty |= 517 anv_dynamic_state_copy(&cmd_buffer->state.gfx.dynamic, 518 &gfx_pipeline->dynamic_state, 519 gfx_pipeline->dynamic_state_mask); 520 break; 521 } 522 523 case VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR: { 524 struct anv_ray_tracing_pipeline *rt_pipeline = 525 anv_pipeline_to_ray_tracing(pipeline); 526 if (cmd_buffer->state.rt.pipeline == rt_pipeline) 527 return; 528 529 cmd_buffer->state.rt.pipeline = rt_pipeline; 530 cmd_buffer->state.rt.pipeline_dirty = true; 531 532 if (rt_pipeline->stack_size > 0) { 533 anv_CmdSetRayTracingPipelineStackSizeKHR(commandBuffer, 534 rt_pipeline->stack_size); 535 } 536 break; 537 } 538 539 default: 540 assert(!"invalid bind point"); 541 break; 542 } 543} 544 545void anv_CmdSetRasterizerDiscardEnableEXT( 546 VkCommandBuffer commandBuffer, 547 VkBool32 rasterizerDiscardEnable) 548{ 549 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 550 551 cmd_buffer->state.gfx.dynamic.raster_discard = rasterizerDiscardEnable; 552 553 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE; 554} 555 556void anv_CmdSetDepthBiasEnableEXT( 557 VkCommandBuffer commandBuffer, 558 VkBool32 depthBiasEnable) 559{ 560 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 561 562 cmd_buffer->state.gfx.dynamic.depth_bias_enable = depthBiasEnable; 563 564 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE; 565} 566 567void anv_CmdSetPrimitiveRestartEnableEXT( 568 VkCommandBuffer commandBuffer, 569 VkBool32 primitiveRestartEnable) 570{ 571 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 572 573 cmd_buffer->state.gfx.dynamic.primitive_restart_enable = primitiveRestartEnable; 574 575 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE; 576} 577 578void anv_CmdSetLogicOpEXT( 579 VkCommandBuffer commandBuffer, 580 VkLogicOp logicOp) 581{ 582 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 583 584 cmd_buffer->state.gfx.dynamic.logic_op = logicOp; 585 586 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP; 587} 588 589void anv_CmdSetPatchControlPointsEXT( 590 VkCommandBuffer commandBuffer, 591 uint32_t patchControlPoints) 592{ 593 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 594 anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_FEATURE_NOT_PRESENT); 595} 596 597void anv_CmdSetViewport( 598 VkCommandBuffer commandBuffer, 599 uint32_t firstViewport, 600 uint32_t viewportCount, 601 const VkViewport* pViewports) 602{ 603 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 604 605 const uint32_t total_count = firstViewport + viewportCount; 606 if (cmd_buffer->state.gfx.dynamic.viewport.count < total_count) 607 cmd_buffer->state.gfx.dynamic.viewport.count = total_count; 608 609 memcpy(cmd_buffer->state.gfx.dynamic.viewport.viewports + firstViewport, 610 pViewports, viewportCount * sizeof(*pViewports)); 611 612 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_VIEWPORT; 613} 614 615void anv_CmdSetViewportWithCountEXT( 616 VkCommandBuffer commandBuffer, 617 uint32_t viewportCount, 618 const VkViewport* pViewports) 619{ 620 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 621 622 cmd_buffer->state.gfx.dynamic.viewport.count = viewportCount; 623 624 memcpy(cmd_buffer->state.gfx.dynamic.viewport.viewports, 625 pViewports, viewportCount * sizeof(*pViewports)); 626 627 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_VIEWPORT; 628} 629 630void anv_CmdSetScissor( 631 VkCommandBuffer commandBuffer, 632 uint32_t firstScissor, 633 uint32_t scissorCount, 634 const VkRect2D* pScissors) 635{ 636 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 637 638 const uint32_t total_count = firstScissor + scissorCount; 639 if (cmd_buffer->state.gfx.dynamic.scissor.count < total_count) 640 cmd_buffer->state.gfx.dynamic.scissor.count = total_count; 641 642 memcpy(cmd_buffer->state.gfx.dynamic.scissor.scissors + firstScissor, 643 pScissors, scissorCount * sizeof(*pScissors)); 644 645 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_SCISSOR; 646} 647 648void anv_CmdSetScissorWithCountEXT( 649 VkCommandBuffer commandBuffer, 650 uint32_t scissorCount, 651 const VkRect2D* pScissors) 652{ 653 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 654 655 cmd_buffer->state.gfx.dynamic.scissor.count = scissorCount; 656 657 memcpy(cmd_buffer->state.gfx.dynamic.scissor.scissors, 658 pScissors, scissorCount * sizeof(*pScissors)); 659 660 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_SCISSOR; 661} 662 663void anv_CmdSetPrimitiveTopologyEXT( 664 VkCommandBuffer commandBuffer, 665 VkPrimitiveTopology primitiveTopology) 666{ 667 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 668 669 cmd_buffer->state.gfx.dynamic.primitive_topology = primitiveTopology; 670 671 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; 672} 673 674void anv_CmdSetLineWidth( 675 VkCommandBuffer commandBuffer, 676 float lineWidth) 677{ 678 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 679 680 cmd_buffer->state.gfx.dynamic.line_width = lineWidth; 681 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH; 682} 683 684void anv_CmdSetDepthBias( 685 VkCommandBuffer commandBuffer, 686 float depthBiasConstantFactor, 687 float depthBiasClamp, 688 float depthBiasSlopeFactor) 689{ 690 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 691 692 cmd_buffer->state.gfx.dynamic.depth_bias.bias = depthBiasConstantFactor; 693 cmd_buffer->state.gfx.dynamic.depth_bias.clamp = depthBiasClamp; 694 cmd_buffer->state.gfx.dynamic.depth_bias.slope = depthBiasSlopeFactor; 695 696 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS; 697} 698 699void anv_CmdSetBlendConstants( 700 VkCommandBuffer commandBuffer, 701 const float blendConstants[4]) 702{ 703 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 704 705 memcpy(cmd_buffer->state.gfx.dynamic.blend_constants, 706 blendConstants, sizeof(float) * 4); 707 708 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS; 709} 710 711void anv_CmdSetDepthBounds( 712 VkCommandBuffer commandBuffer, 713 float minDepthBounds, 714 float maxDepthBounds) 715{ 716 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 717 718 cmd_buffer->state.gfx.dynamic.depth_bounds.min = minDepthBounds; 719 cmd_buffer->state.gfx.dynamic.depth_bounds.max = maxDepthBounds; 720 721 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS; 722} 723 724void anv_CmdSetStencilCompareMask( 725 VkCommandBuffer commandBuffer, 726 VkStencilFaceFlags faceMask, 727 uint32_t compareMask) 728{ 729 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 730 731 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) 732 cmd_buffer->state.gfx.dynamic.stencil_compare_mask.front = compareMask; 733 if (faceMask & VK_STENCIL_FACE_BACK_BIT) 734 cmd_buffer->state.gfx.dynamic.stencil_compare_mask.back = compareMask; 735 736 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK; 737} 738 739void anv_CmdSetStencilWriteMask( 740 VkCommandBuffer commandBuffer, 741 VkStencilFaceFlags faceMask, 742 uint32_t writeMask) 743{ 744 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 745 746 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) 747 cmd_buffer->state.gfx.dynamic.stencil_write_mask.front = writeMask; 748 if (faceMask & VK_STENCIL_FACE_BACK_BIT) 749 cmd_buffer->state.gfx.dynamic.stencil_write_mask.back = writeMask; 750 751 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK; 752} 753 754void anv_CmdSetStencilReference( 755 VkCommandBuffer commandBuffer, 756 VkStencilFaceFlags faceMask, 757 uint32_t reference) 758{ 759 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 760 761 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) 762 cmd_buffer->state.gfx.dynamic.stencil_reference.front = reference; 763 if (faceMask & VK_STENCIL_FACE_BACK_BIT) 764 cmd_buffer->state.gfx.dynamic.stencil_reference.back = reference; 765 766 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE; 767} 768 769void anv_CmdSetSampleLocationsEXT( 770 VkCommandBuffer commandBuffer, 771 const VkSampleLocationsInfoEXT* pSampleLocationsInfo) 772{ 773 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 774 775 struct anv_dynamic_state *dyn_state = &cmd_buffer->state.gfx.dynamic; 776 uint32_t samples = pSampleLocationsInfo->sampleLocationsPerPixel; 777 778 dyn_state->sample_locations.samples = samples; 779 typed_memcpy(dyn_state->sample_locations.locations, 780 pSampleLocationsInfo->pSampleLocations, samples); 781 782 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS; 783} 784 785void anv_CmdSetLineStippleEXT( 786 VkCommandBuffer commandBuffer, 787 uint32_t lineStippleFactor, 788 uint16_t lineStipplePattern) 789{ 790 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 791 792 cmd_buffer->state.gfx.dynamic.line_stipple.factor = lineStippleFactor; 793 cmd_buffer->state.gfx.dynamic.line_stipple.pattern = lineStipplePattern; 794 795 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE; 796} 797 798void anv_CmdSetCullModeEXT( 799 VkCommandBuffer commandBuffer, 800 VkCullModeFlags cullMode) 801{ 802 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 803 804 cmd_buffer->state.gfx.dynamic.cull_mode = cullMode; 805 806 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_CULL_MODE; 807} 808 809void anv_CmdSetFrontFaceEXT( 810 VkCommandBuffer commandBuffer, 811 VkFrontFace frontFace) 812{ 813 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 814 815 cmd_buffer->state.gfx.dynamic.front_face = frontFace; 816 817 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE; 818} 819 820void anv_CmdSetDepthTestEnableEXT( 821 VkCommandBuffer commandBuffer, 822 VkBool32 depthTestEnable) 823 824{ 825 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 826 827 cmd_buffer->state.gfx.dynamic.depth_test_enable = depthTestEnable; 828 829 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE; 830} 831 832void anv_CmdSetDepthWriteEnableEXT( 833 VkCommandBuffer commandBuffer, 834 VkBool32 depthWriteEnable) 835{ 836 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 837 838 cmd_buffer->state.gfx.dynamic.depth_write_enable = depthWriteEnable; 839 840 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE; 841} 842 843void anv_CmdSetDepthCompareOpEXT( 844 VkCommandBuffer commandBuffer, 845 VkCompareOp depthCompareOp) 846{ 847 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 848 849 cmd_buffer->state.gfx.dynamic.depth_compare_op = depthCompareOp; 850 851 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP; 852} 853 854void anv_CmdSetDepthBoundsTestEnableEXT( 855 VkCommandBuffer commandBuffer, 856 VkBool32 depthBoundsTestEnable) 857{ 858 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 859 860 cmd_buffer->state.gfx.dynamic.depth_bounds_test_enable = depthBoundsTestEnable; 861 862 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE; 863} 864 865void anv_CmdSetStencilTestEnableEXT( 866 VkCommandBuffer commandBuffer, 867 VkBool32 stencilTestEnable) 868{ 869 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 870 871 cmd_buffer->state.gfx.dynamic.stencil_test_enable = stencilTestEnable; 872 873 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE; 874} 875 876void anv_CmdSetStencilOpEXT( 877 VkCommandBuffer commandBuffer, 878 VkStencilFaceFlags faceMask, 879 VkStencilOp failOp, 880 VkStencilOp passOp, 881 VkStencilOp depthFailOp, 882 VkCompareOp compareOp) 883{ 884 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 885 886 if (faceMask & VK_STENCIL_FACE_FRONT_BIT) { 887 cmd_buffer->state.gfx.dynamic.stencil_op.front.fail_op = failOp; 888 cmd_buffer->state.gfx.dynamic.stencil_op.front.pass_op = passOp; 889 cmd_buffer->state.gfx.dynamic.stencil_op.front.depth_fail_op = depthFailOp; 890 cmd_buffer->state.gfx.dynamic.stencil_op.front.compare_op = compareOp; 891 } 892 893 if (faceMask & VK_STENCIL_FACE_BACK_BIT) { 894 cmd_buffer->state.gfx.dynamic.stencil_op.back.fail_op = failOp; 895 cmd_buffer->state.gfx.dynamic.stencil_op.back.pass_op = passOp; 896 cmd_buffer->state.gfx.dynamic.stencil_op.back.depth_fail_op = depthFailOp; 897 cmd_buffer->state.gfx.dynamic.stencil_op.back.compare_op = compareOp; 898 } 899 900 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP; 901} 902 903static void 904anv_cmd_buffer_bind_descriptor_set(struct anv_cmd_buffer *cmd_buffer, 905 VkPipelineBindPoint bind_point, 906 struct anv_pipeline_layout *layout, 907 uint32_t set_index, 908 struct anv_descriptor_set *set, 909 uint32_t *dynamic_offset_count, 910 const uint32_t **dynamic_offsets) 911{ 912 struct anv_descriptor_set_layout *set_layout = 913 layout->set[set_index].layout; 914 915 VkShaderStageFlags stages = set_layout->shader_stages; 916 struct anv_cmd_pipeline_state *pipe_state; 917 918 switch (bind_point) { 919 case VK_PIPELINE_BIND_POINT_GRAPHICS: 920 stages &= VK_SHADER_STAGE_ALL_GRAPHICS; 921 pipe_state = &cmd_buffer->state.gfx.base; 922 break; 923 924 case VK_PIPELINE_BIND_POINT_COMPUTE: 925 stages &= VK_SHADER_STAGE_COMPUTE_BIT; 926 pipe_state = &cmd_buffer->state.compute.base; 927 break; 928 929 case VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR: 930 stages &= VK_SHADER_STAGE_RAYGEN_BIT_KHR | 931 VK_SHADER_STAGE_ANY_HIT_BIT_KHR | 932 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | 933 VK_SHADER_STAGE_MISS_BIT_KHR | 934 VK_SHADER_STAGE_INTERSECTION_BIT_KHR | 935 VK_SHADER_STAGE_CALLABLE_BIT_KHR; 936 pipe_state = &cmd_buffer->state.rt.base; 937 break; 938 939 default: 940 unreachable("invalid bind point"); 941 } 942 943 VkShaderStageFlags dirty_stages = 0; 944 /* If it's a push descriptor set, we have to flag things as dirty 945 * regardless of whether or not the CPU-side data structure changed as we 946 * may have edited in-place. 947 */ 948 if (pipe_state->descriptors[set_index] != set || 949 anv_descriptor_set_is_push(set)) { 950 pipe_state->descriptors[set_index] = set; 951 952 /* Ray-tracing shaders are entirely bindless and so they don't have 953 * access to HW binding tables. This means that we have to upload the 954 * descriptor set as an 64-bit address in the push constants. 955 */ 956 if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR) { 957 struct anv_push_constants *push = &pipe_state->push_constants; 958 959 struct anv_address addr = anv_descriptor_set_address(set); 960 push->desc_sets[set_index] = anv_address_physical(addr); 961 962 if (addr.bo) { 963 anv_reloc_list_add_bo(cmd_buffer->batch.relocs, 964 cmd_buffer->batch.alloc, 965 addr.bo); 966 } 967 } 968 969 dirty_stages |= stages; 970 } 971 972 if (dynamic_offsets) { 973 if (set_layout->dynamic_offset_count > 0) { 974 struct anv_push_constants *push = &pipe_state->push_constants; 975 uint32_t dynamic_offset_start = 976 layout->set[set_index].dynamic_offset_start; 977 uint32_t *push_offsets = 978 &push->dynamic_offsets[dynamic_offset_start]; 979 980 /* Assert that everything is in range */ 981 assert(set_layout->dynamic_offset_count <= *dynamic_offset_count); 982 assert(dynamic_offset_start + set_layout->dynamic_offset_count <= 983 ARRAY_SIZE(push->dynamic_offsets)); 984 985 for (uint32_t i = 0; i < set_layout->dynamic_offset_count; i++) { 986 if (push_offsets[i] != (*dynamic_offsets)[i]) { 987 push_offsets[i] = (*dynamic_offsets)[i]; 988 /* dynamic_offset_stages[] elements could contain blanket 989 * values like VK_SHADER_STAGE_ALL, so limit this to the 990 * binding point's bits. 991 */ 992 dirty_stages |= set_layout->dynamic_offset_stages[i] & stages; 993 } 994 } 995 996 *dynamic_offsets += set_layout->dynamic_offset_count; 997 *dynamic_offset_count -= set_layout->dynamic_offset_count; 998 } 999 } 1000 1001 cmd_buffer->state.descriptors_dirty |= dirty_stages; 1002 cmd_buffer->state.push_constants_dirty |= dirty_stages; 1003} 1004 1005void anv_CmdBindDescriptorSets( 1006 VkCommandBuffer commandBuffer, 1007 VkPipelineBindPoint pipelineBindPoint, 1008 VkPipelineLayout _layout, 1009 uint32_t firstSet, 1010 uint32_t descriptorSetCount, 1011 const VkDescriptorSet* pDescriptorSets, 1012 uint32_t dynamicOffsetCount, 1013 const uint32_t* pDynamicOffsets) 1014{ 1015 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 1016 ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout); 1017 1018 assert(firstSet + descriptorSetCount <= MAX_SETS); 1019 1020 for (uint32_t i = 0; i < descriptorSetCount; i++) { 1021 ANV_FROM_HANDLE(anv_descriptor_set, set, pDescriptorSets[i]); 1022 anv_cmd_buffer_bind_descriptor_set(cmd_buffer, pipelineBindPoint, 1023 layout, firstSet + i, set, 1024 &dynamicOffsetCount, 1025 &pDynamicOffsets); 1026 } 1027} 1028 1029void anv_CmdBindVertexBuffers2EXT( 1030 VkCommandBuffer commandBuffer, 1031 uint32_t firstBinding, 1032 uint32_t bindingCount, 1033 const VkBuffer* pBuffers, 1034 const VkDeviceSize* pOffsets, 1035 const VkDeviceSize* pSizes, 1036 const VkDeviceSize* pStrides) 1037{ 1038 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 1039 struct anv_vertex_binding *vb = cmd_buffer->state.vertex_bindings; 1040 1041 /* We have to defer setting up vertex buffer since we need the buffer 1042 * stride from the pipeline. */ 1043 1044 if (pSizes) 1045 cmd_buffer->state.gfx.dynamic.dyn_vbo_size = true; 1046 if (pStrides) 1047 cmd_buffer->state.gfx.dynamic.dyn_vbo_stride = true; 1048 1049 assert(firstBinding + bindingCount <= MAX_VBS); 1050 for (uint32_t i = 0; i < bindingCount; i++) { 1051 vb[firstBinding + i].buffer = anv_buffer_from_handle(pBuffers[i]); 1052 vb[firstBinding + i].offset = pOffsets[i]; 1053 vb[firstBinding + i].size = pSizes ? pSizes[i] : 0; 1054 vb[firstBinding + i].stride = pStrides ? pStrides[i] : 0; 1055 cmd_buffer->state.gfx.vb_dirty |= 1 << (firstBinding + i); 1056 } 1057} 1058 1059void anv_CmdBindVertexBuffers( 1060 VkCommandBuffer commandBuffer, 1061 uint32_t firstBinding, 1062 uint32_t bindingCount, 1063 const VkBuffer* pBuffers, 1064 const VkDeviceSize* pOffsets) 1065{ 1066 return anv_CmdBindVertexBuffers2EXT(commandBuffer, firstBinding, 1067 bindingCount, pBuffers, pOffsets, 1068 NULL, NULL); 1069} 1070 1071void anv_CmdBindTransformFeedbackBuffersEXT( 1072 VkCommandBuffer commandBuffer, 1073 uint32_t firstBinding, 1074 uint32_t bindingCount, 1075 const VkBuffer* pBuffers, 1076 const VkDeviceSize* pOffsets, 1077 const VkDeviceSize* pSizes) 1078{ 1079 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 1080 struct anv_xfb_binding *xfb = cmd_buffer->state.xfb_bindings; 1081 1082 /* We have to defer setting up vertex buffer since we need the buffer 1083 * stride from the pipeline. */ 1084 1085 assert(firstBinding + bindingCount <= MAX_XFB_BUFFERS); 1086 for (uint32_t i = 0; i < bindingCount; i++) { 1087 if (pBuffers[i] == VK_NULL_HANDLE) { 1088 xfb[firstBinding + i].buffer = NULL; 1089 } else { 1090 ANV_FROM_HANDLE(anv_buffer, buffer, pBuffers[i]); 1091 xfb[firstBinding + i].buffer = buffer; 1092 xfb[firstBinding + i].offset = pOffsets[i]; 1093 xfb[firstBinding + i].size = 1094 anv_buffer_get_range(buffer, pOffsets[i], 1095 pSizes ? pSizes[i] : VK_WHOLE_SIZE); 1096 } 1097 } 1098} 1099 1100enum isl_format 1101anv_isl_format_for_descriptor_type(const struct anv_device *device, 1102 VkDescriptorType type) 1103{ 1104 switch (type) { 1105 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 1106 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 1107 return device->physical->compiler->indirect_ubos_use_sampler ? 1108 ISL_FORMAT_R32G32B32A32_FLOAT : ISL_FORMAT_RAW; 1109 1110 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 1111 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 1112 return ISL_FORMAT_RAW; 1113 1114 default: 1115 unreachable("Invalid descriptor type"); 1116 } 1117} 1118 1119struct anv_state 1120anv_cmd_buffer_emit_dynamic(struct anv_cmd_buffer *cmd_buffer, 1121 const void *data, uint32_t size, uint32_t alignment) 1122{ 1123 struct anv_state state; 1124 1125 state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, size, alignment); 1126 memcpy(state.map, data, size); 1127 1128 VG(VALGRIND_CHECK_MEM_IS_DEFINED(state.map, size)); 1129 1130 return state; 1131} 1132 1133struct anv_state 1134anv_cmd_buffer_merge_dynamic(struct anv_cmd_buffer *cmd_buffer, 1135 uint32_t *a, uint32_t *b, 1136 uint32_t dwords, uint32_t alignment) 1137{ 1138 struct anv_state state; 1139 uint32_t *p; 1140 1141 state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, 1142 dwords * 4, alignment); 1143 p = state.map; 1144 for (uint32_t i = 0; i < dwords; i++) 1145 p[i] = a[i] | b[i]; 1146 1147 VG(VALGRIND_CHECK_MEM_IS_DEFINED(p, dwords * 4)); 1148 1149 return state; 1150} 1151 1152struct anv_state 1153anv_cmd_buffer_gfx_push_constants(struct anv_cmd_buffer *cmd_buffer) 1154{ 1155 struct anv_push_constants *data = 1156 &cmd_buffer->state.gfx.base.push_constants; 1157 1158 struct anv_state state = 1159 anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, 1160 sizeof(struct anv_push_constants), 1161 32 /* bottom 5 bits MBZ */); 1162 memcpy(state.map, data, sizeof(struct anv_push_constants)); 1163 1164 return state; 1165} 1166 1167struct anv_state 1168anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer *cmd_buffer) 1169{ 1170 const struct intel_device_info *devinfo = &cmd_buffer->device->info; 1171 struct anv_push_constants *data = 1172 &cmd_buffer->state.compute.base.push_constants; 1173 struct anv_compute_pipeline *pipeline = cmd_buffer->state.compute.pipeline; 1174 const struct brw_cs_prog_data *cs_prog_data = get_cs_prog_data(pipeline); 1175 const struct anv_push_range *range = &pipeline->cs->bind_map.push_ranges[0]; 1176 1177 const struct brw_cs_dispatch_info dispatch = 1178 brw_cs_get_dispatch_info(devinfo, cs_prog_data, NULL); 1179 const unsigned total_push_constants_size = 1180 brw_cs_push_const_total_size(cs_prog_data, dispatch.threads); 1181 if (total_push_constants_size == 0) 1182 return (struct anv_state) { .offset = 0 }; 1183 1184 const unsigned push_constant_alignment = 1185 cmd_buffer->device->info.ver < 8 ? 32 : 64; 1186 const unsigned aligned_total_push_constants_size = 1187 ALIGN(total_push_constants_size, push_constant_alignment); 1188 struct anv_state state; 1189 if (devinfo->verx10 >= 125) { 1190 state = anv_state_stream_alloc(&cmd_buffer->general_state_stream, 1191 aligned_total_push_constants_size, 1192 push_constant_alignment); 1193 } else { 1194 state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, 1195 aligned_total_push_constants_size, 1196 push_constant_alignment); 1197 } 1198 1199 void *dst = state.map; 1200 const void *src = (char *)data + (range->start * 32); 1201 1202 if (cs_prog_data->push.cross_thread.size > 0) { 1203 memcpy(dst, src, cs_prog_data->push.cross_thread.size); 1204 dst += cs_prog_data->push.cross_thread.size; 1205 src += cs_prog_data->push.cross_thread.size; 1206 } 1207 1208 if (cs_prog_data->push.per_thread.size > 0) { 1209 for (unsigned t = 0; t < dispatch.threads; t++) { 1210 memcpy(dst, src, cs_prog_data->push.per_thread.size); 1211 1212 uint32_t *subgroup_id = dst + 1213 offsetof(struct anv_push_constants, cs.subgroup_id) - 1214 (range->start * 32 + cs_prog_data->push.cross_thread.size); 1215 *subgroup_id = t; 1216 1217 dst += cs_prog_data->push.per_thread.size; 1218 } 1219 } 1220 1221 return state; 1222} 1223 1224void anv_CmdPushConstants( 1225 VkCommandBuffer commandBuffer, 1226 VkPipelineLayout layout, 1227 VkShaderStageFlags stageFlags, 1228 uint32_t offset, 1229 uint32_t size, 1230 const void* pValues) 1231{ 1232 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 1233 1234 if (stageFlags & VK_SHADER_STAGE_ALL_GRAPHICS) { 1235 struct anv_cmd_pipeline_state *pipe_state = 1236 &cmd_buffer->state.gfx.base; 1237 1238 memcpy(pipe_state->push_constants.client_data + offset, pValues, size); 1239 } 1240 if (stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) { 1241 struct anv_cmd_pipeline_state *pipe_state = 1242 &cmd_buffer->state.compute.base; 1243 1244 memcpy(pipe_state->push_constants.client_data + offset, pValues, size); 1245 } 1246 if (stageFlags & (VK_SHADER_STAGE_RAYGEN_BIT_KHR | 1247 VK_SHADER_STAGE_ANY_HIT_BIT_KHR | 1248 VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | 1249 VK_SHADER_STAGE_MISS_BIT_KHR | 1250 VK_SHADER_STAGE_INTERSECTION_BIT_KHR | 1251 VK_SHADER_STAGE_CALLABLE_BIT_KHR)) { 1252 struct anv_cmd_pipeline_state *pipe_state = 1253 &cmd_buffer->state.rt.base; 1254 1255 memcpy(pipe_state->push_constants.client_data + offset, pValues, size); 1256 } 1257 1258 cmd_buffer->state.push_constants_dirty |= stageFlags; 1259} 1260 1261VkResult anv_CreateCommandPool( 1262 VkDevice _device, 1263 const VkCommandPoolCreateInfo* pCreateInfo, 1264 const VkAllocationCallbacks* pAllocator, 1265 VkCommandPool* pCmdPool) 1266{ 1267 ANV_FROM_HANDLE(anv_device, device, _device); 1268 struct anv_cmd_pool *pool; 1269 1270 pool = vk_object_alloc(&device->vk, pAllocator, sizeof(*pool), 1271 VK_OBJECT_TYPE_COMMAND_POOL); 1272 if (pool == NULL) 1273 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 1274 1275 assert(pCreateInfo->queueFamilyIndex < device->physical->queue.family_count); 1276 pool->queue_family = 1277 &device->physical->queue.families[pCreateInfo->queueFamilyIndex]; 1278 1279 if (pAllocator) 1280 pool->alloc = *pAllocator; 1281 else 1282 pool->alloc = device->vk.alloc; 1283 1284 list_inithead(&pool->cmd_buffers); 1285 1286 pool->flags = pCreateInfo->flags; 1287 1288 *pCmdPool = anv_cmd_pool_to_handle(pool); 1289 1290 return VK_SUCCESS; 1291} 1292 1293void anv_DestroyCommandPool( 1294 VkDevice _device, 1295 VkCommandPool commandPool, 1296 const VkAllocationCallbacks* pAllocator) 1297{ 1298 ANV_FROM_HANDLE(anv_device, device, _device); 1299 ANV_FROM_HANDLE(anv_cmd_pool, pool, commandPool); 1300 1301 if (!pool) 1302 return; 1303 1304 list_for_each_entry_safe(struct anv_cmd_buffer, cmd_buffer, 1305 &pool->cmd_buffers, pool_link) { 1306 anv_cmd_buffer_destroy(cmd_buffer); 1307 } 1308 1309 vk_object_free(&device->vk, pAllocator, pool); 1310} 1311 1312VkResult anv_ResetCommandPool( 1313 VkDevice device, 1314 VkCommandPool commandPool, 1315 VkCommandPoolResetFlags flags) 1316{ 1317 ANV_FROM_HANDLE(anv_cmd_pool, pool, commandPool); 1318 1319 list_for_each_entry(struct anv_cmd_buffer, cmd_buffer, 1320 &pool->cmd_buffers, pool_link) { 1321 anv_cmd_buffer_reset(cmd_buffer); 1322 } 1323 1324 return VK_SUCCESS; 1325} 1326 1327void anv_TrimCommandPool( 1328 VkDevice device, 1329 VkCommandPool commandPool, 1330 VkCommandPoolTrimFlags flags) 1331{ 1332 /* Nothing for us to do here. Our pools stay pretty tidy. */ 1333} 1334 1335/** 1336 * Return NULL if the current subpass has no depthstencil attachment. 1337 */ 1338const struct anv_image_view * 1339anv_cmd_buffer_get_depth_stencil_view(const struct anv_cmd_buffer *cmd_buffer) 1340{ 1341 const struct anv_subpass *subpass = cmd_buffer->state.subpass; 1342 1343 if (subpass->depth_stencil_attachment == NULL) 1344 return NULL; 1345 1346 const struct anv_image_view *iview = 1347 cmd_buffer->state.attachments[subpass->depth_stencil_attachment->attachment].image_view; 1348 1349 assert(iview->vk.aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | 1350 VK_IMAGE_ASPECT_STENCIL_BIT)); 1351 1352 return iview; 1353} 1354 1355static struct anv_descriptor_set * 1356anv_cmd_buffer_push_descriptor_set(struct anv_cmd_buffer *cmd_buffer, 1357 VkPipelineBindPoint bind_point, 1358 struct anv_descriptor_set_layout *layout, 1359 uint32_t _set) 1360{ 1361 struct anv_cmd_pipeline_state *pipe_state; 1362 1363 switch (bind_point) { 1364 case VK_PIPELINE_BIND_POINT_GRAPHICS: 1365 pipe_state = &cmd_buffer->state.gfx.base; 1366 break; 1367 1368 case VK_PIPELINE_BIND_POINT_COMPUTE: 1369 pipe_state = &cmd_buffer->state.compute.base; 1370 break; 1371 1372 case VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR: 1373 pipe_state = &cmd_buffer->state.rt.base; 1374 break; 1375 1376 default: 1377 unreachable("invalid bind point"); 1378 } 1379 1380 struct anv_push_descriptor_set **push_set = 1381 &pipe_state->push_descriptors[_set]; 1382 1383 if (*push_set == NULL) { 1384 *push_set = vk_zalloc(&cmd_buffer->pool->alloc, 1385 sizeof(struct anv_push_descriptor_set), 8, 1386 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 1387 if (*push_set == NULL) { 1388 anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_OUT_OF_HOST_MEMORY); 1389 return NULL; 1390 } 1391 } 1392 1393 struct anv_descriptor_set *set = &(*push_set)->set; 1394 1395 if (set->layout != layout) { 1396 if (set->layout) 1397 anv_descriptor_set_layout_unref(cmd_buffer->device, set->layout); 1398 anv_descriptor_set_layout_ref(layout); 1399 set->layout = layout; 1400 } 1401 set->size = anv_descriptor_set_layout_size(layout, 0); 1402 set->buffer_view_count = layout->buffer_view_count; 1403 set->descriptor_count = layout->descriptor_count; 1404 set->buffer_views = (*push_set)->buffer_views; 1405 1406 if (layout->descriptor_buffer_size && 1407 ((*push_set)->set_used_on_gpu || 1408 set->desc_mem.alloc_size < layout->descriptor_buffer_size)) { 1409 /* The previous buffer is either actively used by some GPU command (so 1410 * we can't modify it) or is too small. Allocate a new one. 1411 */ 1412 struct anv_state desc_mem = 1413 anv_state_stream_alloc(&cmd_buffer->dynamic_state_stream, 1414 anv_descriptor_set_layout_descriptor_buffer_size(layout, 0), 1415 ANV_UBO_ALIGNMENT); 1416 if (set->desc_mem.alloc_size) { 1417 /* TODO: Do we really need to copy all the time? */ 1418 memcpy(desc_mem.map, set->desc_mem.map, 1419 MIN2(desc_mem.alloc_size, set->desc_mem.alloc_size)); 1420 } 1421 set->desc_mem = desc_mem; 1422 1423 set->desc_addr = (struct anv_address) { 1424 .bo = cmd_buffer->dynamic_state_stream.state_pool->block_pool.bo, 1425 .offset = set->desc_mem.offset, 1426 }; 1427 1428 enum isl_format format = 1429 anv_isl_format_for_descriptor_type(cmd_buffer->device, 1430 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); 1431 1432 const struct isl_device *isl_dev = &cmd_buffer->device->isl_dev; 1433 set->desc_surface_state = 1434 anv_state_stream_alloc(&cmd_buffer->surface_state_stream, 1435 isl_dev->ss.size, isl_dev->ss.align); 1436 anv_fill_buffer_surface_state(cmd_buffer->device, 1437 set->desc_surface_state, format, 1438 ISL_SURF_USAGE_CONSTANT_BUFFER_BIT, 1439 set->desc_addr, 1440 layout->descriptor_buffer_size, 1); 1441 } 1442 1443 return set; 1444} 1445 1446void anv_CmdPushDescriptorSetKHR( 1447 VkCommandBuffer commandBuffer, 1448 VkPipelineBindPoint pipelineBindPoint, 1449 VkPipelineLayout _layout, 1450 uint32_t _set, 1451 uint32_t descriptorWriteCount, 1452 const VkWriteDescriptorSet* pDescriptorWrites) 1453{ 1454 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 1455 ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout); 1456 1457 assert(_set < MAX_SETS); 1458 1459 struct anv_descriptor_set_layout *set_layout = layout->set[_set].layout; 1460 1461 struct anv_descriptor_set *set = 1462 anv_cmd_buffer_push_descriptor_set(cmd_buffer, pipelineBindPoint, 1463 set_layout, _set); 1464 if (!set) 1465 return; 1466 1467 /* Go through the user supplied descriptors. */ 1468 for (uint32_t i = 0; i < descriptorWriteCount; i++) { 1469 const VkWriteDescriptorSet *write = &pDescriptorWrites[i]; 1470 1471 switch (write->descriptorType) { 1472 case VK_DESCRIPTOR_TYPE_SAMPLER: 1473 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 1474 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 1475 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 1476 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 1477 for (uint32_t j = 0; j < write->descriptorCount; j++) { 1478 anv_descriptor_set_write_image_view(cmd_buffer->device, set, 1479 write->pImageInfo + j, 1480 write->descriptorType, 1481 write->dstBinding, 1482 write->dstArrayElement + j); 1483 } 1484 break; 1485 1486 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 1487 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 1488 for (uint32_t j = 0; j < write->descriptorCount; j++) { 1489 ANV_FROM_HANDLE(anv_buffer_view, bview, 1490 write->pTexelBufferView[j]); 1491 1492 anv_descriptor_set_write_buffer_view(cmd_buffer->device, set, 1493 write->descriptorType, 1494 bview, 1495 write->dstBinding, 1496 write->dstArrayElement + j); 1497 } 1498 break; 1499 1500 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 1501 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 1502 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 1503 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 1504 for (uint32_t j = 0; j < write->descriptorCount; j++) { 1505 ANV_FROM_HANDLE(anv_buffer, buffer, write->pBufferInfo[j].buffer); 1506 1507 anv_descriptor_set_write_buffer(cmd_buffer->device, set, 1508 &cmd_buffer->surface_state_stream, 1509 write->descriptorType, 1510 buffer, 1511 write->dstBinding, 1512 write->dstArrayElement + j, 1513 write->pBufferInfo[j].offset, 1514 write->pBufferInfo[j].range); 1515 } 1516 break; 1517 1518 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: { 1519 const VkWriteDescriptorSetAccelerationStructureKHR *accel_write = 1520 vk_find_struct_const(write, WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR); 1521 assert(accel_write->accelerationStructureCount == 1522 write->descriptorCount); 1523 for (uint32_t j = 0; j < write->descriptorCount; j++) { 1524 ANV_FROM_HANDLE(anv_acceleration_structure, accel, 1525 accel_write->pAccelerationStructures[j]); 1526 anv_descriptor_set_write_acceleration_structure(cmd_buffer->device, 1527 set, accel, 1528 write->dstBinding, 1529 write->dstArrayElement + j); 1530 } 1531 break; 1532 } 1533 1534 default: 1535 break; 1536 } 1537 } 1538 1539 anv_cmd_buffer_bind_descriptor_set(cmd_buffer, pipelineBindPoint, 1540 layout, _set, set, NULL, NULL); 1541} 1542 1543void anv_CmdPushDescriptorSetWithTemplateKHR( 1544 VkCommandBuffer commandBuffer, 1545 VkDescriptorUpdateTemplate descriptorUpdateTemplate, 1546 VkPipelineLayout _layout, 1547 uint32_t _set, 1548 const void* pData) 1549{ 1550 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 1551 ANV_FROM_HANDLE(anv_descriptor_update_template, template, 1552 descriptorUpdateTemplate); 1553 ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout); 1554 1555 assert(_set < MAX_PUSH_DESCRIPTORS); 1556 1557 struct anv_descriptor_set_layout *set_layout = layout->set[_set].layout; 1558 1559 struct anv_descriptor_set *set = 1560 anv_cmd_buffer_push_descriptor_set(cmd_buffer, template->bind_point, 1561 set_layout, _set); 1562 if (!set) 1563 return; 1564 1565 anv_descriptor_set_write_template(cmd_buffer->device, set, 1566 &cmd_buffer->surface_state_stream, 1567 template, 1568 pData); 1569 1570 anv_cmd_buffer_bind_descriptor_set(cmd_buffer, template->bind_point, 1571 layout, _set, set, NULL, NULL); 1572} 1573 1574void anv_CmdSetDeviceMask( 1575 VkCommandBuffer commandBuffer, 1576 uint32_t deviceMask) 1577{ 1578 /* No-op */ 1579} 1580 1581void anv_CmdSetColorWriteEnableEXT( 1582 VkCommandBuffer commandBuffer, 1583 uint32_t attachmentCount, 1584 const VkBool32* pColorWriteEnables) 1585{ 1586 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 1587 1588 assert(attachmentCount < MAX_RTS); 1589 1590 uint8_t color_writes = 0; 1591 for (uint32_t i = 0; i < attachmentCount; i++) 1592 color_writes |= pColorWriteEnables[i] ? (1 << i) : 0; 1593 1594 if (cmd_buffer->state.gfx.dynamic.color_writes != color_writes) { 1595 cmd_buffer->state.gfx.dynamic.color_writes = color_writes; 1596 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE; 1597 } 1598} 1599 1600void anv_CmdSetFragmentShadingRateKHR( 1601 VkCommandBuffer commandBuffer, 1602 const VkExtent2D* pFragmentSize, 1603 const VkFragmentShadingRateCombinerOpKHR combinerOps[2]) 1604{ 1605 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 1606 1607 cmd_buffer->state.gfx.dynamic.fragment_shading_rate = *pFragmentSize; 1608 cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE; 1609} 1610 1611static inline uint32_t 1612ilog2_round_up(uint32_t value) 1613{ 1614 assert(value != 0); 1615 return 32 - __builtin_clz(value - 1); 1616} 1617 1618void anv_CmdSetRayTracingPipelineStackSizeKHR( 1619 VkCommandBuffer commandBuffer, 1620 uint32_t pipelineStackSize) 1621{ 1622 ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); 1623 struct anv_cmd_ray_tracing_state *rt = &cmd_buffer->state.rt; 1624 struct anv_device *device = cmd_buffer->device; 1625 1626 if (anv_batch_has_error(&cmd_buffer->batch)) 1627 return; 1628 1629 uint32_t stack_ids_per_dss = 2048; /* TODO */ 1630 1631 unsigned stack_size_log2 = ilog2_round_up(pipelineStackSize); 1632 if (stack_size_log2 < 10) 1633 stack_size_log2 = 10; 1634 1635 if (rt->scratch.layout.total_size == 1 << stack_size_log2) 1636 return; 1637 1638 brw_rt_compute_scratch_layout(&rt->scratch.layout, &device->info, 1639 stack_ids_per_dss, 1 << stack_size_log2); 1640 1641 unsigned bucket = stack_size_log2 - 10; 1642 assert(bucket < ARRAY_SIZE(device->rt_scratch_bos)); 1643 1644 struct anv_bo *bo = p_atomic_read(&device->rt_scratch_bos[bucket]); 1645 if (bo == NULL) { 1646 struct anv_bo *new_bo; 1647 VkResult result = anv_device_alloc_bo(device, "RT scratch", 1648 rt->scratch.layout.total_size, 1649 0, /* alloc_flags */ 1650 0, /* explicit_address */ 1651 &new_bo); 1652 if (result != VK_SUCCESS) { 1653 rt->scratch.layout.total_size = 0; 1654 anv_batch_set_error(&cmd_buffer->batch, result); 1655 return; 1656 } 1657 1658 bo = p_atomic_cmpxchg(&device->rt_scratch_bos[bucket], NULL, new_bo); 1659 if (bo != NULL) { 1660 anv_device_release_bo(device, bo); 1661 } else { 1662 bo = new_bo; 1663 } 1664 } 1665 1666 rt->scratch.bo = bo; 1667} 1668