• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2017-2023 Hans-Kristian Arntzen
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be
12  * included in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include <assert.h>
24 #include <stdbool.h>
25 
26 #include "radv_meta.h"
27 #include "radv_private.h"
28 #include "sid.h"
29 #include "vk_common_entrypoints.h"
30 #include "vk_format.h"
31 
32 VkResult
radv_device_init_meta_astc_decode_state(struct radv_device * device,bool on_demand)33 radv_device_init_meta_astc_decode_state(struct radv_device *device, bool on_demand)
34 {
35    struct radv_meta_state *state = &device->meta_state;
36 
37    if (!device->physical_device->emulate_astc)
38       return VK_SUCCESS;
39 
40    return vk_texcompress_astc_init(&device->vk, &state->alloc, state->cache, &state->astc_decode);
41 }
42 
43 void
radv_device_finish_meta_astc_decode_state(struct radv_device * device)44 radv_device_finish_meta_astc_decode_state(struct radv_device *device)
45 {
46    struct radv_meta_state *state = &device->meta_state;
47    struct vk_texcompress_astc_state *astc = state->astc_decode;
48 
49    if (!device->physical_device->emulate_astc)
50       return;
51 
52    vk_texcompress_astc_finish(&device->vk, &state->alloc, astc);
53 }
54 
55 static void
decode_astc(struct radv_cmd_buffer * cmd_buffer,struct radv_image_view * src_iview,struct radv_image_view * dst_iview,VkImageLayout layout,const VkOffset3D * offset,const VkExtent3D * extent)56 decode_astc(struct radv_cmd_buffer *cmd_buffer, struct radv_image_view *src_iview, struct radv_image_view *dst_iview,
57             VkImageLayout layout, const VkOffset3D *offset, const VkExtent3D *extent)
58 {
59    struct radv_device *device = cmd_buffer->device;
60    struct radv_meta_state *state = &device->meta_state;
61    struct vk_texcompress_astc_write_descriptor_set write_desc_set;
62    VkFormat format = src_iview->image->vk.format;
63    int blk_w = vk_format_get_blockwidth(format);
64    int blk_h = vk_format_get_blockheight(format);
65 
66    vk_texcompress_astc_fill_write_descriptor_sets(state->astc_decode, &write_desc_set,
67                                                   radv_image_view_to_handle(src_iview), layout,
68                                                   radv_image_view_to_handle(dst_iview), format);
69    radv_meta_push_descriptor_set(cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, state->astc_decode->p_layout,
70                                  0, /* set number */
71                                  VK_TEXCOMPRESS_ASTC_WRITE_DESC_SET_COUNT, write_desc_set.descriptor_set);
72 
73    VkPipeline pipeline =
74       vk_texcompress_astc_get_decode_pipeline(&device->vk, &state->alloc, state->astc_decode, state->cache, format);
75    if (pipeline == VK_NULL_HANDLE)
76       return;
77 
78    radv_CmdBindPipeline(radv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
79 
80    bool is_3Dimage = (src_iview->image->vk.image_type == VK_IMAGE_TYPE_3D) ? true : false;
81    int push_constants[5] = {offset->x / blk_w, offset->y / blk_h, extent->width + offset->x, extent->height + offset->y,
82                             is_3Dimage};
83    vk_common_CmdPushConstants(radv_cmd_buffer_to_handle(cmd_buffer), device->meta_state.etc_decode.pipeline_layout,
84                               VK_SHADER_STAGE_COMPUTE_BIT, 0, 20, push_constants);
85 
86    struct radv_dispatch_info info = {
87       .blocks[0] = DIV_ROUND_UP(extent->width, blk_w * 2),
88       .blocks[1] = DIV_ROUND_UP(extent->height, blk_h * 2),
89       .blocks[2] = extent->depth,
90       .offsets[0] = 0,
91       .offsets[1] = 0,
92       .offsets[2] = offset->z,
93       .unaligned = 0,
94    };
95    radv_compute_dispatch(cmd_buffer, &info);
96 }
97 
98 static VkImageViewType
get_view_type(const struct radv_image * image)99 get_view_type(const struct radv_image *image)
100 {
101    switch (image->vk.image_type) {
102    case VK_IMAGE_TYPE_2D:
103       return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
104    case VK_IMAGE_TYPE_3D:
105       return VK_IMAGE_VIEW_TYPE_3D;
106    default:
107       unreachable("bad VkImageViewType");
108    }
109 }
110 
111 static void
image_view_init(struct radv_device * device,struct radv_image * image,VkFormat format,VkImageAspectFlags aspectMask,uint32_t baseMipLevel,uint32_t baseArrayLayer,uint32_t layerCount,struct radv_image_view * iview)112 image_view_init(struct radv_device *device, struct radv_image *image, VkFormat format, VkImageAspectFlags aspectMask,
113                 uint32_t baseMipLevel, uint32_t baseArrayLayer, uint32_t layerCount, struct radv_image_view *iview)
114 {
115    VkImageViewCreateInfo iview_create_info = {
116       .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
117       .image = radv_image_to_handle(image),
118       .viewType = get_view_type(image),
119       .format = format,
120       .subresourceRange =
121          {
122             .aspectMask = aspectMask,
123             .baseMipLevel = baseMipLevel,
124             .levelCount = 1,
125             .baseArrayLayer = 0,
126             .layerCount = baseArrayLayer + layerCount,
127          },
128    };
129 
130    radv_image_view_init(iview, device, &iview_create_info, 0, NULL);
131 }
132 
133 void
radv_meta_decode_astc(struct radv_cmd_buffer * cmd_buffer,struct radv_image * image,VkImageLayout layout,const VkImageSubresourceLayers * subresource,VkOffset3D offset,VkExtent3D extent)134 radv_meta_decode_astc(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image, VkImageLayout layout,
135                       const VkImageSubresourceLayers *subresource, VkOffset3D offset, VkExtent3D extent)
136 {
137    struct radv_meta_saved_state saved_state;
138    radv_meta_save(&saved_state, cmd_buffer,
139                   RADV_META_SAVE_COMPUTE_PIPELINE | RADV_META_SAVE_CONSTANTS | RADV_META_SAVE_DESCRIPTORS |
140                      RADV_META_SUSPEND_PREDICATING);
141 
142    uint32_t base_slice = radv_meta_get_iview_layer(image, subresource, &offset);
143    uint32_t slice_count = image->vk.image_type == VK_IMAGE_TYPE_3D
144                              ? extent.depth
145                              : vk_image_subresource_layer_count(&image->vk, subresource);
146 
147    extent = vk_image_sanitize_extent(&image->vk, extent);
148    offset = vk_image_sanitize_offset(&image->vk, offset);
149 
150    struct radv_image_view src_iview, dst_iview;
151    image_view_init(cmd_buffer->device, image, VK_FORMAT_R32G32B32A32_UINT, VK_IMAGE_ASPECT_COLOR_BIT,
152                    subresource->mipLevel, subresource->baseArrayLayer,
153                    vk_image_subresource_layer_count(&image->vk, subresource), &src_iview);
154    image_view_init(cmd_buffer->device, image, VK_FORMAT_R8G8B8A8_UINT, VK_IMAGE_ASPECT_PLANE_1_BIT,
155                    subresource->mipLevel, subresource->baseArrayLayer,
156                    vk_image_subresource_layer_count(&image->vk, subresource), &dst_iview);
157 
158    VkExtent3D extent_copy = {
159       .width = extent.width,
160       .height = extent.height,
161       .depth = slice_count,
162    };
163    decode_astc(cmd_buffer, &src_iview, &dst_iview, layout, &(VkOffset3D){offset.x, offset.y, base_slice}, &extent_copy);
164 
165    radv_image_view_finish(&src_iview);
166    radv_image_view_finish(&dst_iview);
167 
168    radv_meta_restore(&saved_state, cmd_buffer);
169 }
170