Path: blob/21.2-virgl/src/panfrost/vulkan/panvk_cmd_buffer.c
4560 views
/*1* Copyright © 2021 Collabora Ltd.2*3* Derived from tu_cmd_buffer.c which is:4* Copyright © 2016 Red Hat.5* Copyright © 2016 Bas Nieuwenhuizen6* Copyright © 2015 Intel Corporation7*8* Permission is hereby granted, free of charge, to any person obtaining a9* copy of this software and associated documentation files (the "Software"),10* to deal in the Software without restriction, including without limitation11* the rights to use, copy, modify, merge, publish, distribute, sublicense,12* and/or sell copies of the Software, and to permit persons to whom the13* Software is furnished to do so, subject to the following conditions:14*15* The above copyright notice and this permission notice (including the next16* paragraph) shall be included in all copies or substantial portions of the17* Software.18*19* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR20* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,21* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL22* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER23* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING24* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER25* DEALINGS IN THE SOFTWARE.26*/2728#include "panvk_cs.h"29#include "panvk_private.h"30#include "panfrost-quirks.h"3132#include "pan_blitter.h"33#include "pan_encoder.h"3435#include "util/rounding.h"36#include "util/u_pack_color.h"37#include "vk_format.h"3839static VkResult40panvk_reset_cmdbuf(struct panvk_cmd_buffer *cmdbuf)41{42struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;4344cmdbuf->record_result = VK_SUCCESS;4546list_for_each_entry_safe(struct panvk_batch, batch, &cmdbuf->batches, node) {47list_del(&batch->node);48util_dynarray_fini(&batch->jobs);49if (!pan_is_bifrost(pdev))50panfrost_bo_unreference(batch->tiler.ctx.midgard.polygon_list);5152util_dynarray_fini(&batch->event_ops);5354vk_free(&cmdbuf->pool->alloc, batch);55}5657panvk_pool_reset(&cmdbuf->desc_pool);58panvk_pool_reset(&cmdbuf->tls_pool);59panvk_pool_reset(&cmdbuf->varying_pool);60cmdbuf->status = PANVK_CMD_BUFFER_STATUS_INITIAL;6162for (unsigned i = 0; i < MAX_BIND_POINTS; i++)63memset(&cmdbuf->descriptors[i].sets, 0, sizeof(cmdbuf->descriptors[i].sets));6465return cmdbuf->record_result;66}6768static VkResult69panvk_create_cmdbuf(struct panvk_device *device,70struct panvk_cmd_pool *pool,71VkCommandBufferLevel level,72struct panvk_cmd_buffer **cmdbuf_out)73{74struct panvk_cmd_buffer *cmdbuf;7576cmdbuf = vk_object_zalloc(&device->vk, NULL, sizeof(*cmdbuf),77VK_OBJECT_TYPE_COMMAND_BUFFER);78if (!cmdbuf)79return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);8081cmdbuf->device = device;82cmdbuf->level = level;83cmdbuf->pool = pool;8485if (pool) {86list_addtail(&cmdbuf->pool_link, &pool->active_cmd_buffers);87cmdbuf->queue_family_index = pool->queue_family_index;88} else {89/* Init the pool_link so we can safely call list_del when we destroy90* the command buffer91*/92list_inithead(&cmdbuf->pool_link);93cmdbuf->queue_family_index = PANVK_QUEUE_GENERAL;94}9596panvk_pool_init(&cmdbuf->desc_pool, &device->physical_device->pdev,97pool ? &pool->desc_bo_pool : NULL, 0, 64 * 1024,98"Command buffer descriptor pool", true);99panvk_pool_init(&cmdbuf->tls_pool, &device->physical_device->pdev,100pool ? &pool->tls_bo_pool : NULL,101PAN_BO_INVISIBLE, 64 * 1024, "TLS pool", false);102panvk_pool_init(&cmdbuf->varying_pool, &device->physical_device->pdev,103pool ? &pool->varying_bo_pool : NULL,104PAN_BO_INVISIBLE, 64 * 1024, "Varyings pool", false);105list_inithead(&cmdbuf->batches);106cmdbuf->status = PANVK_CMD_BUFFER_STATUS_INITIAL;107*cmdbuf_out = cmdbuf;108return VK_SUCCESS;109}110111static void112panvk_destroy_cmdbuf(struct panvk_cmd_buffer *cmdbuf)113{114struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;115struct panvk_device *device = cmdbuf->device;116117list_del(&cmdbuf->pool_link);118119list_for_each_entry_safe(struct panvk_batch, batch, &cmdbuf->batches, node) {120list_del(&batch->node);121util_dynarray_fini(&batch->jobs);122if (!pan_is_bifrost(pdev))123panfrost_bo_unreference(batch->tiler.ctx.midgard.polygon_list);124125util_dynarray_fini(&batch->event_ops);126127vk_free(&cmdbuf->pool->alloc, batch);128}129130panvk_pool_cleanup(&cmdbuf->desc_pool);131panvk_pool_cleanup(&cmdbuf->tls_pool);132panvk_pool_cleanup(&cmdbuf->varying_pool);133vk_object_free(&device->vk, NULL, cmdbuf);134}135136VkResult137panvk_AllocateCommandBuffers(VkDevice _device,138const VkCommandBufferAllocateInfo *pAllocateInfo,139VkCommandBuffer *pCommandBuffers)140{141VK_FROM_HANDLE(panvk_device, device, _device);142VK_FROM_HANDLE(panvk_cmd_pool, pool, pAllocateInfo->commandPool);143144VkResult result = VK_SUCCESS;145unsigned i;146147for (i = 0; i < pAllocateInfo->commandBufferCount; i++) {148struct panvk_cmd_buffer *cmdbuf = NULL;149150if (!list_is_empty(&pool->free_cmd_buffers)) {151cmdbuf = list_first_entry(152&pool->free_cmd_buffers, struct panvk_cmd_buffer, pool_link);153154list_del(&cmdbuf->pool_link);155list_addtail(&cmdbuf->pool_link, &pool->active_cmd_buffers);156157cmdbuf->level = pAllocateInfo->level;158vk_object_base_reset(&cmdbuf->base);159} else {160result = panvk_create_cmdbuf(device, pool, pAllocateInfo->level, &cmdbuf);161}162163if (result != VK_SUCCESS)164goto err_free_cmd_bufs;165166pCommandBuffers[i] = panvk_cmd_buffer_to_handle(cmdbuf);167}168169return VK_SUCCESS;170171err_free_cmd_bufs:172panvk_FreeCommandBuffers(_device, pAllocateInfo->commandPool, i,173pCommandBuffers);174for (unsigned j = 0; j < i; j++)175pCommandBuffers[j] = VK_NULL_HANDLE;176177return result;178}179180void181panvk_FreeCommandBuffers(VkDevice device,182VkCommandPool commandPool,183uint32_t commandBufferCount,184const VkCommandBuffer *pCommandBuffers)185{186for (uint32_t i = 0; i < commandBufferCount; i++) {187VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, pCommandBuffers[i]);188189if (cmdbuf) {190if (cmdbuf->pool) {191list_del(&cmdbuf->pool_link);192panvk_reset_cmdbuf(cmdbuf);193list_addtail(&cmdbuf->pool_link,194&cmdbuf->pool->free_cmd_buffers);195} else196panvk_destroy_cmdbuf(cmdbuf);197}198}199}200201VkResult202panvk_ResetCommandBuffer(VkCommandBuffer commandBuffer,203VkCommandBufferResetFlags flags)204{205VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);206207return panvk_reset_cmdbuf(cmdbuf);208}209210VkResult211panvk_BeginCommandBuffer(VkCommandBuffer commandBuffer,212const VkCommandBufferBeginInfo *pBeginInfo)213{214VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);215VkResult result = VK_SUCCESS;216217if (cmdbuf->status != PANVK_CMD_BUFFER_STATUS_INITIAL) {218/* If the command buffer has already been reset with219* vkResetCommandBuffer, no need to do it again.220*/221result = panvk_reset_cmdbuf(cmdbuf);222if (result != VK_SUCCESS)223return result;224}225226memset(&cmdbuf->state, 0, sizeof(cmdbuf->state));227228cmdbuf->status = PANVK_CMD_BUFFER_STATUS_RECORDING;229230return VK_SUCCESS;231}232233void234panvk_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,235uint32_t firstBinding,236uint32_t bindingCount,237const VkBuffer *pBuffers,238const VkDeviceSize *pOffsets)239{240VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);241242assert(firstBinding + bindingCount <= MAX_VBS);243244for (uint32_t i = 0; i < bindingCount; i++) {245struct panvk_buffer *buf = panvk_buffer_from_handle(pBuffers[i]);246247cmdbuf->state.vb.bufs[firstBinding + i].address = buf->bo->ptr.gpu + pOffsets[i];248cmdbuf->state.vb.bufs[firstBinding + i].size = buf->size - pOffsets[i];249}250cmdbuf->state.vb.count = MAX2(cmdbuf->state.vb.count, firstBinding + bindingCount);251cmdbuf->state.vb.attrib_bufs = cmdbuf->state.vb.attribs = 0;252}253254void255panvk_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,256VkBuffer buffer,257VkDeviceSize offset,258VkIndexType indexType)259{260panvk_stub();261}262263void264panvk_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,265VkPipelineBindPoint pipelineBindPoint,266VkPipelineLayout _layout,267uint32_t firstSet,268uint32_t descriptorSetCount,269const VkDescriptorSet *pDescriptorSets,270uint32_t dynamicOffsetCount,271const uint32_t *pDynamicOffsets)272{273VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);274VK_FROM_HANDLE(panvk_pipeline_layout, layout, _layout);275276struct panvk_descriptor_state *descriptors_state =277&cmdbuf->descriptors[pipelineBindPoint];278279for (unsigned i = 0; i < descriptorSetCount; ++i) {280unsigned idx = i + firstSet;281VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorSets[i]);282283descriptors_state->sets[idx].set = set;284285if (layout->num_dynoffsets) {286assert(dynamicOffsetCount >= set->layout->num_dynoffsets);287288descriptors_state->sets[idx].dynoffsets =289pan_pool_alloc_aligned(&cmdbuf->desc_pool.base,290ALIGN(layout->num_dynoffsets, 4) *291sizeof(*pDynamicOffsets),29216);293memcpy(descriptors_state->sets[idx].dynoffsets.cpu,294pDynamicOffsets,295sizeof(*pDynamicOffsets) * set->layout->num_dynoffsets);296dynamicOffsetCount -= set->layout->num_dynoffsets;297pDynamicOffsets += set->layout->num_dynoffsets;298}299300if (set->layout->num_ubos || set->layout->num_dynoffsets)301descriptors_state->ubos = 0;302303if (set->layout->num_textures)304descriptors_state->textures = 0;305306if (set->layout->num_samplers)307descriptors_state->samplers = 0;308}309310assert(!dynamicOffsetCount);311}312313void314panvk_CmdPushConstants(VkCommandBuffer commandBuffer,315VkPipelineLayout layout,316VkShaderStageFlags stageFlags,317uint32_t offset,318uint32_t size,319const void *pValues)320{321panvk_stub();322}323324VkResult325panvk_EndCommandBuffer(VkCommandBuffer commandBuffer)326{327VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);328329cmdbuf->status = PANVK_CMD_BUFFER_STATUS_EXECUTABLE;330331return cmdbuf->record_result;332}333334void335panvk_CmdBindPipeline(VkCommandBuffer commandBuffer,336VkPipelineBindPoint pipelineBindPoint,337VkPipeline _pipeline)338{339VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);340VK_FROM_HANDLE(panvk_pipeline, pipeline, _pipeline);341342cmdbuf->state.bind_point = pipelineBindPoint;343cmdbuf->state.pipeline = pipeline;344cmdbuf->state.varyings = pipeline->varyings;345cmdbuf->state.vb.attrib_bufs = cmdbuf->state.vb.attribs = 0;346cmdbuf->state.fs_rsd = 0;347memset(cmdbuf->descriptors[pipelineBindPoint].sysvals, 0,348sizeof(cmdbuf->descriptors[pipelineBindPoint].sysvals));349350/* Sysvals are passed through UBOs, we need dirty the UBO array if the351* pipeline contain shaders using sysvals.352*/353if (pipeline->num_sysvals)354cmdbuf->descriptors[pipelineBindPoint].ubos = 0;355}356357void358panvk_CmdSetViewport(VkCommandBuffer commandBuffer,359uint32_t firstViewport,360uint32_t viewportCount,361const VkViewport *pViewports)362{363VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);364assert(viewportCount == 1);365assert(!firstViewport);366367cmdbuf->state.viewport = pViewports[0];368cmdbuf->state.vpd = 0;369cmdbuf->state.dirty |= PANVK_DYNAMIC_VIEWPORT;370}371372void373panvk_CmdSetScissor(VkCommandBuffer commandBuffer,374uint32_t firstScissor,375uint32_t scissorCount,376const VkRect2D *pScissors)377{378VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);379assert(scissorCount == 1);380assert(!firstScissor);381382cmdbuf->state.scissor = pScissors[0];383cmdbuf->state.vpd = 0;384cmdbuf->state.dirty |= PANVK_DYNAMIC_SCISSOR;385}386387void388panvk_CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth)389{390VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);391392cmdbuf->state.rast.line_width = lineWidth;393cmdbuf->state.dirty |= PANVK_DYNAMIC_LINE_WIDTH;394}395396void397panvk_CmdSetDepthBias(VkCommandBuffer commandBuffer,398float depthBiasConstantFactor,399float depthBiasClamp,400float depthBiasSlopeFactor)401{402VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);403404cmdbuf->state.rast.depth_bias.constant_factor = depthBiasConstantFactor;405cmdbuf->state.rast.depth_bias.clamp = depthBiasClamp;406cmdbuf->state.rast.depth_bias.slope_factor = depthBiasSlopeFactor;407cmdbuf->state.dirty |= PANVK_DYNAMIC_DEPTH_BIAS;408cmdbuf->state.fs_rsd = 0;409}410411void412panvk_CmdSetBlendConstants(VkCommandBuffer commandBuffer,413const float blendConstants[4])414{415VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);416417memcpy(cmdbuf->state.blend.constants, blendConstants,418sizeof(cmdbuf->state.blend.constants));419cmdbuf->state.dirty |= PANVK_DYNAMIC_BLEND_CONSTANTS;420cmdbuf->state.fs_rsd = 0;421}422423void424panvk_CmdSetDepthBounds(VkCommandBuffer commandBuffer,425float minDepthBounds,426float maxDepthBounds)427{428panvk_stub();429}430431void432panvk_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer,433VkStencilFaceFlags faceMask,434uint32_t compareMask)435{436VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);437438if (faceMask & VK_STENCIL_FACE_FRONT_BIT)439cmdbuf->state.zs.s_front.compare_mask = compareMask;440441if (faceMask & VK_STENCIL_FACE_BACK_BIT)442cmdbuf->state.zs.s_back.compare_mask = compareMask;443444cmdbuf->state.dirty |= PANVK_DYNAMIC_STENCIL_COMPARE_MASK;445cmdbuf->state.fs_rsd = 0;446}447448void449panvk_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer,450VkStencilFaceFlags faceMask,451uint32_t writeMask)452{453VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);454455if (faceMask & VK_STENCIL_FACE_FRONT_BIT)456cmdbuf->state.zs.s_front.write_mask = writeMask;457458if (faceMask & VK_STENCIL_FACE_BACK_BIT)459cmdbuf->state.zs.s_back.write_mask = writeMask;460461cmdbuf->state.dirty |= PANVK_DYNAMIC_STENCIL_WRITE_MASK;462cmdbuf->state.fs_rsd = 0;463}464465void466panvk_CmdSetStencilReference(VkCommandBuffer commandBuffer,467VkStencilFaceFlags faceMask,468uint32_t reference)469{470VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);471472if (faceMask & VK_STENCIL_FACE_FRONT_BIT)473cmdbuf->state.zs.s_front.ref = reference;474475if (faceMask & VK_STENCIL_FACE_BACK_BIT)476cmdbuf->state.zs.s_back.ref = reference;477478cmdbuf->state.dirty |= PANVK_DYNAMIC_STENCIL_REFERENCE;479cmdbuf->state.fs_rsd = 0;480}481482void483panvk_CmdExecuteCommands(VkCommandBuffer commandBuffer,484uint32_t commandBufferCount,485const VkCommandBuffer *pCmdBuffers)486{487panvk_stub();488}489490VkResult491panvk_CreateCommandPool(VkDevice _device,492const VkCommandPoolCreateInfo *pCreateInfo,493const VkAllocationCallbacks *pAllocator,494VkCommandPool *pCmdPool)495{496VK_FROM_HANDLE(panvk_device, device, _device);497struct panvk_cmd_pool *pool;498499pool = vk_object_alloc(&device->vk, pAllocator, sizeof(*pool),500VK_OBJECT_TYPE_COMMAND_POOL);501if (pool == NULL)502return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);503504if (pAllocator)505pool->alloc = *pAllocator;506else507pool->alloc = device->vk.alloc;508509list_inithead(&pool->active_cmd_buffers);510list_inithead(&pool->free_cmd_buffers);511512pool->queue_family_index = pCreateInfo->queueFamilyIndex;513panvk_bo_pool_init(&pool->desc_bo_pool);514panvk_bo_pool_init(&pool->varying_bo_pool);515panvk_bo_pool_init(&pool->tls_bo_pool);516*pCmdPool = panvk_cmd_pool_to_handle(pool);517return VK_SUCCESS;518}519520void521panvk_DestroyCommandPool(VkDevice _device,522VkCommandPool commandPool,523const VkAllocationCallbacks *pAllocator)524{525VK_FROM_HANDLE(panvk_device, device, _device);526VK_FROM_HANDLE(panvk_cmd_pool, pool, commandPool);527528list_for_each_entry_safe(struct panvk_cmd_buffer, cmdbuf,529&pool->active_cmd_buffers, pool_link)530panvk_destroy_cmdbuf(cmdbuf);531532list_for_each_entry_safe(struct panvk_cmd_buffer, cmdbuf,533&pool->free_cmd_buffers, pool_link)534panvk_destroy_cmdbuf(cmdbuf);535536panvk_bo_pool_cleanup(&pool->desc_bo_pool);537panvk_bo_pool_cleanup(&pool->varying_bo_pool);538panvk_bo_pool_cleanup(&pool->tls_bo_pool);539vk_object_free(&device->vk, pAllocator, pool);540}541542VkResult543panvk_ResetCommandPool(VkDevice device,544VkCommandPool commandPool,545VkCommandPoolResetFlags flags)546{547VK_FROM_HANDLE(panvk_cmd_pool, pool, commandPool);548VkResult result;549550list_for_each_entry(struct panvk_cmd_buffer, cmdbuf, &pool->active_cmd_buffers,551pool_link)552{553result = panvk_reset_cmdbuf(cmdbuf);554if (result != VK_SUCCESS)555return result;556}557558return VK_SUCCESS;559}560561void562panvk_TrimCommandPool(VkDevice device,563VkCommandPool commandPool,564VkCommandPoolTrimFlags flags)565{566VK_FROM_HANDLE(panvk_cmd_pool, pool, commandPool);567568if (!pool)569return;570571list_for_each_entry_safe(struct panvk_cmd_buffer, cmdbuf,572&pool->free_cmd_buffers, pool_link)573panvk_destroy_cmdbuf(cmdbuf);574}575576static void577panvk_pack_color_32(uint32_t *packed, uint32_t v)578{579for (unsigned i = 0; i < 4; ++i)580packed[i] = v;581}582583static void584panvk_pack_color_64(uint32_t *packed, uint32_t lo, uint32_t hi)585{586for (unsigned i = 0; i < 4; i += 2) {587packed[i + 0] = lo;588packed[i + 1] = hi;589}590}591592void593panvk_pack_color(struct panvk_clear_value *out,594const VkClearColorValue *in,595enum pipe_format format)596{597const struct util_format_description *desc = util_format_description(format);598599/* Alpha magicked to 1.0 if there is no alpha */600bool has_alpha = util_format_has_alpha(format);601float clear_alpha = has_alpha ? in->float32[3] : 1.0f;602uint32_t *packed = out->color;603604if (util_format_is_rgba8_variant(desc) && desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {605panvk_pack_color_32(packed,606((uint32_t) float_to_ubyte(clear_alpha) << 24) |607((uint32_t) float_to_ubyte(in->float32[2]) << 16) |608((uint32_t) float_to_ubyte(in->float32[1]) << 8) |609((uint32_t) float_to_ubyte(in->float32[0]) << 0));610} else if (format == PIPE_FORMAT_B5G6R5_UNORM) {611/* First, we convert the components to R5, G6, B5 separately */612unsigned r5 = _mesa_roundevenf(SATURATE(in->float32[0]) * 31.0);613unsigned g6 = _mesa_roundevenf(SATURATE(in->float32[1]) * 63.0);614unsigned b5 = _mesa_roundevenf(SATURATE(in->float32[2]) * 31.0);615616/* Then we pack into a sparse u32. TODO: Why these shifts? */617panvk_pack_color_32(packed, (b5 << 25) | (g6 << 14) | (r5 << 5));618} else if (format == PIPE_FORMAT_B4G4R4A4_UNORM) {619/* Convert to 4-bits */620unsigned r4 = _mesa_roundevenf(SATURATE(in->float32[0]) * 15.0);621unsigned g4 = _mesa_roundevenf(SATURATE(in->float32[1]) * 15.0);622unsigned b4 = _mesa_roundevenf(SATURATE(in->float32[2]) * 15.0);623unsigned a4 = _mesa_roundevenf(SATURATE(clear_alpha) * 15.0);624625/* Pack on *byte* intervals */626panvk_pack_color_32(packed, (a4 << 28) | (b4 << 20) | (g4 << 12) | (r4 << 4));627} else if (format == PIPE_FORMAT_B5G5R5A1_UNORM) {628/* Scale as expected but shift oddly */629unsigned r5 = _mesa_roundevenf(SATURATE(in->float32[0]) * 31.0);630unsigned g5 = _mesa_roundevenf(SATURATE(in->float32[1]) * 31.0);631unsigned b5 = _mesa_roundevenf(SATURATE(in->float32[2]) * 31.0);632unsigned a1 = _mesa_roundevenf(SATURATE(clear_alpha) * 1.0);633634panvk_pack_color_32(packed, (a1 << 31) | (b5 << 25) | (g5 << 15) | (r5 << 5));635} else {636/* Otherwise, it's generic subject to replication */637638union util_color out = { 0 };639unsigned size = util_format_get_blocksize(format);640641util_pack_color(in->float32, format, &out);642643if (size == 1) {644unsigned b = out.ui[0];645unsigned s = b | (b << 8);646panvk_pack_color_32(packed, s | (s << 16));647} else if (size == 2)648panvk_pack_color_32(packed, out.ui[0] | (out.ui[0] << 16));649else if (size == 3 || size == 4)650panvk_pack_color_32(packed, out.ui[0]);651else if (size == 6 || size == 8)652panvk_pack_color_64(packed, out.ui[0], out.ui[1]);653else if (size == 12 || size == 16)654memcpy(packed, out.ui, 16);655else656unreachable("Unknown generic format size packing clear colour");657}658}659660static void661panvk_cmd_prepare_clear_values(struct panvk_cmd_buffer *cmdbuf,662const VkClearValue *in)663{664for (unsigned i = 0; i < cmdbuf->state.pass->attachment_count; i++) {665const struct panvk_render_pass_attachment *attachment =666&cmdbuf->state.pass->attachments[i];667enum pipe_format fmt = attachment->format;668669if (util_format_is_depth_or_stencil(fmt)) {670if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR ||671attachment->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {672cmdbuf->state.clear[i].depth = in[i].depthStencil.depth;673cmdbuf->state.clear[i].stencil = in[i].depthStencil.stencil;674}675} else if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {676panvk_pack_color(&cmdbuf->state.clear[i], &in[i].color, fmt);677}678}679}680681void682panvk_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,683const VkRenderPassBeginInfo *pRenderPassBegin,684const VkSubpassBeginInfo *pSubpassBeginInfo)685{686VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);687VK_FROM_HANDLE(panvk_render_pass, pass, pRenderPassBegin->renderPass);688VK_FROM_HANDLE(panvk_framebuffer, fb, pRenderPassBegin->framebuffer);689690cmdbuf->state.pass = pass;691cmdbuf->state.subpass = pass->subpasses;692cmdbuf->state.framebuffer = fb;693cmdbuf->state.render_area = pRenderPassBegin->renderArea;694cmdbuf->state.batch = vk_zalloc(&cmdbuf->pool->alloc,695sizeof(*cmdbuf->state.batch), 8,696VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);697util_dynarray_init(&cmdbuf->state.batch->jobs, NULL);698util_dynarray_init(&cmdbuf->state.batch->event_ops, NULL);699cmdbuf->state.clear = vk_zalloc(&cmdbuf->pool->alloc,700sizeof(*cmdbuf->state.clear) *701pRenderPassBegin->clearValueCount, 8,702VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);703assert(pRenderPassBegin->clearValueCount == pass->attachment_count);704panvk_cmd_prepare_clear_values(cmdbuf, pRenderPassBegin->pClearValues);705memset(&cmdbuf->state.compute, 0, sizeof(cmdbuf->state.compute));706}707708void709panvk_CmdBeginRenderPass(VkCommandBuffer cmd,710const VkRenderPassBeginInfo *info,711VkSubpassContents contents)712{713VkSubpassBeginInfo subpass_info = {714.sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,715.contents = contents716};717718return panvk_CmdBeginRenderPass2(cmd, info, &subpass_info);719}720721static void722panvk_cmd_prepare_fragment_job(struct panvk_cmd_buffer *cmdbuf)723{724assert(cmdbuf->state.bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS);725726struct panvk_batch *batch = cmdbuf->state.batch;727struct panfrost_ptr job_ptr =728pan_pool_alloc_desc(&cmdbuf->desc_pool.base, FRAGMENT_JOB);729730panvk_emit_fragment_job(cmdbuf->device, cmdbuf->state.framebuffer,731cmdbuf->state.batch->fb.desc.gpu,732job_ptr.cpu);733cmdbuf->state.batch->fragment_job = job_ptr.gpu;734util_dynarray_append(&batch->jobs, void *, job_ptr.cpu);735}736737void738panvk_cmd_get_midgard_polygon_list(struct panvk_cmd_buffer *cmdbuf,739unsigned width, unsigned height,740bool has_draws)741{742struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;743struct panvk_batch *batch = cmdbuf->state.batch;744745assert(!pan_is_bifrost(pdev));746747if (batch->tiler.ctx.midgard.polygon_list)748return;749750unsigned size =751panfrost_tiler_get_polygon_list_size(pdev, width, height, has_draws);752size = util_next_power_of_two(size);753754/* Create the BO as invisible if we can. In the non-hierarchical tiler case,755* we need to write the polygon list manually because there's not WRITE_VALUE756* job in the chain. */757bool init_polygon_list = !has_draws && (pdev->quirks & MIDGARD_NO_HIER_TILING);758batch->tiler.ctx.midgard.polygon_list =759panfrost_bo_create(pdev, size,760init_polygon_list ? 0 : PAN_BO_INVISIBLE,761"Polygon list");762763764if (init_polygon_list) {765assert(batch->tiler.ctx.midgard.polygon_list->ptr.cpu);766uint32_t *polygon_list_body =767batch->tiler.ctx.midgard.polygon_list->ptr.cpu +768MALI_MIDGARD_TILER_MINIMUM_HEADER_SIZE;769polygon_list_body[0] = 0xa0000000;770}771772batch->tiler.ctx.midgard.disable = !has_draws;773}774775void776panvk_cmd_close_batch(struct panvk_cmd_buffer *cmdbuf)777{778struct panvk_batch *batch = cmdbuf->state.batch;779780assert(batch);781782if (!batch->fragment_job && !batch->scoreboard.first_job) {783if (util_dynarray_num_elements(&batch->event_ops, struct panvk_event_op) == 0) {784/* Content-less batch, let's drop it */785vk_free(&cmdbuf->pool->alloc, batch);786} else {787/* Batch has no jobs but is needed for synchronization, let's add a788* NULL job so the SUBMIT ioctl doesn't choke on it.789*/790struct panfrost_ptr ptr = pan_pool_alloc_desc(&cmdbuf->desc_pool.base,791JOB_HEADER);792util_dynarray_append(&batch->jobs, void *, ptr.cpu);793panfrost_add_job(&cmdbuf->desc_pool.base, &batch->scoreboard,794MALI_JOB_TYPE_NULL, false, false, 0, 0,795&ptr, false);796list_addtail(&batch->node, &cmdbuf->batches);797}798cmdbuf->state.batch = NULL;799return;800}801802struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;803804list_addtail(&cmdbuf->state.batch->node, &cmdbuf->batches);805806struct pan_tls_info tlsinfo = {807.tls.size = cmdbuf->state.pipeline->tls_size,808.wls.size = cmdbuf->state.pipeline->wls_size,809};810811if (tlsinfo.tls.size) {812tlsinfo.tls.ptr =813pan_pool_alloc_aligned(&cmdbuf->tls_pool.base, tlsinfo.tls.size, 4096).gpu;814}815816if (tlsinfo.wls.size) {817unsigned wls_size =818pan_wls_mem_size(pdev, &cmdbuf->state.compute.wg_count, tlsinfo.wls.size);819tlsinfo.wls.ptr =820pan_pool_alloc_aligned(&cmdbuf->tls_pool.base, wls_size, 4096).gpu;821}822823if ((pan_is_bifrost(pdev) || !cmdbuf->state.batch->fb.desc.cpu) &&824cmdbuf->state.batch->tls.cpu) {825pan_emit_tls(pdev, &tlsinfo, cmdbuf->state.batch->tls.cpu);826}827828if (cmdbuf->state.batch->fb.desc.cpu) {829if (!pan_is_bifrost(pdev)) {830panvk_cmd_get_midgard_polygon_list(cmdbuf,831batch->fb.info->width,832batch->fb.info->height,833false);834835mali_ptr polygon_list =836cmdbuf->state.batch->tiler.ctx.midgard.polygon_list->ptr.gpu;837struct panfrost_ptr writeval_job =838panfrost_scoreboard_initialize_tiler(&cmdbuf->desc_pool.base,839&cmdbuf->state.batch->scoreboard,840polygon_list);841if (writeval_job.cpu)842util_dynarray_append(&cmdbuf->state.batch->jobs, void *, writeval_job.cpu);843}844845cmdbuf->state.batch->fb.desc.gpu |=846panvk_emit_fb(cmdbuf->device,847cmdbuf->state.batch,848cmdbuf->state.subpass,849cmdbuf->state.pipeline,850cmdbuf->state.framebuffer,851cmdbuf->state.clear,852&tlsinfo, &cmdbuf->state.batch->tiler.ctx,853cmdbuf->state.batch->fb.desc.cpu);854855if (!pan_is_bifrost(pdev)) {856memcpy(&cmdbuf->state.batch->tiler.templ.midgard,857pan_section_ptr(cmdbuf->state.batch->fb.desc.cpu,858MULTI_TARGET_FRAMEBUFFER, TILER),859sizeof(cmdbuf->state.batch->tiler.templ.midgard));860}861862panvk_cmd_prepare_fragment_job(cmdbuf);863}864865cmdbuf->state.batch = NULL;866}867868void869panvk_cmd_open_batch(struct panvk_cmd_buffer *cmdbuf)870{871assert(!cmdbuf->state.batch);872cmdbuf->state.batch = vk_zalloc(&cmdbuf->pool->alloc,873sizeof(*cmdbuf->state.batch), 8,874VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);875assert(cmdbuf->state.batch);876}877878void879panvk_CmdNextSubpass2(VkCommandBuffer commandBuffer,880const VkSubpassBeginInfo *pSubpassBeginInfo,881const VkSubpassEndInfo *pSubpassEndInfo)882{883VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);884885panvk_cmd_close_batch(cmdbuf);886887cmdbuf->state.subpass++;888panvk_cmd_open_batch(cmdbuf);889memset(&cmdbuf->state.compute, 0, sizeof(cmdbuf->state.compute));890}891892void893panvk_CmdNextSubpass(VkCommandBuffer cmd, VkSubpassContents contents)894{895VkSubpassBeginInfo binfo = {896.sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,897.contents = contents898};899VkSubpassEndInfo einfo = {900.sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,901};902903panvk_CmdNextSubpass2(cmd, &binfo, &einfo);904}905906907static void908panvk_cmd_alloc_fb_desc(struct panvk_cmd_buffer *cmdbuf)909{910if (!cmdbuf->state.pipeline->fs.required)911return;912913struct panvk_batch *batch = cmdbuf->state.batch;914915if (batch->fb.desc.gpu)916return;917918const struct panvk_subpass *subpass = cmdbuf->state.subpass;919bool has_zs_ext = subpass->zs_attachment.idx != VK_ATTACHMENT_UNUSED;920unsigned tags = MALI_FBD_TAG_IS_MFBD;921922batch->fb.info = cmdbuf->state.framebuffer;923batch->fb.desc =924pan_pool_alloc_desc_aggregate(&cmdbuf->desc_pool.base,925PAN_DESC(MULTI_TARGET_FRAMEBUFFER),926PAN_DESC_ARRAY(has_zs_ext ? 1 : 0, ZS_CRC_EXTENSION),927PAN_DESC_ARRAY(MAX2(subpass->color_count, 1), RENDER_TARGET));928929/* Tag the pointer */930batch->fb.desc.gpu |= tags;931}932933static void934panvk_cmd_alloc_tls_desc(struct panvk_cmd_buffer *cmdbuf)935{936const struct panfrost_device *pdev =937&cmdbuf->device->physical_device->pdev;938struct panvk_batch *batch = cmdbuf->state.batch;939940assert(batch);941if (batch->tls.gpu)942return;943944if (!pan_is_bifrost(pdev) &&945cmdbuf->state.bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {946panvk_cmd_alloc_fb_desc(cmdbuf);947batch->tls = batch->fb.desc;948batch->tls.gpu &= ~63ULL;949} else {950batch->tls =951pan_pool_alloc_desc(&cmdbuf->desc_pool.base, LOCAL_STORAGE);952}953}954955static void956panvk_cmd_upload_sysval(struct panvk_cmd_buffer *cmdbuf,957unsigned id, union panvk_sysval_data *data)958{959switch (PAN_SYSVAL_TYPE(id)) {960case PAN_SYSVAL_VIEWPORT_SCALE:961panvk_sysval_upload_viewport_scale(&cmdbuf->state.viewport, data);962break;963case PAN_SYSVAL_VIEWPORT_OFFSET:964panvk_sysval_upload_viewport_offset(&cmdbuf->state.viewport, data);965break;966case PAN_SYSVAL_VERTEX_INSTANCE_OFFSETS:967/* TODO: support base_{vertex,instance} */968data->u32[0] = data->u32[1] = data->u32[2] = 0;969break;970default:971unreachable("Invalid static sysval");972}973}974975static void976panvk_cmd_prepare_sysvals(struct panvk_cmd_buffer *cmdbuf)977{978struct panvk_descriptor_state *desc_state =979&cmdbuf->descriptors[cmdbuf->state.bind_point];980const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;981982if (!pipeline->num_sysvals)983return;984985for (unsigned i = 0; i < ARRAY_SIZE(desc_state->sysvals); i++) {986unsigned sysval_count = pipeline->sysvals[i].ids.sysval_count;987if (!sysval_count ||988(desc_state->sysvals[i] &&989!(cmdbuf->state.dirty & pipeline->sysvals[i].dirty_mask)))990continue;991992struct panfrost_ptr sysvals =993pan_pool_alloc_aligned(&cmdbuf->desc_pool.base, sysval_count * 16, 16);994union panvk_sysval_data *data = sysvals.cpu;995996for (unsigned s = 0; s < pipeline->sysvals[i].ids.sysval_count; s++) {997panvk_cmd_upload_sysval(cmdbuf, pipeline->sysvals[i].ids.sysvals[s],998&data[s]);999}10001001desc_state->sysvals[i] = sysvals.gpu;1002}1003}10041005static void1006panvk_cmd_prepare_ubos(struct panvk_cmd_buffer *cmdbuf)1007{1008struct panvk_descriptor_state *desc_state =1009&cmdbuf->descriptors[cmdbuf->state.bind_point];1010const struct panvk_pipeline *pipeline =1011cmdbuf->state.pipeline;10121013if (!pipeline->num_ubos || desc_state->ubos)1014return;10151016panvk_cmd_prepare_sysvals(cmdbuf);10171018struct panfrost_ptr ubos =1019pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base,1020pipeline->num_ubos,1021UNIFORM_BUFFER);10221023panvk_emit_ubos(pipeline, desc_state, ubos.cpu);10241025desc_state->ubos = ubos.gpu;1026}10271028static void1029panvk_cmd_prepare_textures(struct panvk_cmd_buffer *cmdbuf)1030{1031struct panvk_descriptor_state *desc_state =1032&cmdbuf->descriptors[cmdbuf->state.bind_point];1033const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;1034unsigned num_textures = pipeline->layout->num_textures;10351036if (!num_textures || desc_state->textures)1037return;10381039const struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;1040unsigned tex_entry_size = pan_is_bifrost(pdev) ?1041sizeof(struct mali_bifrost_texture_packed) :1042sizeof(mali_ptr);1043struct panfrost_ptr textures =1044pan_pool_alloc_aligned(&cmdbuf->desc_pool.base,1045num_textures * tex_entry_size,1046tex_entry_size);10471048void *texture = textures.cpu;10491050for (unsigned i = 0; i < ARRAY_SIZE(desc_state->sets); i++) {1051if (!desc_state->sets[i].set) continue;10521053memcpy(texture,1054desc_state->sets[i].set->textures.midgard,1055desc_state->sets[i].set->layout->num_textures *1056tex_entry_size);10571058texture += desc_state->sets[i].set->layout->num_textures *1059tex_entry_size;1060}10611062desc_state->textures = textures.gpu;1063}10641065static void1066panvk_cmd_prepare_samplers(struct panvk_cmd_buffer *cmdbuf)1067{1068struct panvk_descriptor_state *desc_state =1069&cmdbuf->descriptors[cmdbuf->state.bind_point];1070const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;1071unsigned num_samplers = pipeline->layout->num_samplers;10721073if (!num_samplers || desc_state->samplers)1074return;10751076struct panfrost_ptr samplers =1077pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base,1078num_samplers,1079MIDGARD_SAMPLER);10801081struct mali_midgard_sampler_packed *sampler = samplers.cpu;10821083for (unsigned i = 0; i < ARRAY_SIZE(desc_state->sets); i++) {1084if (!desc_state->sets[i].set) continue;10851086memcpy(sampler,1087desc_state->sets[i].set->samplers,1088desc_state->sets[i].set->layout->num_samplers *1089sizeof(*sampler));10901091sampler += desc_state->sets[i].set->layout->num_samplers;1092}10931094desc_state->samplers = samplers.gpu;1095}10961097static void1098panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf,1099struct panvk_draw_info *draw)1100{1101const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;11021103if (!pipeline->fs.dynamic_rsd) {1104draw->fs_rsd = pipeline->rsds[MESA_SHADER_FRAGMENT];1105return;1106}11071108if (!cmdbuf->state.fs_rsd) {1109struct panfrost_ptr rsd =1110pan_pool_alloc_desc_aggregate(&cmdbuf->desc_pool.base,1111PAN_DESC(RENDERER_STATE),1112PAN_DESC_ARRAY(pipeline->blend.state.rt_count,1113BLEND));11141115struct mali_renderer_state_packed rsd_dyn;11161117panvk_emit_dyn_fs_rsd(cmdbuf->device, pipeline, &cmdbuf->state, &rsd_dyn);1118pan_merge(rsd_dyn, pipeline->fs.rsd_template, RENDERER_STATE);1119memcpy(rsd.cpu, &rsd_dyn, sizeof(rsd_dyn));11201121void *bd = rsd.cpu + MALI_RENDERER_STATE_LENGTH;1122for (unsigned i = 0; i < pipeline->blend.state.rt_count; i++) {1123if (pipeline->blend.constant[i].index != ~0) {1124struct mali_blend_packed bd_dyn;11251126panvk_emit_blend_constant(cmdbuf->device, pipeline, i,1127cmdbuf->state.blend.constants[i],1128&bd_dyn);1129pan_merge(bd_dyn, pipeline->blend.bd_template[i], BLEND);1130memcpy(bd, &bd_dyn, sizeof(bd_dyn));1131}1132bd += MALI_BLEND_LENGTH;1133}11341135cmdbuf->state.fs_rsd = rsd.gpu;1136}11371138draw->fs_rsd = cmdbuf->state.fs_rsd;1139}11401141void1142panvk_cmd_get_bifrost_tiler_context(struct panvk_cmd_buffer *cmdbuf,1143unsigned width, unsigned height)1144{1145struct panvk_batch *batch = cmdbuf->state.batch;11461147if (batch->tiler.bifrost_descs.cpu)1148return;11491150batch->tiler.bifrost_descs =1151pan_pool_alloc_desc_aggregate(&cmdbuf->desc_pool.base,1152PAN_DESC(BIFROST_TILER),1153PAN_DESC(BIFROST_TILER_HEAP));11541155panvk_emit_bifrost_tiler_context(cmdbuf->device, width, height,1156&batch->tiler.bifrost_descs);1157memcpy(&batch->tiler.templ.bifrost, batch->tiler.bifrost_descs.cpu,1158sizeof(batch->tiler.templ.bifrost));1159batch->tiler.ctx.bifrost = batch->tiler.bifrost_descs.gpu;1160}11611162static void1163panvk_draw_prepare_tiler_context(struct panvk_cmd_buffer *cmdbuf,1164struct panvk_draw_info *draw)1165{1166const struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;1167struct panvk_batch *batch = cmdbuf->state.batch;11681169if (pan_is_bifrost(pdev)) {1170panvk_cmd_get_bifrost_tiler_context(cmdbuf,1171batch->fb.info->width,1172batch->fb.info->height);1173} else {1174panvk_cmd_get_midgard_polygon_list(cmdbuf,1175batch->fb.info->width,1176batch->fb.info->height,1177true);1178}11791180draw->tiler_ctx = &batch->tiler.ctx;1181}11821183static void1184panvk_draw_prepare_varyings(struct panvk_cmd_buffer *cmdbuf,1185struct panvk_draw_info *draw)1186{1187const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;1188struct panvk_varyings_info *varyings = &cmdbuf->state.varyings;11891190panvk_varyings_alloc(varyings, &cmdbuf->varying_pool.base,1191draw->vertex_count);11921193unsigned buf_count = panvk_varyings_buf_count(cmdbuf->device, varyings);1194struct panfrost_ptr bufs =1195pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base,1196buf_count, ATTRIBUTE_BUFFER);11971198panvk_emit_varying_bufs(cmdbuf->device, varyings, bufs.cpu);1199if (BITSET_TEST(varyings->active, VARYING_SLOT_POS)) {1200draw->position = varyings->buf[varyings->varying[VARYING_SLOT_POS].buf].address +1201varyings->varying[VARYING_SLOT_POS].offset;1202}12031204if (BITSET_TEST(varyings->active, VARYING_SLOT_PSIZ)) {1205draw->psiz = varyings->buf[varyings->varying[VARYING_SLOT_PSIZ].buf].address +1206varyings->varying[VARYING_SLOT_POS].offset;1207} else if (pipeline->ia.topology == MALI_DRAW_MODE_LINES ||1208pipeline->ia.topology == MALI_DRAW_MODE_LINE_STRIP ||1209pipeline->ia.topology == MALI_DRAW_MODE_LINE_LOOP) {1210draw->line_width = pipeline->dynamic_state_mask & PANVK_DYNAMIC_LINE_WIDTH ?1211cmdbuf->state.rast.line_width : pipeline->rast.line_width;1212} else {1213draw->line_width = 1.0f;1214}1215draw->varying_bufs = bufs.gpu;12161217for (unsigned s = 0; s < MESA_SHADER_STAGES; s++) {1218if (!varyings->stage[s].count) continue;12191220struct panfrost_ptr attribs =1221pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base,1222varyings->stage[s].count,1223ATTRIBUTE);12241225panvk_emit_varyings(cmdbuf->device, varyings, s, attribs.cpu);1226draw->stages[s].varyings = attribs.gpu;1227}1228}12291230static void1231panvk_draw_prepare_attributes(struct panvk_cmd_buffer *cmdbuf,1232struct panvk_draw_info *draw)1233{1234/* TODO: images */1235const struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;12361237if (!cmdbuf->state.pipeline->attribs.buf_count)1238return;12391240if (cmdbuf->state.vb.attribs) {1241draw->stages[MESA_SHADER_VERTEX].attributes = cmdbuf->state.vb.attribs;1242draw->attribute_bufs = cmdbuf->state.vb.attrib_bufs;1243return;1244}12451246unsigned buf_count = cmdbuf->state.pipeline->attribs.buf_count +1247(pan_is_bifrost(pdev) ? 1 : 0);1248struct panfrost_ptr bufs =1249pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base,1250buf_count * 2, ATTRIBUTE_BUFFER);12511252panvk_emit_attrib_bufs(cmdbuf->device,1253&cmdbuf->state.pipeline->attribs,1254cmdbuf->state.vb.bufs, cmdbuf->state.vb.count,1255draw, bufs.cpu);1256cmdbuf->state.vb.attrib_bufs = bufs.gpu;12571258struct panfrost_ptr attribs =1259pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base,1260cmdbuf->state.pipeline->attribs.attrib_count,1261ATTRIBUTE);12621263panvk_emit_attribs(cmdbuf->device, &cmdbuf->state.pipeline->attribs,1264cmdbuf->state.vb.bufs, cmdbuf->state.vb.count,1265attribs.cpu);1266cmdbuf->state.vb.attribs = attribs.gpu;1267draw->stages[MESA_SHADER_VERTEX].attributes = cmdbuf->state.vb.attribs;1268draw->attribute_bufs = cmdbuf->state.vb.attrib_bufs;1269}12701271static void1272panvk_draw_prepare_viewport(struct panvk_cmd_buffer *cmdbuf,1273struct panvk_draw_info *draw)1274{1275const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;12761277if (pipeline->vpd) {1278draw->viewport = pipeline->vpd;1279} else if (cmdbuf->state.vpd) {1280draw->viewport = cmdbuf->state.vpd;1281} else {1282struct panfrost_ptr vp =1283pan_pool_alloc_desc(&cmdbuf->desc_pool.base, VIEWPORT);12841285const VkViewport *viewport =1286pipeline->dynamic_state_mask & PANVK_DYNAMIC_VIEWPORT ?1287&cmdbuf->state.viewport : &pipeline->viewport;1288const VkRect2D *scissor =1289pipeline->dynamic_state_mask & PANVK_DYNAMIC_SCISSOR ?1290&cmdbuf->state.scissor : &pipeline->scissor;12911292panvk_emit_viewport(viewport, scissor, vp.cpu);1293draw->viewport = cmdbuf->state.vpd = vp.gpu;1294}1295}12961297static void1298panvk_draw_prepare_vertex_job(struct panvk_cmd_buffer *cmdbuf,1299struct panvk_draw_info *draw)1300{1301struct panvk_batch *batch = cmdbuf->state.batch;1302struct panfrost_ptr ptr =1303pan_pool_alloc_desc(&cmdbuf->desc_pool.base, COMPUTE_JOB);13041305util_dynarray_append(&batch->jobs, void *, ptr.cpu);1306draw->jobs.vertex = ptr;1307panvk_emit_vertex_job(cmdbuf->device,1308cmdbuf->state.pipeline,1309draw, ptr.cpu);13101311}13121313static void1314panvk_draw_prepare_tiler_job(struct panvk_cmd_buffer *cmdbuf,1315struct panvk_draw_info *draw)1316{1317const struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;1318struct panvk_batch *batch = cmdbuf->state.batch;1319struct panfrost_ptr ptr =1320pan_is_bifrost(pdev) ?1321pan_pool_alloc_desc(&cmdbuf->desc_pool.base, BIFROST_TILER_JOB) :1322pan_pool_alloc_desc(&cmdbuf->desc_pool.base, MIDGARD_TILER_JOB);13231324util_dynarray_append(&batch->jobs, void *, ptr.cpu);1325draw->jobs.tiler = ptr;1326panvk_emit_tiler_job(cmdbuf->device,1327cmdbuf->state.pipeline,1328draw, ptr.cpu);1329}13301331void1332panvk_CmdDraw(VkCommandBuffer commandBuffer,1333uint32_t vertexCount,1334uint32_t instanceCount,1335uint32_t firstVertex,1336uint32_t firstInstance)1337{1338VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);13391340struct panvk_batch *batch = cmdbuf->state.batch;13411342panvk_cmd_alloc_fb_desc(cmdbuf);1343panvk_cmd_alloc_tls_desc(cmdbuf);1344panvk_cmd_prepare_ubos(cmdbuf);1345panvk_cmd_prepare_textures(cmdbuf);1346panvk_cmd_prepare_samplers(cmdbuf);13471348/* TODO: indexed draws */13491350struct panvk_draw_info draw = {1351.first_vertex = firstVertex,1352.vertex_count = vertexCount,1353.first_instance = firstInstance,1354.instance_count = instanceCount,1355.padded_vertex_count = panfrost_padded_vertex_count(vertexCount),1356.offset_start = firstVertex,1357.tls = batch->tls.gpu,1358.fb = batch->fb.desc.gpu,1359.ubos = cmdbuf->descriptors[VK_PIPELINE_BIND_POINT_GRAPHICS].ubos,1360.textures = cmdbuf->descriptors[VK_PIPELINE_BIND_POINT_GRAPHICS].textures,1361.samplers = cmdbuf->descriptors[VK_PIPELINE_BIND_POINT_GRAPHICS].samplers,1362};13631364panfrost_pack_work_groups_compute(&draw.invocation, 1, vertexCount,1365instanceCount, 1, 1, 1, true, false);1366panvk_draw_prepare_fs_rsd(cmdbuf, &draw);1367panvk_draw_prepare_varyings(cmdbuf, &draw);1368panvk_draw_prepare_attributes(cmdbuf, &draw);1369panvk_draw_prepare_viewport(cmdbuf, &draw);1370panvk_draw_prepare_tiler_context(cmdbuf, &draw);1371panvk_draw_prepare_vertex_job(cmdbuf, &draw);1372panvk_draw_prepare_tiler_job(cmdbuf, &draw);13731374const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;1375unsigned vjob_id =1376panfrost_add_job(&cmdbuf->desc_pool.base, &batch->scoreboard,1377MALI_JOB_TYPE_VERTEX, false, false, 0, 0,1378&draw.jobs.vertex, false);13791380if (pipeline->fs.required) {1381panfrost_add_job(&cmdbuf->desc_pool.base, &batch->scoreboard,1382MALI_JOB_TYPE_TILER, false, false, vjob_id, 0,1383&draw.jobs.tiler, false);1384}13851386/* Clear the dirty flags all at once */1387cmdbuf->state.dirty = 0;1388}13891390void1391panvk_CmdDrawIndexed(VkCommandBuffer commandBuffer,1392uint32_t indexCount,1393uint32_t instanceCount,1394uint32_t firstIndex,1395int32_t vertexOffset,1396uint32_t firstInstance)1397{1398panvk_stub();1399}14001401void1402panvk_CmdDrawIndirect(VkCommandBuffer commandBuffer,1403VkBuffer _buffer,1404VkDeviceSize offset,1405uint32_t drawCount,1406uint32_t stride)1407{1408panvk_stub();1409}14101411void1412panvk_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,1413VkBuffer _buffer,1414VkDeviceSize offset,1415uint32_t drawCount,1416uint32_t stride)1417{1418panvk_stub();1419}14201421void1422panvk_CmdDispatchBase(VkCommandBuffer commandBuffer,1423uint32_t base_x,1424uint32_t base_y,1425uint32_t base_z,1426uint32_t x,1427uint32_t y,1428uint32_t z)1429{1430panvk_stub();1431}14321433void1434panvk_CmdDispatch(VkCommandBuffer commandBuffer,1435uint32_t x,1436uint32_t y,1437uint32_t z)1438{1439panvk_stub();1440}14411442void1443panvk_CmdDispatchIndirect(VkCommandBuffer commandBuffer,1444VkBuffer _buffer,1445VkDeviceSize offset)1446{1447panvk_stub();1448}14491450void1451panvk_CmdEndRenderPass2(VkCommandBuffer commandBuffer,1452const VkSubpassEndInfoKHR *pSubpassEndInfo)1453{1454VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);14551456panvk_cmd_close_batch(cmdbuf);1457vk_free(&cmdbuf->pool->alloc, cmdbuf->state.clear);1458cmdbuf->state.batch = NULL;1459cmdbuf->state.pass = NULL;1460cmdbuf->state.subpass = NULL;1461cmdbuf->state.framebuffer = NULL;1462cmdbuf->state.clear = NULL;1463memset(&cmdbuf->state.compute, 0, sizeof(cmdbuf->state.compute));1464}14651466void1467panvk_CmdEndRenderPass(VkCommandBuffer cmd)1468{1469VkSubpassEndInfoKHR einfo = {1470.sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,1471};14721473panvk_CmdEndRenderPass2(cmd, &einfo);1474}147514761477void1478panvk_CmdPipelineBarrier(VkCommandBuffer commandBuffer,1479VkPipelineStageFlags srcStageMask,1480VkPipelineStageFlags destStageMask,1481VkDependencyFlags dependencyFlags,1482uint32_t memoryBarrierCount,1483const VkMemoryBarrier *pMemoryBarriers,1484uint32_t bufferMemoryBarrierCount,1485const VkBufferMemoryBarrier *pBufferMemoryBarriers,1486uint32_t imageMemoryBarrierCount,1487const VkImageMemoryBarrier *pImageMemoryBarriers)1488{1489VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);14901491/* Caches are flushed/invalidated at batch boundaries for now, nothing to do1492* for memory barriers assuming we implement barriers with the creation of a1493* new batch.1494* FIXME: We can probably do better with a CacheFlush job that has the1495* barrier flag set to true.1496*/1497if (cmdbuf->state.batch) {1498panvk_cmd_close_batch(cmdbuf);1499panvk_cmd_open_batch(cmdbuf);1500}1501}15021503static void1504panvk_add_set_event_operation(struct panvk_cmd_buffer *cmdbuf,1505struct panvk_event *event,1506enum panvk_event_op_type type)1507{1508struct panvk_event_op op = {1509.type = type,1510.event = event,1511};15121513if (cmdbuf->state.batch == NULL) {1514/* No open batch, let's create a new one so this operation happens in1515* the right order.1516*/1517panvk_cmd_open_batch(cmdbuf);1518util_dynarray_append(&cmdbuf->state.batch->event_ops,1519struct panvk_event_op,1520op);1521panvk_cmd_close_batch(cmdbuf);1522} else {1523/* Let's close the current batch so the operation executes before any1524* future commands.1525*/1526util_dynarray_append(&cmdbuf->state.batch->event_ops,1527struct panvk_event_op,1528op);1529panvk_cmd_close_batch(cmdbuf);1530panvk_cmd_open_batch(cmdbuf);1531}1532}15331534static void1535panvk_add_wait_event_operation(struct panvk_cmd_buffer *cmdbuf,1536struct panvk_event *event)1537{1538struct panvk_event_op op = {1539.type = PANVK_EVENT_OP_WAIT,1540.event = event,1541};15421543if (cmdbuf->state.batch == NULL) {1544/* No open batch, let's create a new one and have it wait for this event. */1545panvk_cmd_open_batch(cmdbuf);1546util_dynarray_append(&cmdbuf->state.batch->event_ops,1547struct panvk_event_op,1548op);1549} else {1550/* Let's close the current batch so any future commands wait on the1551* event signal operation.1552*/1553if (cmdbuf->state.batch->fragment_job ||1554cmdbuf->state.batch->scoreboard.first_job) {1555panvk_cmd_close_batch(cmdbuf);1556panvk_cmd_open_batch(cmdbuf);1557}1558util_dynarray_append(&cmdbuf->state.batch->event_ops,1559struct panvk_event_op,1560op);1561}1562}15631564void1565panvk_CmdSetEvent(VkCommandBuffer commandBuffer,1566VkEvent _event,1567VkPipelineStageFlags stageMask)1568{1569VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);1570VK_FROM_HANDLE(panvk_event, event, _event);15711572/* vkCmdSetEvent cannot be called inside a render pass */1573assert(cmdbuf->state.pass == NULL);15741575panvk_add_set_event_operation(cmdbuf, event, PANVK_EVENT_OP_SET);1576}15771578void1579panvk_CmdResetEvent(VkCommandBuffer commandBuffer,1580VkEvent _event,1581VkPipelineStageFlags stageMask)1582{1583VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);1584VK_FROM_HANDLE(panvk_event, event, _event);15851586/* vkCmdResetEvent cannot be called inside a render pass */1587assert(cmdbuf->state.pass == NULL);15881589panvk_add_set_event_operation(cmdbuf, event, PANVK_EVENT_OP_RESET);1590}15911592void1593panvk_CmdWaitEvents(VkCommandBuffer commandBuffer,1594uint32_t eventCount,1595const VkEvent *pEvents,1596VkPipelineStageFlags srcStageMask,1597VkPipelineStageFlags dstStageMask,1598uint32_t memoryBarrierCount,1599const VkMemoryBarrier *pMemoryBarriers,1600uint32_t bufferMemoryBarrierCount,1601const VkBufferMemoryBarrier *pBufferMemoryBarriers,1602uint32_t imageMemoryBarrierCount,1603const VkImageMemoryBarrier *pImageMemoryBarriers)1604{1605VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);16061607assert(eventCount > 0);16081609for (uint32_t i = 0; i < eventCount; i++) {1610VK_FROM_HANDLE(panvk_event, event, pEvents[i]);1611panvk_add_wait_event_operation(cmdbuf, event);1612}1613}16141615void1616panvk_CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask)1617{1618panvk_stub();1619}162016211622