1 /*
2 * Copyright © 2021 Google
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include <assert.h>
8 #include <stdbool.h>
9
10 #include "nir/nir_builder.h"
11 #include "radv_meta.h"
12 #include "sid.h"
13 #include "vk_common_entrypoints.h"
14 #include "vk_format.h"
15
16 static VkPipeline
radv_get_etc_decode_pipeline(struct radv_cmd_buffer * cmd_buffer)17 radv_get_etc_decode_pipeline(struct radv_cmd_buffer *cmd_buffer)
18 {
19 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
20 struct radv_meta_state *state = &device->meta_state;
21 VkResult ret;
22
23 ret = vk_texcompress_etc2_late_init(&device->vk, &state->etc_decode);
24 if (ret != VK_SUCCESS) {
25 vk_command_buffer_set_error(&cmd_buffer->vk, ret);
26 return VK_NULL_HANDLE;
27 }
28
29 return state->etc_decode.pipeline;
30 }
31
32 static void
decode_etc(struct radv_cmd_buffer * cmd_buffer,struct radv_image_view * src_iview,struct radv_image_view * dst_iview,const VkOffset3D * offset,const VkExtent3D * extent)33 decode_etc(struct radv_cmd_buffer *cmd_buffer, struct radv_image_view *src_iview, struct radv_image_view *dst_iview,
34 const VkOffset3D *offset, const VkExtent3D *extent)
35 {
36 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
37 VkPipeline pipeline = radv_get_etc_decode_pipeline(cmd_buffer);
38
39 radv_meta_push_descriptor_set(cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE,
40 device->meta_state.etc_decode.pipeline_layout, 0, 2,
41 (VkWriteDescriptorSet[]){{.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
42 .dstBinding = 0,
43 .dstArrayElement = 0,
44 .descriptorCount = 1,
45 .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
46 .pImageInfo =
47 (VkDescriptorImageInfo[]){
48 {.sampler = VK_NULL_HANDLE,
49 .imageView = radv_image_view_to_handle(src_iview),
50 .imageLayout = VK_IMAGE_LAYOUT_GENERAL},
51 }},
52 {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
53 .dstBinding = 1,
54 .dstArrayElement = 0,
55 .descriptorCount = 1,
56 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
57 .pImageInfo = (VkDescriptorImageInfo[]){
58 {
59 .sampler = VK_NULL_HANDLE,
60 .imageView = radv_image_view_to_handle(dst_iview),
61 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
62 },
63 }}});
64
65 radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
66
67 unsigned push_constants[5] = {
68 offset->x, offset->y, offset->z, src_iview->image->vk.format, src_iview->image->vk.image_type,
69 };
70
71 vk_common_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), device->meta_state.etc_decode.pipeline_layout,
72 VK_SHADER_STAGE_COMPUTE_BIT, 0, 20, push_constants);
73 radv_unaligned_dispatch(cmd_buffer, extent->width, extent->height, extent->depth);
74 }
75
76 void
radv_meta_decode_etc(struct radv_cmd_buffer * cmd_buffer,struct radv_image * image,VkImageLayout layout,const VkImageSubresourceLayers * subresource,VkOffset3D offset,VkExtent3D extent)77 radv_meta_decode_etc(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image, VkImageLayout layout,
78 const VkImageSubresourceLayers *subresource, VkOffset3D offset, VkExtent3D extent)
79 {
80 struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
81 struct radv_meta_saved_state saved_state;
82 radv_meta_save(&saved_state, cmd_buffer,
83 RADV_META_SAVE_COMPUTE_PIPELINE | RADV_META_SAVE_CONSTANTS | RADV_META_SAVE_DESCRIPTORS |
84 RADV_META_SUSPEND_PREDICATING);
85
86 uint32_t base_slice = radv_meta_get_iview_layer(image, subresource, &offset);
87 uint32_t slice_count = image->vk.image_type == VK_IMAGE_TYPE_3D
88 ? extent.depth
89 : vk_image_subresource_layer_count(&image->vk, subresource);
90
91 extent = vk_image_sanitize_extent(&image->vk, extent);
92 offset = vk_image_sanitize_offset(&image->vk, offset);
93
94 VkFormat load_format = vk_texcompress_etc2_load_format(image->vk.format);
95 struct radv_image_view src_iview;
96 radv_image_view_init(
97 &src_iview, device,
98 &(VkImageViewCreateInfo){
99 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
100 .image = radv_image_to_handle(image),
101 .viewType = vk_texcompress_etc2_image_view_type(image->vk.image_type),
102 .format = load_format,
103 .subresourceRange =
104 {
105 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
106 .baseMipLevel = subresource->mipLevel,
107 .levelCount = 1,
108 .baseArrayLayer = 0,
109 .layerCount = subresource->baseArrayLayer + vk_image_subresource_layer_count(&image->vk, subresource),
110 },
111 },
112 NULL);
113
114 VkFormat store_format = vk_texcompress_etc2_store_format(image->vk.format);
115 struct radv_image_view dst_iview;
116 radv_image_view_init(
117 &dst_iview, device,
118 &(VkImageViewCreateInfo){
119 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
120 .image = radv_image_to_handle(image),
121 .viewType = vk_texcompress_etc2_image_view_type(image->vk.image_type),
122 .format = store_format,
123 .subresourceRange =
124 {
125 .aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT,
126 .baseMipLevel = subresource->mipLevel,
127 .levelCount = 1,
128 .baseArrayLayer = 0,
129 .layerCount = subresource->baseArrayLayer + vk_image_subresource_layer_count(&image->vk, subresource),
130 },
131 },
132 NULL);
133
134 decode_etc(cmd_buffer, &src_iview, &dst_iview, &(VkOffset3D){offset.x, offset.y, base_slice},
135 &(VkExtent3D){extent.width, extent.height, slice_count});
136
137 radv_image_view_finish(&src_iview);
138 radv_image_view_finish(&dst_iview);
139
140 radv_meta_restore(&saved_state, cmd_buffer);
141 }
142