12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066 |
- /*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
- #include "radv_debug.h"
- #include "radv_meta.h"
- #include "radv_private.h"
- #include "nir/nir_builder.h"
-
- #include "util/format_rgb9e5.h"
- #include "vk_format.h"
-
- enum {
- DEPTH_CLEAR_SLOW,
- DEPTH_CLEAR_FAST_EXPCLEAR,
- DEPTH_CLEAR_FAST_NO_EXPCLEAR
- };
-
- static void
- build_color_shaders(struct nir_shader **out_vs,
- struct nir_shader **out_fs,
- uint32_t frag_output)
- {
- nir_builder vs_b;
- nir_builder fs_b;
-
- nir_builder_init_simple_shader(&vs_b, NULL, MESA_SHADER_VERTEX, NULL);
- nir_builder_init_simple_shader(&fs_b, NULL, MESA_SHADER_FRAGMENT, NULL);
-
- vs_b.shader->info.name = ralloc_strdup(vs_b.shader, "meta_clear_color_vs");
- fs_b.shader->info.name = ralloc_strdup(fs_b.shader, "meta_clear_color_fs");
-
- const struct glsl_type *position_type = glsl_vec4_type();
- const struct glsl_type *color_type = glsl_vec4_type();
-
- nir_variable *vs_out_pos =
- nir_variable_create(vs_b.shader, nir_var_shader_out, position_type,
- "gl_Position");
- vs_out_pos->data.location = VARYING_SLOT_POS;
-
- nir_intrinsic_instr *in_color_load = nir_intrinsic_instr_create(fs_b.shader, nir_intrinsic_load_push_constant);
- nir_intrinsic_set_base(in_color_load, 0);
- nir_intrinsic_set_range(in_color_load, 16);
- in_color_load->src[0] = nir_src_for_ssa(nir_imm_int(&fs_b, 0));
- in_color_load->num_components = 4;
- nir_ssa_dest_init(&in_color_load->instr, &in_color_load->dest, 4, 32, "clear color");
- nir_builder_instr_insert(&fs_b, &in_color_load->instr);
-
- nir_variable *fs_out_color =
- nir_variable_create(fs_b.shader, nir_var_shader_out, color_type,
- "f_color");
- fs_out_color->data.location = FRAG_RESULT_DATA0 + frag_output;
-
- nir_store_var(&fs_b, fs_out_color, &in_color_load->dest.ssa, 0xf);
-
- nir_ssa_def *outvec = radv_meta_gen_rect_vertices(&vs_b);
- nir_store_var(&vs_b, vs_out_pos, outvec, 0xf);
-
- const struct glsl_type *layer_type = glsl_int_type();
- nir_variable *vs_out_layer =
- nir_variable_create(vs_b.shader, nir_var_shader_out, layer_type,
- "v_layer");
- vs_out_layer->data.location = VARYING_SLOT_LAYER;
- vs_out_layer->data.interpolation = INTERP_MODE_FLAT;
- nir_ssa_def *inst_id = nir_load_instance_id(&vs_b);
- nir_ssa_def *base_instance = nir_load_base_instance(&vs_b);
-
- nir_ssa_def *layer_id = nir_iadd(&vs_b, inst_id, base_instance);
- nir_store_var(&vs_b, vs_out_layer, layer_id, 0x1);
-
- *out_vs = vs_b.shader;
- *out_fs = fs_b.shader;
- }
-
- static VkResult
- create_pipeline(struct radv_device *device,
- struct radv_render_pass *render_pass,
- uint32_t samples,
- struct nir_shader *vs_nir,
- struct nir_shader *fs_nir,
- const VkPipelineVertexInputStateCreateInfo *vi_state,
- const VkPipelineDepthStencilStateCreateInfo *ds_state,
- const VkPipelineColorBlendStateCreateInfo *cb_state,
- const VkPipelineLayout layout,
- const struct radv_graphics_pipeline_create_info *extra,
- const VkAllocationCallbacks *alloc,
- VkPipeline *pipeline)
- {
- VkDevice device_h = radv_device_to_handle(device);
- VkResult result;
-
- struct radv_shader_module vs_m = { .nir = vs_nir };
- struct radv_shader_module fs_m = { .nir = fs_nir };
-
- result = radv_graphics_pipeline_create(device_h,
- radv_pipeline_cache_to_handle(&device->meta_state.cache),
- &(VkGraphicsPipelineCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
- .stageCount = fs_nir ? 2 : 1,
- .pStages = (VkPipelineShaderStageCreateInfo[]) {
- {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_VERTEX_BIT,
- .module = radv_shader_module_to_handle(&vs_m),
- .pName = "main",
- },
- {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
- .module = radv_shader_module_to_handle(&fs_m),
- .pName = "main",
- },
- },
- .pVertexInputState = vi_state,
- .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
- .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
- .primitiveRestartEnable = false,
- },
- .pViewportState = &(VkPipelineViewportStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
- .viewportCount = 1,
- .scissorCount = 1,
- },
- .pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
- .rasterizerDiscardEnable = false,
- .polygonMode = VK_POLYGON_MODE_FILL,
- .cullMode = VK_CULL_MODE_NONE,
- .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
- .depthBiasEnable = false,
- },
- .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
- .rasterizationSamples = samples,
- .sampleShadingEnable = false,
- .pSampleMask = NULL,
- .alphaToCoverageEnable = false,
- .alphaToOneEnable = false,
- },
- .pDepthStencilState = ds_state,
- .pColorBlendState = cb_state,
- .pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
- /* The meta clear pipeline declares all state as dynamic.
- * As a consequence, vkCmdBindPipeline writes no dynamic state
- * to the cmd buffer. Therefore, at the end of the meta clear,
- * we need only restore dynamic state was vkCmdSet.
- */
- .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
- .dynamicStateCount = 8,
- .pDynamicStates = (VkDynamicState[]) {
- /* Everything except stencil write mask */
- VK_DYNAMIC_STATE_VIEWPORT,
- VK_DYNAMIC_STATE_SCISSOR,
- VK_DYNAMIC_STATE_LINE_WIDTH,
- VK_DYNAMIC_STATE_DEPTH_BIAS,
- VK_DYNAMIC_STATE_BLEND_CONSTANTS,
- VK_DYNAMIC_STATE_DEPTH_BOUNDS,
- VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
- VK_DYNAMIC_STATE_STENCIL_REFERENCE,
- },
- },
- .layout = layout,
- .flags = 0,
- .renderPass = radv_render_pass_to_handle(render_pass),
- .subpass = 0,
- },
- extra,
- alloc,
- pipeline);
-
- ralloc_free(vs_nir);
- ralloc_free(fs_nir);
-
- return result;
- }
-
- static VkResult
- create_color_renderpass(struct radv_device *device,
- VkFormat vk_format,
- uint32_t samples,
- VkRenderPass *pass)
- {
- mtx_lock(&device->meta_state.mtx);
- if (*pass) {
- mtx_unlock (&device->meta_state.mtx);
- return VK_SUCCESS;
- }
-
- VkResult result = radv_CreateRenderPass(radv_device_to_handle(device),
- &(VkRenderPassCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
- .attachmentCount = 1,
- .pAttachments = &(VkAttachmentDescription) {
- .format = vk_format,
- .samples = samples,
- .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
- .initialLayout = VK_IMAGE_LAYOUT_GENERAL,
- .finalLayout = VK_IMAGE_LAYOUT_GENERAL,
- },
- .subpassCount = 1,
- .pSubpasses = &(VkSubpassDescription) {
- .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
- .inputAttachmentCount = 0,
- .colorAttachmentCount = 1,
- .pColorAttachments = &(VkAttachmentReference) {
- .attachment = 0,
- .layout = VK_IMAGE_LAYOUT_GENERAL,
- },
- .pResolveAttachments = NULL,
- .pDepthStencilAttachment = &(VkAttachmentReference) {
- .attachment = VK_ATTACHMENT_UNUSED,
- .layout = VK_IMAGE_LAYOUT_GENERAL,
- },
- .preserveAttachmentCount = 0,
- .pPreserveAttachments = NULL,
- },
- .dependencyCount = 0,
- }, &device->meta_state.alloc, pass);
- mtx_unlock(&device->meta_state.mtx);
- return result;
- }
-
- static VkResult
- create_color_pipeline(struct radv_device *device,
- uint32_t samples,
- uint32_t frag_output,
- VkPipeline *pipeline,
- VkRenderPass pass)
- {
- struct nir_shader *vs_nir;
- struct nir_shader *fs_nir;
- VkResult result;
-
- mtx_lock(&device->meta_state.mtx);
- if (*pipeline) {
- mtx_unlock(&device->meta_state.mtx);
- return VK_SUCCESS;
- }
-
- build_color_shaders(&vs_nir, &fs_nir, frag_output);
-
- const VkPipelineVertexInputStateCreateInfo vi_state = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
- .vertexBindingDescriptionCount = 0,
- .vertexAttributeDescriptionCount = 0,
- };
-
- const VkPipelineDepthStencilStateCreateInfo ds_state = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
- .depthTestEnable = false,
- .depthWriteEnable = false,
- .depthBoundsTestEnable = false,
- .stencilTestEnable = false,
- };
-
- VkPipelineColorBlendAttachmentState blend_attachment_state[MAX_RTS] = { 0 };
- blend_attachment_state[frag_output] = (VkPipelineColorBlendAttachmentState) {
- .blendEnable = false,
- .colorWriteMask = VK_COLOR_COMPONENT_A_BIT |
- VK_COLOR_COMPONENT_R_BIT |
- VK_COLOR_COMPONENT_G_BIT |
- VK_COLOR_COMPONENT_B_BIT,
- };
-
- const VkPipelineColorBlendStateCreateInfo cb_state = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
- .logicOpEnable = false,
- .attachmentCount = MAX_RTS,
- .pAttachments = blend_attachment_state
- };
-
-
- struct radv_graphics_pipeline_create_info extra = {
- .use_rectlist = true,
- };
- result = create_pipeline(device, radv_render_pass_from_handle(pass),
- samples, vs_nir, fs_nir, &vi_state, &ds_state, &cb_state,
- device->meta_state.clear_color_p_layout,
- &extra, &device->meta_state.alloc, pipeline);
-
- mtx_unlock(&device->meta_state.mtx);
- return result;
- }
-
- static void
- finish_meta_clear_htile_mask_state(struct radv_device *device)
- {
- struct radv_meta_state *state = &device->meta_state;
-
- radv_DestroyPipeline(radv_device_to_handle(device),
- state->clear_htile_mask_pipeline,
- &state->alloc);
- radv_DestroyPipelineLayout(radv_device_to_handle(device),
- state->clear_htile_mask_p_layout,
- &state->alloc);
- radv_DestroyDescriptorSetLayout(radv_device_to_handle(device),
- state->clear_htile_mask_ds_layout,
- &state->alloc);
- }
-
- void
- radv_device_finish_meta_clear_state(struct radv_device *device)
- {
- struct radv_meta_state *state = &device->meta_state;
-
- for (uint32_t i = 0; i < ARRAY_SIZE(state->clear); ++i) {
- for (uint32_t j = 0; j < ARRAY_SIZE(state->clear[i].color_pipelines); ++j) {
- radv_DestroyPipeline(radv_device_to_handle(device),
- state->clear[i].color_pipelines[j],
- &state->alloc);
- radv_DestroyRenderPass(radv_device_to_handle(device),
- state->clear[i].render_pass[j],
- &state->alloc);
- }
-
- for (uint32_t j = 0; j < NUM_DEPTH_CLEAR_PIPELINES; j++) {
- radv_DestroyPipeline(radv_device_to_handle(device),
- state->clear[i].depth_only_pipeline[j],
- &state->alloc);
- radv_DestroyPipeline(radv_device_to_handle(device),
- state->clear[i].stencil_only_pipeline[j],
- &state->alloc);
- radv_DestroyPipeline(radv_device_to_handle(device),
- state->clear[i].depthstencil_pipeline[j],
- &state->alloc);
- }
- radv_DestroyRenderPass(radv_device_to_handle(device),
- state->clear[i].depthstencil_rp,
- &state->alloc);
- }
- radv_DestroyPipelineLayout(radv_device_to_handle(device),
- state->clear_color_p_layout,
- &state->alloc);
- radv_DestroyPipelineLayout(radv_device_to_handle(device),
- state->clear_depth_p_layout,
- &state->alloc);
-
- finish_meta_clear_htile_mask_state(device);
- }
-
- static void
- emit_color_clear(struct radv_cmd_buffer *cmd_buffer,
- const VkClearAttachment *clear_att,
- const VkClearRect *clear_rect,
- uint32_t view_mask)
- {
- struct radv_device *device = cmd_buffer->device;
- const struct radv_subpass *subpass = cmd_buffer->state.subpass;
- const struct radv_framebuffer *fb = cmd_buffer->state.framebuffer;
- const uint32_t subpass_att = clear_att->colorAttachment;
- const uint32_t pass_att = subpass->color_attachments[subpass_att].attachment;
- const struct radv_image_view *iview = fb ? fb->attachments[pass_att].attachment : NULL;
- uint32_t samples, samples_log2;
- VkFormat format;
- unsigned fs_key;
- VkClearColorValue clear_value = clear_att->clearValue.color;
- VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
- VkPipeline pipeline;
-
- /* When a framebuffer is bound to the current command buffer, get the
- * number of samples from it. Otherwise, get the number of samples from
- * the render pass because it's likely a secondary command buffer.
- */
- if (iview) {
- samples = iview->image->info.samples;
- format = iview->vk_format;
- } else {
- samples = cmd_buffer->state.pass->attachments[pass_att].samples;
- format = cmd_buffer->state.pass->attachments[pass_att].format;
- }
-
- samples_log2 = ffs(samples) - 1;
- fs_key = radv_format_meta_fs_key(format);
-
- if (fs_key == -1) {
- radv_finishme("color clears incomplete");
- return;
- }
-
- if (device->meta_state.clear[samples_log2].render_pass[fs_key] == VK_NULL_HANDLE) {
- VkResult ret = create_color_renderpass(device, radv_fs_key_format_exemplars[fs_key],
- samples,
- &device->meta_state.clear[samples_log2].render_pass[fs_key]);
- if (ret != VK_SUCCESS) {
- cmd_buffer->record_result = ret;
- return;
- }
- }
-
- if (device->meta_state.clear[samples_log2].color_pipelines[fs_key] == VK_NULL_HANDLE) {
- VkResult ret = create_color_pipeline(device, samples, 0,
- &device->meta_state.clear[samples_log2].color_pipelines[fs_key],
- device->meta_state.clear[samples_log2].render_pass[fs_key]);
- if (ret != VK_SUCCESS) {
- cmd_buffer->record_result = ret;
- return;
- }
- }
-
- pipeline = device->meta_state.clear[samples_log2].color_pipelines[fs_key];
- if (!pipeline) {
- radv_finishme("color clears incomplete");
- return;
- }
- assert(samples_log2 < ARRAY_SIZE(device->meta_state.clear));
- assert(pipeline);
- assert(clear_att->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
- assert(clear_att->colorAttachment < subpass->color_count);
-
- radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
- device->meta_state.clear_color_p_layout,
- VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16,
- &clear_value);
-
- struct radv_subpass clear_subpass = {
- .color_count = 1,
- .color_attachments = (struct radv_subpass_attachment[]) {
- subpass->color_attachments[clear_att->colorAttachment]
- },
- .depth_stencil_attachment = NULL,
- };
-
- radv_cmd_buffer_set_subpass(cmd_buffer, &clear_subpass);
-
- radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
- pipeline);
-
- radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) {
- .x = clear_rect->rect.offset.x,
- .y = clear_rect->rect.offset.y,
- .width = clear_rect->rect.extent.width,
- .height = clear_rect->rect.extent.height,
- .minDepth = 0.0f,
- .maxDepth = 1.0f
- });
-
- radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &clear_rect->rect);
-
- if (view_mask) {
- unsigned i;
- for_each_bit(i, view_mask)
- radv_CmdDraw(cmd_buffer_h, 3, 1, 0, i);
- } else {
- radv_CmdDraw(cmd_buffer_h, 3, clear_rect->layerCount, 0, clear_rect->baseArrayLayer);
- }
-
- radv_cmd_buffer_set_subpass(cmd_buffer, subpass);
- }
-
-
- static void
- build_depthstencil_shader(struct nir_shader **out_vs, struct nir_shader **out_fs)
- {
- nir_builder vs_b, fs_b;
-
- nir_builder_init_simple_shader(&vs_b, NULL, MESA_SHADER_VERTEX, NULL);
- nir_builder_init_simple_shader(&fs_b, NULL, MESA_SHADER_FRAGMENT, NULL);
-
- vs_b.shader->info.name = ralloc_strdup(vs_b.shader, "meta_clear_depthstencil_vs");
- fs_b.shader->info.name = ralloc_strdup(fs_b.shader, "meta_clear_depthstencil_fs");
- const struct glsl_type *position_out_type = glsl_vec4_type();
-
- nir_variable *vs_out_pos =
- nir_variable_create(vs_b.shader, nir_var_shader_out, position_out_type,
- "gl_Position");
- vs_out_pos->data.location = VARYING_SLOT_POS;
-
- nir_intrinsic_instr *in_color_load = nir_intrinsic_instr_create(vs_b.shader, nir_intrinsic_load_push_constant);
- nir_intrinsic_set_base(in_color_load, 0);
- nir_intrinsic_set_range(in_color_load, 4);
- in_color_load->src[0] = nir_src_for_ssa(nir_imm_int(&vs_b, 0));
- in_color_load->num_components = 1;
- nir_ssa_dest_init(&in_color_load->instr, &in_color_load->dest, 1, 32, "depth value");
- nir_builder_instr_insert(&vs_b, &in_color_load->instr);
-
- nir_ssa_def *outvec = radv_meta_gen_rect_vertices_comp2(&vs_b, &in_color_load->dest.ssa);
- nir_store_var(&vs_b, vs_out_pos, outvec, 0xf);
-
- const struct glsl_type *layer_type = glsl_int_type();
- nir_variable *vs_out_layer =
- nir_variable_create(vs_b.shader, nir_var_shader_out, layer_type,
- "v_layer");
- vs_out_layer->data.location = VARYING_SLOT_LAYER;
- vs_out_layer->data.interpolation = INTERP_MODE_FLAT;
- nir_ssa_def *inst_id = nir_load_instance_id(&vs_b);
- nir_ssa_def *base_instance = nir_load_base_instance(&vs_b);
-
- nir_ssa_def *layer_id = nir_iadd(&vs_b, inst_id, base_instance);
- nir_store_var(&vs_b, vs_out_layer, layer_id, 0x1);
-
- *out_vs = vs_b.shader;
- *out_fs = fs_b.shader;
- }
-
- static VkResult
- create_depthstencil_renderpass(struct radv_device *device,
- uint32_t samples,
- VkRenderPass *render_pass)
- {
- mtx_lock(&device->meta_state.mtx);
- if (*render_pass) {
- mtx_unlock(&device->meta_state.mtx);
- return VK_SUCCESS;
- }
-
- VkResult result = radv_CreateRenderPass(radv_device_to_handle(device),
- &(VkRenderPassCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
- .attachmentCount = 1,
- .pAttachments = &(VkAttachmentDescription) {
- .format = VK_FORMAT_D32_SFLOAT_S8_UINT,
- .samples = samples,
- .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
- .initialLayout = VK_IMAGE_LAYOUT_GENERAL,
- .finalLayout = VK_IMAGE_LAYOUT_GENERAL,
- },
- .subpassCount = 1,
- .pSubpasses = &(VkSubpassDescription) {
- .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
- .inputAttachmentCount = 0,
- .colorAttachmentCount = 0,
- .pColorAttachments = NULL,
- .pResolveAttachments = NULL,
- .pDepthStencilAttachment = &(VkAttachmentReference) {
- .attachment = 0,
- .layout = VK_IMAGE_LAYOUT_GENERAL,
- },
- .preserveAttachmentCount = 0,
- .pPreserveAttachments = NULL,
- },
- .dependencyCount = 0,
- }, &device->meta_state.alloc, render_pass);
- mtx_unlock(&device->meta_state.mtx);
- return result;
- }
-
- static VkResult
- create_depthstencil_pipeline(struct radv_device *device,
- VkImageAspectFlags aspects,
- uint32_t samples,
- int index,
- VkPipeline *pipeline,
- VkRenderPass render_pass)
- {
- struct nir_shader *vs_nir, *fs_nir;
- VkResult result;
-
- mtx_lock(&device->meta_state.mtx);
- if (*pipeline) {
- mtx_unlock(&device->meta_state.mtx);
- return VK_SUCCESS;
- }
-
- build_depthstencil_shader(&vs_nir, &fs_nir);
-
- const VkPipelineVertexInputStateCreateInfo vi_state = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
- .vertexBindingDescriptionCount = 0,
- .vertexAttributeDescriptionCount = 0,
- };
-
- const VkPipelineDepthStencilStateCreateInfo ds_state = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
- .depthTestEnable = (aspects & VK_IMAGE_ASPECT_DEPTH_BIT),
- .depthCompareOp = VK_COMPARE_OP_ALWAYS,
- .depthWriteEnable = (aspects & VK_IMAGE_ASPECT_DEPTH_BIT),
- .depthBoundsTestEnable = false,
- .stencilTestEnable = (aspects & VK_IMAGE_ASPECT_STENCIL_BIT),
- .front = {
- .passOp = VK_STENCIL_OP_REPLACE,
- .compareOp = VK_COMPARE_OP_ALWAYS,
- .writeMask = UINT32_MAX,
- .reference = 0, /* dynamic */
- },
- .back = { 0 /* dont care */ },
- };
-
- const VkPipelineColorBlendStateCreateInfo cb_state = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
- .logicOpEnable = false,
- .attachmentCount = 0,
- .pAttachments = NULL,
- };
-
- struct radv_graphics_pipeline_create_info extra = {
- .use_rectlist = true,
- };
-
- if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
- extra.db_depth_clear = index == DEPTH_CLEAR_SLOW ? false : true;
- extra.db_depth_disable_expclear = index == DEPTH_CLEAR_FAST_NO_EXPCLEAR ? true : false;
- }
- if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
- extra.db_stencil_clear = index == DEPTH_CLEAR_SLOW ? false : true;
- extra.db_stencil_disable_expclear = index == DEPTH_CLEAR_FAST_NO_EXPCLEAR ? true : false;
- }
- result = create_pipeline(device, radv_render_pass_from_handle(render_pass),
- samples, vs_nir, fs_nir, &vi_state, &ds_state, &cb_state,
- device->meta_state.clear_depth_p_layout,
- &extra, &device->meta_state.alloc, pipeline);
-
- mtx_unlock(&device->meta_state.mtx);
- return result;
- }
-
- static bool depth_view_can_fast_clear(struct radv_cmd_buffer *cmd_buffer,
- const struct radv_image_view *iview,
- VkImageAspectFlags aspects,
- VkImageLayout layout,
- const VkClearRect *clear_rect,
- VkClearDepthStencilValue clear_value)
- {
- if (!iview)
- return false;
-
- uint32_t queue_mask = radv_image_queue_family_mask(iview->image,
- cmd_buffer->queue_family_index,
- cmd_buffer->queue_family_index);
- if (clear_rect->rect.offset.x || clear_rect->rect.offset.y ||
- clear_rect->rect.extent.width != iview->extent.width ||
- clear_rect->rect.extent.height != iview->extent.height)
- return false;
- if (radv_image_is_tc_compat_htile(iview->image) &&
- (((aspects & VK_IMAGE_ASPECT_DEPTH_BIT) && clear_value.depth != 0.0 &&
- clear_value.depth != 1.0) ||
- ((aspects & VK_IMAGE_ASPECT_STENCIL_BIT) && clear_value.stencil != 0)))
- return false;
- if (radv_image_has_htile(iview->image) &&
- iview->base_mip == 0 &&
- iview->base_layer == 0 &&
- radv_layout_is_htile_compressed(iview->image, layout, queue_mask) &&
- !radv_image_extent_compare(iview->image, &iview->extent))
- return true;
- return false;
- }
-
- static VkPipeline
- pick_depthstencil_pipeline(struct radv_cmd_buffer *cmd_buffer,
- struct radv_meta_state *meta_state,
- const struct radv_image_view *iview,
- int samples_log2,
- VkImageAspectFlags aspects,
- VkImageLayout layout,
- const VkClearRect *clear_rect,
- VkClearDepthStencilValue clear_value)
- {
- bool fast = depth_view_can_fast_clear(cmd_buffer, iview, aspects, layout, clear_rect, clear_value);
- int index = DEPTH_CLEAR_SLOW;
- VkPipeline *pipeline;
-
- if (fast) {
- /* we don't know the previous clear values, so we always have
- * the NO_EXPCLEAR path */
- index = DEPTH_CLEAR_FAST_NO_EXPCLEAR;
- }
-
- switch (aspects) {
- case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
- pipeline = &meta_state->clear[samples_log2].depthstencil_pipeline[index];
- break;
- case VK_IMAGE_ASPECT_DEPTH_BIT:
- pipeline = &meta_state->clear[samples_log2].depth_only_pipeline[index];
- break;
- case VK_IMAGE_ASPECT_STENCIL_BIT:
- pipeline = &meta_state->clear[samples_log2].stencil_only_pipeline[index];
- break;
- default:
- unreachable("expected depth or stencil aspect");
- }
-
- if (cmd_buffer->device->meta_state.clear[samples_log2].depthstencil_rp == VK_NULL_HANDLE) {
- VkResult ret = create_depthstencil_renderpass(cmd_buffer->device, 1u << samples_log2,
- &cmd_buffer->device->meta_state.clear[samples_log2].depthstencil_rp);
- if (ret != VK_SUCCESS) {
- cmd_buffer->record_result = ret;
- return VK_NULL_HANDLE;
- }
- }
-
- if (*pipeline == VK_NULL_HANDLE) {
- VkResult ret = create_depthstencil_pipeline(cmd_buffer->device, aspects, 1u << samples_log2, index,
- pipeline, cmd_buffer->device->meta_state.clear[samples_log2].depthstencil_rp);
- if (ret != VK_SUCCESS) {
- cmd_buffer->record_result = ret;
- return VK_NULL_HANDLE;
- }
- }
- return *pipeline;
- }
-
- static void
- emit_depthstencil_clear(struct radv_cmd_buffer *cmd_buffer,
- const VkClearAttachment *clear_att,
- const VkClearRect *clear_rect,
- uint32_t view_mask)
- {
- struct radv_device *device = cmd_buffer->device;
- struct radv_meta_state *meta_state = &device->meta_state;
- const struct radv_subpass *subpass = cmd_buffer->state.subpass;
- const struct radv_framebuffer *fb = cmd_buffer->state.framebuffer;
- const uint32_t pass_att = subpass->depth_stencil_attachment->attachment;
- VkClearDepthStencilValue clear_value = clear_att->clearValue.depthStencil;
- VkImageAspectFlags aspects = clear_att->aspectMask;
- const struct radv_image_view *iview = fb ? fb->attachments[pass_att].attachment : NULL;
- uint32_t samples, samples_log2;
- VkCommandBuffer cmd_buffer_h = radv_cmd_buffer_to_handle(cmd_buffer);
-
- /* When a framebuffer is bound to the current command buffer, get the
- * number of samples from it. Otherwise, get the number of samples from
- * the render pass because it's likely a secondary command buffer.
- */
- if (iview) {
- samples = iview->image->info.samples;
- } else {
- samples = cmd_buffer->state.pass->attachments[pass_att].samples;
- }
-
- samples_log2 = ffs(samples) - 1;
-
- assert(pass_att != VK_ATTACHMENT_UNUSED);
-
- if (!(aspects & VK_IMAGE_ASPECT_DEPTH_BIT))
- clear_value.depth = 1.0f;
-
- radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
- device->meta_state.clear_depth_p_layout,
- VK_SHADER_STAGE_VERTEX_BIT, 0, 4,
- &clear_value.depth);
-
- uint32_t prev_reference = cmd_buffer->state.dynamic.stencil_reference.front;
- if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
- radv_CmdSetStencilReference(cmd_buffer_h, VK_STENCIL_FACE_FRONT_BIT,
- clear_value.stencil);
- }
-
- VkPipeline pipeline = pick_depthstencil_pipeline(cmd_buffer,
- meta_state,
- iview,
- samples_log2,
- aspects,
- subpass->depth_stencil_attachment->layout,
- clear_rect,
- clear_value);
- if (!pipeline)
- return;
-
- radv_CmdBindPipeline(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
- pipeline);
-
- if (depth_view_can_fast_clear(cmd_buffer, iview, aspects,
- subpass->depth_stencil_attachment->layout,
- clear_rect, clear_value))
- radv_update_ds_clear_metadata(cmd_buffer, iview->image,
- clear_value, aspects);
-
- radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) {
- .x = clear_rect->rect.offset.x,
- .y = clear_rect->rect.offset.y,
- .width = clear_rect->rect.extent.width,
- .height = clear_rect->rect.extent.height,
- .minDepth = 0.0f,
- .maxDepth = 1.0f
- });
-
- radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &clear_rect->rect);
-
- if (view_mask) {
- unsigned i;
- for_each_bit(i, view_mask)
- radv_CmdDraw(cmd_buffer_h, 3, 1, 0, i);
- } else {
- radv_CmdDraw(cmd_buffer_h, 3, clear_rect->layerCount, 0, clear_rect->baseArrayLayer);
- }
-
- if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
- radv_CmdSetStencilReference(cmd_buffer_h, VK_STENCIL_FACE_FRONT_BIT,
- prev_reference);
- }
- }
-
- static uint32_t
- clear_htile_mask(struct radv_cmd_buffer *cmd_buffer,
- struct radeon_winsys_bo *bo, uint64_t offset, uint64_t size,
- uint32_t htile_value, uint32_t htile_mask)
- {
- struct radv_device *device = cmd_buffer->device;
- struct radv_meta_state *state = &device->meta_state;
- uint64_t block_count = round_up_u64(size, 1024);
- struct radv_meta_saved_state saved_state;
-
- radv_meta_save(&saved_state, cmd_buffer,
- RADV_META_SAVE_COMPUTE_PIPELINE |
- RADV_META_SAVE_CONSTANTS |
- RADV_META_SAVE_DESCRIPTORS);
-
- struct radv_buffer dst_buffer = {
- .bo = bo,
- .offset = offset,
- .size = size
- };
-
- radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer),
- VK_PIPELINE_BIND_POINT_COMPUTE,
- state->clear_htile_mask_pipeline);
-
- radv_meta_push_descriptor_set(cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE,
- state->clear_htile_mask_p_layout,
- 0, /* set */
- 1, /* descriptorWriteCount */
- (VkWriteDescriptorSet[]) {
- {
- .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- .dstBinding = 0,
- .dstArrayElement = 0,
- .descriptorCount = 1,
- .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
- .pBufferInfo = &(VkDescriptorBufferInfo) {
- .buffer = radv_buffer_to_handle(&dst_buffer),
- .offset = 0,
- .range = size
- }
- }
- });
-
- const unsigned constants[2] = {
- htile_value & htile_mask,
- ~htile_mask,
- };
-
- radv_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer),
- state->clear_htile_mask_p_layout,
- VK_SHADER_STAGE_COMPUTE_BIT, 0, 8,
- constants);
-
- radv_CmdDispatch(radv_cmd_buffer_to_handle(cmd_buffer), block_count, 1, 1);
-
- radv_meta_restore(&saved_state, cmd_buffer);
-
- return RADV_CMD_FLAG_CS_PARTIAL_FLUSH |
- RADV_CMD_FLAG_INV_VMEM_L1 |
- RADV_CMD_FLAG_WRITEBACK_GLOBAL_L2;
- }
-
- static uint32_t
- radv_get_htile_fast_clear_value(const struct radv_image *image,
- VkClearDepthStencilValue value)
- {
- uint32_t clear_value;
-
- if (!image->surface.has_stencil) {
- clear_value = value.depth ? 0xfffffff0 : 0;
- } else {
- clear_value = value.depth ? 0xfffc0000 : 0;
- }
-
- return clear_value;
- }
-
- static uint32_t
- radv_get_htile_mask(const struct radv_image *image, VkImageAspectFlags aspects)
- {
- uint32_t mask = 0;
-
- if (!image->surface.has_stencil) {
- /* All the HTILE buffer is used when there is no stencil. */
- mask = UINT32_MAX;
- } else {
- if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
- mask |= 0xfffffc0f;
- if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
- mask |= 0x000003f0;
- }
-
- return mask;
- }
-
- static bool
- radv_is_fast_clear_depth_allowed(VkClearDepthStencilValue value)
- {
- return value.depth == 1.0f || value.depth == 0.0f;
- }
-
- static bool
- radv_is_fast_clear_stencil_allowed(VkClearDepthStencilValue value)
- {
- return value.stencil == 0;
- }
-
- /**
- * Determine if the given image can be fast cleared.
- */
- static bool
- radv_image_can_fast_clear(struct radv_device *device, struct radv_image *image)
- {
- if (device->instance->debug_flags & RADV_DEBUG_NO_FAST_CLEARS)
- return false;
-
- if (vk_format_is_color(image->vk_format)) {
- if (!radv_image_has_cmask(image) && !radv_image_has_dcc(image))
- return false;
-
- /* RB+ doesn't work with CMASK fast clear on Stoney. */
- if (!radv_image_has_dcc(image) &&
- device->physical_device->rad_info.family == CHIP_STONEY)
- return false;
- } else {
- if (!radv_image_has_htile(image))
- return false;
- }
-
- /* Do not fast clears 3D images. */
- if (image->type == VK_IMAGE_TYPE_3D)
- return false;
-
- return true;
- }
-
- /**
- * Determine if the given image view can be fast cleared.
- */
- static bool
- radv_image_view_can_fast_clear(struct radv_device *device,
- const struct radv_image_view *iview)
- {
- struct radv_image *image;
-
- if (!iview)
- return false;
- image = iview->image;
-
- /* Only fast clear if the image itself can be fast cleared. */
- if (!radv_image_can_fast_clear(device, image))
- return false;
-
- /* Only fast clear if all layers are bound. */
- if (iview->base_layer > 0 ||
- iview->layer_count != image->info.array_size)
- return false;
-
- /* Only fast clear if the view covers the whole image. */
- if (!radv_image_extent_compare(image, &iview->extent))
- return false;
-
- return true;
- }
-
- static bool
- radv_can_fast_clear_depth(struct radv_cmd_buffer *cmd_buffer,
- const struct radv_image_view *iview,
- VkImageLayout image_layout,
- VkImageAspectFlags aspects,
- const VkClearRect *clear_rect,
- const VkClearDepthStencilValue clear_value,
- uint32_t view_mask)
- {
- if (!radv_image_view_can_fast_clear(cmd_buffer->device, iview))
- return false;
-
- if (!radv_layout_is_htile_compressed(iview->image, image_layout, radv_image_queue_family_mask(iview->image, cmd_buffer->queue_family_index, cmd_buffer->queue_family_index)))
- return false;
-
- if (clear_rect->rect.offset.x || clear_rect->rect.offset.y ||
- clear_rect->rect.extent.width != iview->image->info.width ||
- clear_rect->rect.extent.height != iview->image->info.height)
- return false;
-
- if (view_mask && (iview->image->info.array_size >= 32 ||
- (1u << iview->image->info.array_size) - 1u != view_mask))
- return false;
- if (!view_mask && clear_rect->baseArrayLayer != 0)
- return false;
- if (!view_mask && clear_rect->layerCount != iview->image->info.array_size)
- return false;
-
- if (cmd_buffer->device->physical_device->rad_info.chip_class < GFX9 &&
- (!(aspects & VK_IMAGE_ASPECT_DEPTH_BIT) ||
- ((vk_format_aspects(iview->image->vk_format) & VK_IMAGE_ASPECT_STENCIL_BIT) &&
- !(aspects & VK_IMAGE_ASPECT_STENCIL_BIT))))
- return false;
-
- if (((aspects & VK_IMAGE_ASPECT_DEPTH_BIT) &&
- !radv_is_fast_clear_depth_allowed(clear_value)) ||
- ((aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
- !radv_is_fast_clear_stencil_allowed(clear_value)))
- return false;
-
- return true;
- }
-
- static void
- radv_fast_clear_depth(struct radv_cmd_buffer *cmd_buffer,
- const struct radv_image_view *iview,
- const VkClearAttachment *clear_att,
- enum radv_cmd_flush_bits *pre_flush,
- enum radv_cmd_flush_bits *post_flush)
- {
- VkClearDepthStencilValue clear_value = clear_att->clearValue.depthStencil;
- VkImageAspectFlags aspects = clear_att->aspectMask;
- uint32_t clear_word, flush_bits;
- uint32_t htile_mask;
-
- clear_word = radv_get_htile_fast_clear_value(iview->image, clear_value);
- htile_mask = radv_get_htile_mask(iview->image, aspects);
-
- if (pre_flush) {
- cmd_buffer->state.flush_bits |= (RADV_CMD_FLAG_FLUSH_AND_INV_DB |
- RADV_CMD_FLAG_FLUSH_AND_INV_DB_META) & ~ *pre_flush;
- *pre_flush |= cmd_buffer->state.flush_bits;
- }
-
- if (htile_mask == UINT_MAX) {
- /* Clear the whole HTILE buffer. */
- flush_bits = radv_fill_buffer(cmd_buffer, iview->image->bo,
- iview->image->offset + iview->image->htile_offset,
- iview->image->surface.htile_size, clear_word);
- } else {
- /* Only clear depth or stencil bytes in the HTILE buffer. */
- assert(cmd_buffer->device->physical_device->rad_info.chip_class >= GFX9);
- flush_bits = clear_htile_mask(cmd_buffer, iview->image->bo,
- iview->image->offset + iview->image->htile_offset,
- iview->image->surface.htile_size, clear_word,
- htile_mask);
- }
-
- radv_update_ds_clear_metadata(cmd_buffer, iview->image, clear_value, aspects);
- if (post_flush) {
- *post_flush |= flush_bits;
- }
- }
-
- static nir_shader *
- build_clear_htile_mask_shader()
- {
- nir_builder b;
-
- nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_COMPUTE, NULL);
- b.shader->info.name = ralloc_strdup(b.shader, "meta_clear_htile_mask");
- b.shader->info.cs.local_size[0] = 64;
- b.shader->info.cs.local_size[1] = 1;
- b.shader->info.cs.local_size[2] = 1;
-
- nir_ssa_def *invoc_id = nir_load_local_invocation_id(&b);
- nir_ssa_def *wg_id = nir_load_work_group_id(&b);
- nir_ssa_def *block_size = nir_imm_ivec4(&b,
- b.shader->info.cs.local_size[0],
- b.shader->info.cs.local_size[1],
- b.shader->info.cs.local_size[2], 0);
-
- nir_ssa_def *global_id = nir_iadd(&b, nir_imul(&b, wg_id, block_size), invoc_id);
-
- nir_ssa_def *offset = nir_imul(&b, global_id, nir_imm_int(&b, 16));
- offset = nir_channel(&b, offset, 0);
-
- nir_intrinsic_instr *buf =
- nir_intrinsic_instr_create(b.shader,
- nir_intrinsic_vulkan_resource_index);
-
- buf->src[0] = nir_src_for_ssa(nir_imm_int(&b, 0));
- buf->num_components = 1;
- nir_intrinsic_set_desc_set(buf, 0);
- nir_intrinsic_set_binding(buf, 0);
- nir_ssa_dest_init(&buf->instr, &buf->dest, buf->num_components, 32, NULL);
- nir_builder_instr_insert(&b, &buf->instr);
-
- nir_intrinsic_instr *constants =
- nir_intrinsic_instr_create(b.shader,
- nir_intrinsic_load_push_constant);
- nir_intrinsic_set_base(constants, 0);
- nir_intrinsic_set_range(constants, 8);
- constants->src[0] = nir_src_for_ssa(nir_imm_int(&b, 0));
- constants->num_components = 2;
- nir_ssa_dest_init(&constants->instr, &constants->dest, 2, 32, "constants");
- nir_builder_instr_insert(&b, &constants->instr);
-
- nir_intrinsic_instr *load =
- nir_intrinsic_instr_create(b.shader, nir_intrinsic_load_ssbo);
- load->src[0] = nir_src_for_ssa(&buf->dest.ssa);
- load->src[1] = nir_src_for_ssa(offset);
- nir_ssa_dest_init(&load->instr, &load->dest, 4, 32, NULL);
- load->num_components = 4;
- nir_builder_instr_insert(&b, &load->instr);
-
- /* data = (data & ~htile_mask) | (htile_value & htile_mask) */
- nir_ssa_def *data =
- nir_iand(&b, &load->dest.ssa,
- nir_channel(&b, &constants->dest.ssa, 1));
- data = nir_ior(&b, data, nir_channel(&b, &constants->dest.ssa, 0));
-
- nir_intrinsic_instr *store =
- nir_intrinsic_instr_create(b.shader, nir_intrinsic_store_ssbo);
- store->src[0] = nir_src_for_ssa(data);
- store->src[1] = nir_src_for_ssa(&buf->dest.ssa);
- store->src[2] = nir_src_for_ssa(offset);
- nir_intrinsic_set_write_mask(store, 0xf);
- store->num_components = 4;
- nir_builder_instr_insert(&b, &store->instr);
-
- return b.shader;
- }
-
- static VkResult
- init_meta_clear_htile_mask_state(struct radv_device *device)
- {
- struct radv_meta_state *state = &device->meta_state;
- struct radv_shader_module cs = { .nir = NULL };
- VkResult result;
-
- cs.nir = build_clear_htile_mask_shader();
-
- VkDescriptorSetLayoutCreateInfo ds_layout_info = {
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR,
- .bindingCount = 1,
- .pBindings = (VkDescriptorSetLayoutBinding[]) {
- {
- .binding = 0,
- .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
- .descriptorCount = 1,
- .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
- .pImmutableSamplers = NULL
- },
- }
- };
-
- result = radv_CreateDescriptorSetLayout(radv_device_to_handle(device),
- &ds_layout_info, &state->alloc,
- &state->clear_htile_mask_ds_layout);
- if (result != VK_SUCCESS)
- goto fail;
-
- VkPipelineLayoutCreateInfo p_layout_info = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- .setLayoutCount = 1,
- .pSetLayouts = &state->clear_htile_mask_ds_layout,
- .pushConstantRangeCount = 1,
- .pPushConstantRanges = &(VkPushConstantRange){
- VK_SHADER_STAGE_COMPUTE_BIT, 0, 8,
- },
- };
-
- result = radv_CreatePipelineLayout(radv_device_to_handle(device),
- &p_layout_info, &state->alloc,
- &state->clear_htile_mask_p_layout);
- if (result != VK_SUCCESS)
- goto fail;
-
- VkPipelineShaderStageCreateInfo shader_stage = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
- .stage = VK_SHADER_STAGE_COMPUTE_BIT,
- .module = radv_shader_module_to_handle(&cs),
- .pName = "main",
- .pSpecializationInfo = NULL,
- };
-
- VkComputePipelineCreateInfo pipeline_info = {
- .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
- .stage = shader_stage,
- .flags = 0,
- .layout = state->clear_htile_mask_p_layout,
- };
-
- result = radv_CreateComputePipelines(radv_device_to_handle(device),
- radv_pipeline_cache_to_handle(&state->cache),
- 1, &pipeline_info, NULL,
- &state->clear_htile_mask_pipeline);
-
- ralloc_free(cs.nir);
- return result;
- fail:
- ralloc_free(cs.nir);
- return result;
- }
-
- VkResult
- radv_device_init_meta_clear_state(struct radv_device *device, bool on_demand)
- {
- VkResult res;
- struct radv_meta_state *state = &device->meta_state;
-
- VkPipelineLayoutCreateInfo pl_color_create_info = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- .setLayoutCount = 0,
- .pushConstantRangeCount = 1,
- .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16},
- };
-
- res = radv_CreatePipelineLayout(radv_device_to_handle(device),
- &pl_color_create_info,
- &device->meta_state.alloc,
- &device->meta_state.clear_color_p_layout);
- if (res != VK_SUCCESS)
- goto fail;
-
- VkPipelineLayoutCreateInfo pl_depth_create_info = {
- .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- .setLayoutCount = 0,
- .pushConstantRangeCount = 1,
- .pPushConstantRanges = &(VkPushConstantRange){VK_SHADER_STAGE_VERTEX_BIT, 0, 4},
- };
-
- res = radv_CreatePipelineLayout(radv_device_to_handle(device),
- &pl_depth_create_info,
- &device->meta_state.alloc,
- &device->meta_state.clear_depth_p_layout);
- if (res != VK_SUCCESS)
- goto fail;
-
- res = init_meta_clear_htile_mask_state(device);
- if (res != VK_SUCCESS)
- goto fail;
-
- if (on_demand)
- return VK_SUCCESS;
-
- for (uint32_t i = 0; i < ARRAY_SIZE(state->clear); ++i) {
- uint32_t samples = 1 << i;
- for (uint32_t j = 0; j < NUM_META_FS_KEYS; ++j) {
- VkFormat format = radv_fs_key_format_exemplars[j];
- unsigned fs_key = radv_format_meta_fs_key(format);
- assert(!state->clear[i].color_pipelines[fs_key]);
-
- res = create_color_renderpass(device, format, samples,
- &state->clear[i].render_pass[fs_key]);
- if (res != VK_SUCCESS)
- goto fail;
-
- res = create_color_pipeline(device, samples, 0, &state->clear[i].color_pipelines[fs_key],
- state->clear[i].render_pass[fs_key]);
- if (res != VK_SUCCESS)
- goto fail;
-
- }
-
- res = create_depthstencil_renderpass(device,
- samples,
- &state->clear[i].depthstencil_rp);
- if (res != VK_SUCCESS)
- goto fail;
-
- for (uint32_t j = 0; j < NUM_DEPTH_CLEAR_PIPELINES; j++) {
- res = create_depthstencil_pipeline(device,
- VK_IMAGE_ASPECT_DEPTH_BIT,
- samples,
- j,
- &state->clear[i].depth_only_pipeline[j],
- state->clear[i].depthstencil_rp);
- if (res != VK_SUCCESS)
- goto fail;
-
- res = create_depthstencil_pipeline(device,
- VK_IMAGE_ASPECT_STENCIL_BIT,
- samples,
- j,
- &state->clear[i].stencil_only_pipeline[j],
- state->clear[i].depthstencil_rp);
- if (res != VK_SUCCESS)
- goto fail;
-
- res = create_depthstencil_pipeline(device,
- VK_IMAGE_ASPECT_DEPTH_BIT |
- VK_IMAGE_ASPECT_STENCIL_BIT,
- samples,
- j,
- &state->clear[i].depthstencil_pipeline[j],
- state->clear[i].depthstencil_rp);
- if (res != VK_SUCCESS)
- goto fail;
- }
- }
- return VK_SUCCESS;
-
- fail:
- radv_device_finish_meta_clear_state(device);
- return res;
- }
-
- static uint32_t
- radv_get_cmask_fast_clear_value(const struct radv_image *image)
- {
- uint32_t value = 0; /* Default value when no DCC. */
-
- /* The fast-clear value is different for images that have both DCC and
- * CMASK metadata.
- */
- if (radv_image_has_dcc(image)) {
- /* DCC fast clear with MSAA should clear CMASK to 0xC. */
- return image->info.samples > 1 ? 0xcccccccc : 0xffffffff;
- }
-
- return value;
- }
-
- uint32_t
- radv_clear_cmask(struct radv_cmd_buffer *cmd_buffer,
- struct radv_image *image, uint32_t value)
- {
- return radv_fill_buffer(cmd_buffer, image->bo,
- image->offset + image->cmask.offset,
- image->cmask.size, value);
- }
-
-
- uint32_t
- radv_clear_fmask(struct radv_cmd_buffer *cmd_buffer,
- struct radv_image *image, uint32_t value)
- {
- return radv_fill_buffer(cmd_buffer, image->bo,
- image->offset + image->fmask.offset,
- image->fmask.size, value);
- }
-
- uint32_t
- radv_clear_dcc(struct radv_cmd_buffer *cmd_buffer,
- struct radv_image *image, uint32_t value)
- {
- /* Mark the image as being compressed. */
- radv_update_dcc_metadata(cmd_buffer, image, true);
-
- return radv_fill_buffer(cmd_buffer, image->bo,
- image->offset + image->dcc_offset,
- image->surface.dcc_size, value);
- }
-
- static void vi_get_fast_clear_parameters(VkFormat format,
- const VkClearColorValue *clear_value,
- uint32_t* reset_value,
- bool *can_avoid_fast_clear_elim)
- {
- bool values[4] = {};
- int extra_channel;
- bool main_value = false;
- bool extra_value = false;
- int i;
- *can_avoid_fast_clear_elim = false;
-
- *reset_value = 0x20202020U;
-
- const struct vk_format_description *desc = vk_format_description(format);
- if (format == VK_FORMAT_B10G11R11_UFLOAT_PACK32 ||
- format == VK_FORMAT_R5G6B5_UNORM_PACK16 ||
- format == VK_FORMAT_B5G6R5_UNORM_PACK16)
- extra_channel = -1;
- else if (desc->layout == VK_FORMAT_LAYOUT_PLAIN) {
- if (radv_translate_colorswap(format, false) <= 1)
- extra_channel = desc->nr_channels - 1;
- else
- extra_channel = 0;
- } else
- return;
-
- for (i = 0; i < 4; i++) {
- int index = desc->swizzle[i] - VK_SWIZZLE_X;
- if (desc->swizzle[i] < VK_SWIZZLE_X ||
- desc->swizzle[i] > VK_SWIZZLE_W)
- continue;
-
- if (desc->channel[i].pure_integer &&
- desc->channel[i].type == VK_FORMAT_TYPE_SIGNED) {
- /* Use the maximum value for clamping the clear color. */
- int max = u_bit_consecutive(0, desc->channel[i].size - 1);
-
- values[i] = clear_value->int32[i] != 0;
- if (clear_value->int32[i] != 0 && MIN2(clear_value->int32[i], max) != max)
- return;
- } else if (desc->channel[i].pure_integer &&
- desc->channel[i].type == VK_FORMAT_TYPE_UNSIGNED) {
- /* Use the maximum value for clamping the clear color. */
- unsigned max = u_bit_consecutive(0, desc->channel[i].size);
-
- values[i] = clear_value->uint32[i] != 0U;
- if (clear_value->uint32[i] != 0U && MIN2(clear_value->uint32[i], max) != max)
- return;
- } else {
- values[i] = clear_value->float32[i] != 0.0F;
- if (clear_value->float32[i] != 0.0F && clear_value->float32[i] != 1.0F)
- return;
- }
-
- if (index == extra_channel)
- extra_value = values[i];
- else
- main_value = values[i];
- }
-
- for (int i = 0; i < 4; ++i)
- if (values[i] != main_value &&
- desc->swizzle[i] - VK_SWIZZLE_X != extra_channel &&
- desc->swizzle[i] >= VK_SWIZZLE_X &&
- desc->swizzle[i] <= VK_SWIZZLE_W)
- return;
-
- *can_avoid_fast_clear_elim = true;
- if (main_value)
- *reset_value |= 0x80808080U;
-
- if (extra_value)
- *reset_value |= 0x40404040U;
- return;
- }
-
- static bool
- radv_can_fast_clear_color(struct radv_cmd_buffer *cmd_buffer,
- const struct radv_image_view *iview,
- VkImageLayout image_layout,
- const VkClearRect *clear_rect,
- VkClearColorValue clear_value,
- uint32_t view_mask)
- {
- uint32_t clear_color[2];
-
- if (!radv_image_view_can_fast_clear(cmd_buffer->device, iview))
- return false;
-
- if (!radv_layout_can_fast_clear(iview->image, image_layout, radv_image_queue_family_mask(iview->image, cmd_buffer->queue_family_index, cmd_buffer->queue_family_index)))
- return false;
-
- if (clear_rect->rect.offset.x || clear_rect->rect.offset.y ||
- clear_rect->rect.extent.width != iview->image->info.width ||
- clear_rect->rect.extent.height != iview->image->info.height)
- return false;
-
- if (view_mask && (iview->image->info.array_size >= 32 ||
- (1u << iview->image->info.array_size) - 1u != view_mask))
- return false;
- if (!view_mask && clear_rect->baseArrayLayer != 0)
- return false;
- if (!view_mask && clear_rect->layerCount != iview->image->info.array_size)
- return false;
-
- /* DCC */
- if (!radv_format_pack_clear_color(iview->vk_format,
- clear_color, &clear_value))
- return false;
-
- if (radv_image_has_dcc(iview->image)) {
- bool can_avoid_fast_clear_elim;
- uint32_t reset_value;
-
- vi_get_fast_clear_parameters(iview->vk_format,
- &clear_value, &reset_value,
- &can_avoid_fast_clear_elim);
-
- if (iview->image->info.samples > 1) {
- /* DCC fast clear with MSAA should clear CMASK. */
- /* FIXME: This doesn't work for now. There is a
- * hardware bug with fast clears and DCC for MSAA
- * textures. AMDVLK has a workaround but it doesn't
- * seem to work here. Note that we might emit useless
- * CB flushes but that shouldn't matter.
- */
- if (!can_avoid_fast_clear_elim)
- return false;
- }
- }
-
- return true;
- }
-
-
- static void
- radv_fast_clear_color(struct radv_cmd_buffer *cmd_buffer,
- const struct radv_image_view *iview,
- const VkClearAttachment *clear_att,
- uint32_t subpass_att,
- enum radv_cmd_flush_bits *pre_flush,
- enum radv_cmd_flush_bits *post_flush)
- {
- VkClearColorValue clear_value = clear_att->clearValue.color;
- uint32_t clear_color[2], flush_bits = 0;
- uint32_t cmask_clear_value;
-
- if (pre_flush) {
- cmd_buffer->state.flush_bits |= (RADV_CMD_FLAG_FLUSH_AND_INV_CB |
- RADV_CMD_FLAG_FLUSH_AND_INV_CB_META) & ~ *pre_flush;
- *pre_flush |= cmd_buffer->state.flush_bits;
- }
-
- /* DCC */
- radv_format_pack_clear_color(iview->vk_format, clear_color, &clear_value);
-
- cmask_clear_value = radv_get_cmask_fast_clear_value(iview->image);
-
- /* clear cmask buffer */
- if (radv_image_has_dcc(iview->image)) {
- uint32_t reset_value;
- bool can_avoid_fast_clear_elim;
- bool need_decompress_pass = false;
-
- vi_get_fast_clear_parameters(iview->vk_format,
- &clear_value, &reset_value,
- &can_avoid_fast_clear_elim);
-
- if (radv_image_has_cmask(iview->image)) {
- flush_bits = radv_clear_cmask(cmd_buffer, iview->image,
- cmask_clear_value);
-
- need_decompress_pass = true;
- }
-
- if (!can_avoid_fast_clear_elim)
- need_decompress_pass = true;
-
- flush_bits |= radv_clear_dcc(cmd_buffer, iview->image, reset_value);
-
- radv_update_fce_metadata(cmd_buffer, iview->image,
- need_decompress_pass);
- } else {
- flush_bits = radv_clear_cmask(cmd_buffer, iview->image,
- cmask_clear_value);
- }
-
- if (post_flush) {
- *post_flush |= flush_bits;
- }
-
- radv_update_color_clear_metadata(cmd_buffer, iview->image, subpass_att,
- clear_color);
- }
-
- /**
- * The parameters mean that same as those in vkCmdClearAttachments.
- */
- static void
- emit_clear(struct radv_cmd_buffer *cmd_buffer,
- const VkClearAttachment *clear_att,
- const VkClearRect *clear_rect,
- enum radv_cmd_flush_bits *pre_flush,
- enum radv_cmd_flush_bits *post_flush,
- uint32_t view_mask)
- {
- const struct radv_framebuffer *fb = cmd_buffer->state.framebuffer;
- const struct radv_subpass *subpass = cmd_buffer->state.subpass;
- VkImageAspectFlags aspects = clear_att->aspectMask;
-
- if (aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
- const uint32_t subpass_att = clear_att->colorAttachment;
- assert(subpass_att < subpass->color_count);
- const uint32_t pass_att = subpass->color_attachments[subpass_att].attachment;
- if (pass_att == VK_ATTACHMENT_UNUSED)
- return;
-
- VkImageLayout image_layout = subpass->color_attachments[subpass_att].layout;
- const struct radv_image_view *iview = fb ? fb->attachments[pass_att].attachment : NULL;
- VkClearColorValue clear_value = clear_att->clearValue.color;
-
- if (radv_can_fast_clear_color(cmd_buffer, iview, image_layout,
- clear_rect, clear_value, view_mask)) {
- radv_fast_clear_color(cmd_buffer, iview, clear_att,
- subpass_att, pre_flush,
- post_flush);
- } else {
- emit_color_clear(cmd_buffer, clear_att, clear_rect, view_mask);
- }
- } else {
- const uint32_t pass_att = subpass->depth_stencil_attachment->attachment;
- if (pass_att == VK_ATTACHMENT_UNUSED)
- return;
-
- VkImageLayout image_layout = subpass->depth_stencil_attachment->layout;
- const struct radv_image_view *iview = fb ? fb->attachments[pass_att].attachment : NULL;
- VkClearDepthStencilValue clear_value = clear_att->clearValue.depthStencil;
-
- assert(aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
- VK_IMAGE_ASPECT_STENCIL_BIT));
-
- if (radv_can_fast_clear_depth(cmd_buffer, iview, image_layout,
- aspects, clear_rect, clear_value,
- view_mask)) {
- radv_fast_clear_depth(cmd_buffer, iview, clear_att,
- pre_flush, post_flush);
- } else {
- emit_depthstencil_clear(cmd_buffer, clear_att, clear_rect,
- view_mask);
- }
- }
- }
-
- static inline bool
- radv_attachment_needs_clear(struct radv_cmd_state *cmd_state, uint32_t a)
- {
- uint32_t view_mask = cmd_state->subpass->view_mask;
- return (a != VK_ATTACHMENT_UNUSED &&
- cmd_state->attachments[a].pending_clear_aspects &&
- (!view_mask || (view_mask & ~cmd_state->attachments[a].cleared_views)));
- }
-
- static bool
- radv_subpass_needs_clear(struct radv_cmd_buffer *cmd_buffer)
- {
- struct radv_cmd_state *cmd_state = &cmd_buffer->state;
- uint32_t a;
-
- if (!cmd_state->subpass)
- return false;
-
- for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
- a = cmd_state->subpass->color_attachments[i].attachment;
- if (radv_attachment_needs_clear(cmd_state, a))
- return true;
- }
-
- if (!cmd_state->subpass->depth_stencil_attachment)
- return false;
-
- a = cmd_state->subpass->depth_stencil_attachment->attachment;
- return radv_attachment_needs_clear(cmd_state, a);
- }
-
- static void
- radv_subpass_clear_attachment(struct radv_cmd_buffer *cmd_buffer,
- struct radv_attachment_state *attachment,
- const VkClearAttachment *clear_att,
- enum radv_cmd_flush_bits *pre_flush,
- enum radv_cmd_flush_bits *post_flush)
- {
- struct radv_cmd_state *cmd_state = &cmd_buffer->state;
- uint32_t view_mask = cmd_state->subpass->view_mask;
-
- VkClearRect clear_rect = {
- .rect = cmd_state->render_area,
- .baseArrayLayer = 0,
- .layerCount = cmd_state->framebuffer->layers,
- };
-
- emit_clear(cmd_buffer, clear_att, &clear_rect, pre_flush, post_flush,
- view_mask & ~attachment->cleared_views);
- if (view_mask)
- attachment->cleared_views |= view_mask;
- else
- attachment->pending_clear_aspects = 0;
- }
-
- /**
- * Emit any pending attachment clears for the current subpass.
- *
- * @see radv_attachment_state::pending_clear_aspects
- */
- void
- radv_cmd_buffer_clear_subpass(struct radv_cmd_buffer *cmd_buffer)
- {
- struct radv_cmd_state *cmd_state = &cmd_buffer->state;
- struct radv_meta_saved_state saved_state;
- enum radv_cmd_flush_bits pre_flush = 0;
- enum radv_cmd_flush_bits post_flush = 0;
-
- if (!radv_subpass_needs_clear(cmd_buffer))
- return;
-
- radv_meta_save(&saved_state, cmd_buffer,
- RADV_META_SAVE_GRAPHICS_PIPELINE |
- RADV_META_SAVE_CONSTANTS);
-
- for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
- uint32_t a = cmd_state->subpass->color_attachments[i].attachment;
-
- if (!radv_attachment_needs_clear(cmd_state, a))
- continue;
-
- assert(cmd_state->attachments[a].pending_clear_aspects ==
- VK_IMAGE_ASPECT_COLOR_BIT);
-
- VkClearAttachment clear_att = {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .colorAttachment = i, /* Use attachment index relative to subpass */
- .clearValue = cmd_state->attachments[a].clear_value,
- };
-
- radv_subpass_clear_attachment(cmd_buffer,
- &cmd_state->attachments[a],
- &clear_att, &pre_flush,
- &post_flush);
- }
-
- if (cmd_state->subpass->depth_stencil_attachment) {
- uint32_t ds = cmd_state->subpass->depth_stencil_attachment->attachment;
- if (radv_attachment_needs_clear(cmd_state, ds)) {
- VkClearAttachment clear_att = {
- .aspectMask = cmd_state->attachments[ds].pending_clear_aspects,
- .clearValue = cmd_state->attachments[ds].clear_value,
- };
-
- radv_subpass_clear_attachment(cmd_buffer,
- &cmd_state->attachments[ds],
- &clear_att, &pre_flush,
- &post_flush);
- }
- }
-
- radv_meta_restore(&saved_state, cmd_buffer);
- cmd_buffer->state.flush_bits |= post_flush;
- }
-
- static void
- radv_clear_image_layer(struct radv_cmd_buffer *cmd_buffer,
- struct radv_image *image,
- VkImageLayout image_layout,
- const VkImageSubresourceRange *range,
- VkFormat format, int level, int layer,
- const VkClearValue *clear_val)
- {
- VkDevice device_h = radv_device_to_handle(cmd_buffer->device);
- struct radv_image_view iview;
- uint32_t width = radv_minify(image->info.width, range->baseMipLevel + level);
- uint32_t height = radv_minify(image->info.height, range->baseMipLevel + level);
-
- radv_image_view_init(&iview, cmd_buffer->device,
- &(VkImageViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = radv_image_to_handle(image),
- .viewType = radv_meta_get_view_type(image),
- .format = format,
- .subresourceRange = {
- .aspectMask = range->aspectMask,
- .baseMipLevel = range->baseMipLevel + level,
- .levelCount = 1,
- .baseArrayLayer = range->baseArrayLayer + layer,
- .layerCount = 1
- },
- });
-
- VkFramebuffer fb;
- radv_CreateFramebuffer(device_h,
- &(VkFramebufferCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
- .attachmentCount = 1,
- .pAttachments = (VkImageView[]) {
- radv_image_view_to_handle(&iview),
- },
- .width = width,
- .height = height,
- .layers = 1
- },
- &cmd_buffer->pool->alloc,
- &fb);
-
- VkAttachmentDescription att_desc = {
- .format = iview.vk_format,
- .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
- .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
- .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
- .initialLayout = image_layout,
- .finalLayout = image_layout,
- };
-
- VkSubpassDescription subpass_desc = {
- .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
- .inputAttachmentCount = 0,
- .colorAttachmentCount = 0,
- .pColorAttachments = NULL,
- .pResolveAttachments = NULL,
- .pDepthStencilAttachment = NULL,
- .preserveAttachmentCount = 0,
- .pPreserveAttachments = NULL,
- };
-
- const VkAttachmentReference att_ref = {
- .attachment = 0,
- .layout = image_layout,
- };
-
- if (range->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
- subpass_desc.colorAttachmentCount = 1;
- subpass_desc.pColorAttachments = &att_ref;
- } else {
- subpass_desc.pDepthStencilAttachment = &att_ref;
- }
-
- VkRenderPass pass;
- radv_CreateRenderPass(device_h,
- &(VkRenderPassCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
- .attachmentCount = 1,
- .pAttachments = &att_desc,
- .subpassCount = 1,
- .pSubpasses = &subpass_desc,
- },
- &cmd_buffer->pool->alloc,
- &pass);
-
- radv_CmdBeginRenderPass(radv_cmd_buffer_to_handle(cmd_buffer),
- &(VkRenderPassBeginInfo) {
- .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
- .renderArea = {
- .offset = { 0, 0, },
- .extent = {
- .width = width,
- .height = height,
- },
- },
- .renderPass = pass,
- .framebuffer = fb,
- .clearValueCount = 0,
- .pClearValues = NULL,
- },
- VK_SUBPASS_CONTENTS_INLINE);
-
- VkClearAttachment clear_att = {
- .aspectMask = range->aspectMask,
- .colorAttachment = 0,
- .clearValue = *clear_val,
- };
-
- VkClearRect clear_rect = {
- .rect = {
- .offset = { 0, 0 },
- .extent = { width, height },
- },
- .baseArrayLayer = range->baseArrayLayer,
- .layerCount = 1, /* FINISHME: clear multi-layer framebuffer */
- };
-
- emit_clear(cmd_buffer, &clear_att, &clear_rect, NULL, NULL, 0);
-
- radv_CmdEndRenderPass(radv_cmd_buffer_to_handle(cmd_buffer));
- radv_DestroyRenderPass(device_h, pass,
- &cmd_buffer->pool->alloc);
- radv_DestroyFramebuffer(device_h, fb,
- &cmd_buffer->pool->alloc);
- }
-
- /**
- * Return TRUE if a fast color or depth clear has been performed.
- */
- static bool
- radv_fast_clear_range(struct radv_cmd_buffer *cmd_buffer,
- struct radv_image *image,
- VkFormat format,
- VkImageLayout image_layout,
- const VkImageSubresourceRange *range,
- const VkClearValue *clear_val)
- {
- struct radv_image_view iview;
-
- radv_image_view_init(&iview, cmd_buffer->device,
- &(VkImageViewCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = radv_image_to_handle(image),
- .viewType = radv_meta_get_view_type(image),
- .format = image->vk_format,
- .subresourceRange = {
- .aspectMask = range->aspectMask,
- .baseMipLevel = range->baseMipLevel,
- .levelCount = range->levelCount,
- .baseArrayLayer = range->baseArrayLayer,
- .layerCount = range->layerCount,
- },
- });
-
- VkClearRect clear_rect = {
- .rect = {
- .offset = { 0, 0 },
- .extent = {
- radv_minify(image->info.width, range->baseMipLevel),
- radv_minify(image->info.height, range->baseMipLevel),
- },
- },
- .baseArrayLayer = range->baseArrayLayer,
- .layerCount = range->layerCount,
- };
-
- VkClearAttachment clear_att = {
- .aspectMask = range->aspectMask,
- .colorAttachment = 0,
- .clearValue = *clear_val,
- };
-
- if (vk_format_is_color(format)) {
- if (radv_can_fast_clear_color(cmd_buffer, &iview,
- image_layout, &clear_rect,
- clear_att.clearValue.color, 0)) {
- radv_fast_clear_color(cmd_buffer, &iview, &clear_att,
- clear_att.colorAttachment,
- NULL, NULL);
- return true;
- }
- } else {
- if (radv_can_fast_clear_depth(cmd_buffer, &iview, image_layout,
- range->aspectMask, &clear_rect,
- clear_att.clearValue.depthStencil, 0)) {
- radv_fast_clear_depth(cmd_buffer, &iview, &clear_att,
- NULL, NULL);
- return true;
- }
- }
-
- return false;
- }
-
- static void
- radv_cmd_clear_image(struct radv_cmd_buffer *cmd_buffer,
- struct radv_image *image,
- VkImageLayout image_layout,
- const VkClearValue *clear_value,
- uint32_t range_count,
- const VkImageSubresourceRange *ranges,
- bool cs)
- {
- VkFormat format = image->vk_format;
- VkClearValue internal_clear_value = *clear_value;
-
- if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) {
- uint32_t value;
- format = VK_FORMAT_R32_UINT;
- value = float3_to_rgb9e5(clear_value->color.float32);
- internal_clear_value.color.uint32[0] = value;
- }
-
- if (format == VK_FORMAT_R4G4_UNORM_PACK8) {
- uint8_t r, g;
- format = VK_FORMAT_R8_UINT;
- r = float_to_ubyte(clear_value->color.float32[0]) >> 4;
- g = float_to_ubyte(clear_value->color.float32[1]) >> 4;
- internal_clear_value.color.uint32[0] = (r << 4) | (g & 0xf);
- }
-
- if (format == VK_FORMAT_R32G32B32_UINT ||
- format == VK_FORMAT_R32G32B32_SINT ||
- format == VK_FORMAT_R32G32B32_SFLOAT)
- cs = true;
-
- for (uint32_t r = 0; r < range_count; r++) {
- const VkImageSubresourceRange *range = &ranges[r];
-
- /* Try to perform a fast clear first, otherwise fallback to
- * the legacy path.
- */
- if (!cs &&
- radv_fast_clear_range(cmd_buffer, image, format,
- image_layout, range,
- &internal_clear_value)) {
- continue;
- }
-
- for (uint32_t l = 0; l < radv_get_levelCount(image, range); ++l) {
- const uint32_t layer_count = image->type == VK_IMAGE_TYPE_3D ?
- radv_minify(image->info.depth, range->baseMipLevel + l) :
- radv_get_layerCount(image, range);
- for (uint32_t s = 0; s < layer_count; ++s) {
-
- if (cs) {
- struct radv_meta_blit2d_surf surf;
- surf.format = format;
- surf.image = image;
- surf.level = range->baseMipLevel + l;
- surf.layer = range->baseArrayLayer + s;
- surf.aspect_mask = range->aspectMask;
- radv_meta_clear_image_cs(cmd_buffer, &surf,
- &internal_clear_value.color);
- } else {
- radv_clear_image_layer(cmd_buffer, image, image_layout,
- range, format, l, s, &internal_clear_value);
- }
- }
- }
- }
- }
-
- void radv_CmdClearColorImage(
- VkCommandBuffer commandBuffer,
- VkImage image_h,
- VkImageLayout imageLayout,
- const VkClearColorValue* pColor,
- uint32_t rangeCount,
- const VkImageSubresourceRange* pRanges)
- {
- RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
- RADV_FROM_HANDLE(radv_image, image, image_h);
- struct radv_meta_saved_state saved_state;
- bool cs = cmd_buffer->queue_family_index == RADV_QUEUE_COMPUTE;
-
- if (cs) {
- radv_meta_save(&saved_state, cmd_buffer,
- RADV_META_SAVE_COMPUTE_PIPELINE |
- RADV_META_SAVE_CONSTANTS |
- RADV_META_SAVE_DESCRIPTORS);
- } else {
- radv_meta_save(&saved_state, cmd_buffer,
- RADV_META_SAVE_GRAPHICS_PIPELINE |
- RADV_META_SAVE_CONSTANTS);
- }
-
- radv_cmd_clear_image(cmd_buffer, image, imageLayout,
- (const VkClearValue *) pColor,
- rangeCount, pRanges, cs);
-
- radv_meta_restore(&saved_state, cmd_buffer);
- }
-
- void radv_CmdClearDepthStencilImage(
- VkCommandBuffer commandBuffer,
- VkImage image_h,
- VkImageLayout imageLayout,
- const VkClearDepthStencilValue* pDepthStencil,
- uint32_t rangeCount,
- const VkImageSubresourceRange* pRanges)
- {
- RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
- RADV_FROM_HANDLE(radv_image, image, image_h);
- struct radv_meta_saved_state saved_state;
-
- radv_meta_save(&saved_state, cmd_buffer,
- RADV_META_SAVE_GRAPHICS_PIPELINE |
- RADV_META_SAVE_CONSTANTS);
-
- radv_cmd_clear_image(cmd_buffer, image, imageLayout,
- (const VkClearValue *) pDepthStencil,
- rangeCount, pRanges, false);
-
- radv_meta_restore(&saved_state, cmd_buffer);
- }
-
- void radv_CmdClearAttachments(
- VkCommandBuffer commandBuffer,
- uint32_t attachmentCount,
- const VkClearAttachment* pAttachments,
- uint32_t rectCount,
- const VkClearRect* pRects)
- {
- RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
- struct radv_meta_saved_state saved_state;
- enum radv_cmd_flush_bits pre_flush = 0;
- enum radv_cmd_flush_bits post_flush = 0;
-
- if (!cmd_buffer->state.subpass)
- return;
-
- radv_meta_save(&saved_state, cmd_buffer,
- RADV_META_SAVE_GRAPHICS_PIPELINE |
- RADV_META_SAVE_CONSTANTS);
-
- /* FINISHME: We can do better than this dumb loop. It thrashes too much
- * state.
- */
- for (uint32_t a = 0; a < attachmentCount; ++a) {
- for (uint32_t r = 0; r < rectCount; ++r) {
- emit_clear(cmd_buffer, &pAttachments[a], &pRects[r], &pre_flush, &post_flush,
- cmd_buffer->state.subpass->view_mask);
- }
- }
-
- radv_meta_restore(&saved_state, cmd_buffer);
- cmd_buffer->state.flush_bits |= post_flush;
- }
|