Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

Commit

Permalink
render/vulkan: Refactor image usages for modifiers
Browse files Browse the repository at this point in the history
Makes this much more extensible so we could add a storage type in future for compute.

Signed-off-by: Joshua Ashton <[email protected]>
  • Loading branch information
misyltoad committed Nov 10, 2021
1 parent 3a685b1 commit 9498632
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 130 deletions.
20 changes: 13 additions & 7 deletions include/render/vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,22 +106,28 @@ struct wlr_vk_format_modifier_props {
bool export_imported;
};

enum wlr_vk_image_usage {
WLR_VK_IMAGE_USAGE_RENDER,
WLR_VK_IMAGE_USAGE_SAMPLED,

WLR_VK_IMAGE_USAGE_COUNT,
};

VkImageUsageFlags wlr_vk_image_usage_to_vk(enum wlr_vk_image_usage usage);

struct wlr_vk_format_props {
struct wlr_vk_format format;
VkExtent2D max_extent; // relevant if not created as dma_buf
VkFormatFeatureFlags features; // relevant if not created as dma_buf

uint32_t render_mod_count;
struct wlr_vk_format_modifier_props *render_mods;

uint32_t texture_mod_count;
struct wlr_vk_format_modifier_props *texture_mods;
uint32_t mod_count[WLR_VK_IMAGE_USAGE_COUNT];
struct wlr_vk_format_modifier_props *mods[WLR_VK_IMAGE_USAGE_COUNT];
};

void vulkan_format_props_query(struct wlr_vk_device *dev,
const struct wlr_vk_format *format);
struct wlr_vk_format_modifier_props *vulkan_format_props_find_modifier(
struct wlr_vk_format_props *props, uint64_t mod, bool render);
struct wlr_vk_format_props *props, uint64_t mod, enum wlr_vk_image_usage usage);
void vulkan_format_props_finish(struct wlr_vk_format_props *props);

// For each format we want to render, we need a separate renderpass
Expand Down Expand Up @@ -260,7 +266,7 @@ struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture);
VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
const struct wlr_dmabuf_attributes *attribs,
VkDeviceMemory mems[static WLR_DMABUF_MAX_PLANES], uint32_t *n_mems,
bool for_render);
enum wlr_vk_image_usage usage);
struct wlr_texture *vulkan_texture_from_buffer(
struct wlr_renderer *wlr_renderer, struct wlr_buffer *buffer);
void vulkan_texture_destroy(struct wlr_vk_texture *texture);
Expand Down
203 changes: 87 additions & 116 deletions render/vulkan/pixel_format.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,9 @@ const struct wlr_vk_format *vulkan_get_format_from_drm(uint32_t drm_format) {
return NULL;
}

static const VkImageUsageFlags render_usage =
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
static const VkImageUsageFlags tex_usage =
VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
static const VkImageUsageFlags dma_tex_usage =
VK_IMAGE_USAGE_SAMPLED_BIT;

static const VkFormatFeatureFlags tex_features =
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
Expand All @@ -53,14 +49,31 @@ static const VkFormatFeatureFlags tex_features =
// NOTE: we don't strictly require this, we could create a NEAREST
// sampler for formats that need it, in case this ever makes problems.
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
static const VkFormatFeatureFlags render_features =
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
static const VkFormatFeatureFlags dma_tex_features =
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
// NOTE: we don't strictly require this, we could create a NEAREST
// sampler for formats that need it, in case this ever makes problems.
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;

static const VkImageUsageFlags mod_set_usage[WLR_VK_IMAGE_USAGE_COUNT] = {
[WLR_VK_IMAGE_USAGE_RENDER] = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
[WLR_VK_IMAGE_USAGE_SAMPLED] = VK_IMAGE_USAGE_SAMPLED_BIT,
};

static const VkFormatFeatureFlags mod_set_features[WLR_VK_IMAGE_USAGE_COUNT] = {
[WLR_VK_IMAGE_USAGE_RENDER] = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT,

[WLR_VK_IMAGE_USAGE_SAMPLED] = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT,
};

VkImageUsageFlags wlr_vk_image_usage_to_vk(enum wlr_vk_image_usage usage) {
return mod_set_usage[usage];
}

static const char *wlr_vk_image_usage_to_str(enum wlr_vk_image_usage usage) {
switch (usage) {
case WLR_VK_IMAGE_USAGE_RENDER: return "render";
case WLR_VK_IMAGE_USAGE_SAMPLED: return "sampled";
default: return "unknown";
}
}

static bool query_modifier_support(struct wlr_vk_device *dev,
struct wlr_vk_format_props *props, size_t modifier_count,
Expand Down Expand Up @@ -88,21 +101,17 @@ static bool query_modifier_support(struct wlr_vk_device *dev,
vkGetPhysicalDeviceFormatProperties2(dev->phdev,
props->format.vk_format, &fmtp);

props->render_mods = calloc(modp.drmFormatModifierCount,
sizeof(*props->render_mods));
if (!props->render_mods) {
wlr_log_errno(WLR_ERROR, "Allocation failed");
free(modp.pDrmFormatModifierProperties);
return false;
}

props->texture_mods = calloc(modp.drmFormatModifierCount,
sizeof(*props->texture_mods));
if (!props->texture_mods) {
wlr_log_errno(WLR_ERROR, "Allocation failed");
free(modp.pDrmFormatModifierProperties);
free(props->render_mods);
return false;
for (int i = 0; i < WLR_VK_IMAGE_USAGE_COUNT; i++) {
props->mods[i] = calloc(modp.drmFormatModifierCount,
sizeof(*props->mods[i]));
if (!props->mods[i]) {
wlr_log_errno(WLR_ERROR, "Allocation failed");
for (int j = 0; j < i; j++) {
free(props->mods[j]);
}
free(modp.pDrmFormatModifierProperties);
return false;
}
}

// detailed check
Expand Down Expand Up @@ -131,91 +140,60 @@ static bool query_modifier_support(struct wlr_vk_device *dev,

bool found = false;

struct wlr_drm_format_set *dmabuf_formats[WLR_VK_IMAGE_USAGE_COUNT] = {
[WLR_VK_IMAGE_USAGE_RENDER] = &dev->dmabuf_render_formats,
[WLR_VK_IMAGE_USAGE_SAMPLED] = &dev->dmabuf_texture_formats,
};

for (unsigned i = 0u; i < modp.drmFormatModifierCount; ++i) {
VkDrmFormatModifierPropertiesEXT m =
modp.pDrmFormatModifierProperties[i];
wlr_log(WLR_DEBUG, " modifier: 0x%"PRIx64 ": features 0x%"PRIx32", %d planes",
m.drmFormatModifier, m.drmFormatModifierTilingFeatures,
m.drmFormatModifierPlaneCount);

// check that specific modifier for render usage
if ((m.drmFormatModifierTilingFeatures & render_features) == render_features) {
fmti.usage = render_usage;

modi.drmFormatModifier = m.drmFormatModifier;
res = vkGetPhysicalDeviceImageFormatProperties2(
dev->phdev, &fmti, &ifmtp);
if (res != VK_SUCCESS) {
if (res != VK_ERROR_FORMAT_NOT_SUPPORTED) {
wlr_vk_error("vkGetPhysicalDeviceImageFormatProperties2",
res);
}

wlr_log(WLR_DEBUG, " >> rendering: format not supported");
} else if (emp->externalMemoryFeatures &
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) {
unsigned c = props->render_mod_count;
VkExtent3D me = ifmtp.imageFormatProperties.maxExtent;
VkExternalMemoryProperties emp = efmtp.externalMemoryProperties;
props->render_mods[c].props = m;
props->render_mods[c].max_extent.width = me.width;
props->render_mods[c].max_extent.height = me.height;
props->render_mods[c].dmabuf_flags = emp.externalMemoryFeatures;
props->render_mods[c].export_imported =
(emp.exportFromImportedHandleTypes &
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
++props->render_mod_count;

found = true;
wlr_drm_format_set_add(&dev->dmabuf_render_formats,
props->format.drm_format, m.drmFormatModifier);

wlr_log(WLR_DEBUG, " >> rendering: supported");
} else {
wlr_log(WLR_DEBUG, " >> rendering: importing not supported");
}
} else {
wlr_log(WLR_DEBUG, " >> rendering: format features not supported");
}

// check that specific modifier for texture usage
if ((m.drmFormatModifierTilingFeatures & dma_tex_features) == dma_tex_features) {
fmti.usage = dma_tex_usage;

modi.drmFormatModifier = m.drmFormatModifier;
res = vkGetPhysicalDeviceImageFormatProperties2(
dev->phdev, &fmti, &ifmtp);
if (res != VK_SUCCESS) {
if (res != VK_ERROR_FORMAT_NOT_SUPPORTED) {
wlr_vk_error("vkGetPhysicalDeviceImageFormatProperties2",
res);
for (int i = 0; i < WLR_VK_IMAGE_USAGE_COUNT; i++) {
// check that specific modifier for render usage
if ((m.drmFormatModifierTilingFeatures & mod_set_features[i]) == mod_set_features[i]) {
fmti.usage = mod_set_usage[i];

modi.drmFormatModifier = m.drmFormatModifier;
res = vkGetPhysicalDeviceImageFormatProperties2(
dev->phdev, &fmti, &ifmtp);
if (res != VK_SUCCESS) {
if (res != VK_ERROR_FORMAT_NOT_SUPPORTED) {
wlr_vk_error("vkGetPhysicalDeviceImageFormatProperties2",
res);
}

wlr_log(WLR_DEBUG, " >> %s: format not supported", wlr_vk_image_usage_to_str(i));
} else if (emp->externalMemoryFeatures &
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) {
unsigned c = props->mod_count[i];
VkExtent3D me = ifmtp.imageFormatProperties.maxExtent;
VkExternalMemoryProperties emp = efmtp.externalMemoryProperties;
props->mods[i][c].props = m;
props->mods[i][c].max_extent.width = me.width;
props->mods[i][c].max_extent.height = me.height;
props->mods[i][c].dmabuf_flags = emp.externalMemoryFeatures;
props->mods[i][c].export_imported =
(emp.exportFromImportedHandleTypes &
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
++props->mod_count[i];

found = true;
if (dmabuf_formats[i]) {
wlr_drm_format_set_add(dmabuf_formats[i],
props->format.drm_format, m.drmFormatModifier);
}

wlr_log(WLR_DEBUG, " >> %s: supported", wlr_vk_image_usage_to_str(i));
} else {
wlr_log(WLR_DEBUG, " >> %s: importing not supported", wlr_vk_image_usage_to_str(i));
}

wlr_log(WLR_DEBUG, " >> dmatex: format not supported");
} else if (emp->externalMemoryFeatures &
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) {
unsigned c = props->texture_mod_count;
VkExtent3D me = ifmtp.imageFormatProperties.maxExtent;
VkExternalMemoryProperties emp = efmtp.externalMemoryProperties;
props->texture_mods[c].props = m;
props->texture_mods[c].max_extent.width = me.width;
props->texture_mods[c].max_extent.height = me.height;
props->texture_mods[c].dmabuf_flags = emp.externalMemoryFeatures;
props->texture_mods[c].export_imported =
(emp.exportFromImportedHandleTypes &
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
++props->texture_mod_count;

found = true;
wlr_drm_format_set_add(&dev->dmabuf_texture_formats,
props->format.drm_format, m.drmFormatModifier);

wlr_log(WLR_DEBUG, " >> dmatex: supported");
} else {
wlr_log(WLR_DEBUG, " >> dmatex: importing not supported");
wlr_log(WLR_DEBUG, " >> %s: format features not supported", wlr_vk_image_usage_to_str(i));
}
} else {
wlr_log(WLR_DEBUG, " >> dmatex: format features not supported");
}
}

Expand Down Expand Up @@ -300,23 +278,16 @@ void vulkan_format_props_query(struct wlr_vk_device *dev,
}

void vulkan_format_props_finish(struct wlr_vk_format_props *props) {
free(props->texture_mods);
free(props->render_mods);
for (int i = 0; i < WLR_VK_IMAGE_USAGE_COUNT; i++) {
free(props->mods[i]);
}
}

struct wlr_vk_format_modifier_props *vulkan_format_props_find_modifier(
struct wlr_vk_format_props *props, uint64_t mod, bool render) {
if (render) {
for (unsigned i = 0u; i < props->render_mod_count; ++i) {
if (props->render_mods[i].props.drmFormatModifier == mod) {
return &props->render_mods[i];
}
}
} else {
for (unsigned i = 0u; i < props->texture_mod_count; ++i) {
if (props->texture_mods[i].props.drmFormatModifier == mod) {
return &props->texture_mods[i];
}
struct wlr_vk_format_props *props, uint64_t mod, enum wlr_vk_image_usage usage) {
for (unsigned i = 0u; i < props->mod_count[usage]; ++i) {
if (props->mods[usage][i].props.drmFormatModifier == mod) {
return &props->mods[usage][i];
}
}

Expand Down
2 changes: 1 addition & 1 deletion render/vulkan/renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ static struct wlr_vk_render_buffer *create_render_buffer(
}

buffer->image = vulkan_import_dmabuf(renderer, &dmabuf,
buffer->memories, &buffer->mem_count, true);
buffer->memories, &buffer->mem_count, WLR_VK_IMAGE_USAGE_RENDER);
if (!buffer->image) {
goto error_buffer;
}
Expand Down
10 changes: 4 additions & 6 deletions render/vulkan/texture.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ static bool is_dmabuf_disjoint(const struct wlr_dmabuf_attributes *attribs) {
VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
const struct wlr_dmabuf_attributes *attribs,
VkDeviceMemory mems[static WLR_DMABUF_MAX_PLANES], uint32_t *n_mems,
bool for_render) {
enum wlr_vk_image_usage usage) {
VkResult res;
VkDevice dev = renderer->dev->dev;
*n_mems = 0u;
Expand All @@ -398,7 +398,7 @@ VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
uint32_t plane_count = attribs->n_planes;
assert(plane_count < WLR_DMABUF_MAX_PLANES);
struct wlr_vk_format_modifier_props *mod =
vulkan_format_props_find_modifier(fmt, attribs->modifier, for_render);
vulkan_format_props_find_modifier(fmt, attribs->modifier, usage);
if (!mod || !(mod->dmabuf_flags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) {
wlr_log(WLR_ERROR, "Format %"PRIx32" (%.4s) can't be used with modifier "
"%"PRIx64, attribs->format, (const char*) &attribs->format,
Expand Down Expand Up @@ -440,9 +440,7 @@ VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
img_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
img_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
img_info.extent = (VkExtent3D) { attribs->width, attribs->height, 1 };
img_info.usage = for_render ?
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT :
VK_IMAGE_USAGE_SAMPLED_BIT;
img_info.usage = wlr_vk_image_usage_to_vk(usage);
if (disjoint) {
img_info.flags = VK_IMAGE_CREATE_DISJOINT_BIT;
}
Expand Down Expand Up @@ -600,7 +598,7 @@ static struct wlr_texture *vulkan_texture_from_dmabuf(struct wlr_renderer *wlr_r

texture->format = &fmt->format;
texture->image = vulkan_import_dmabuf(renderer, attribs,
texture->memories, &texture->mem_count, false);
texture->memories, &texture->mem_count, WLR_VK_IMAGE_USAGE_SAMPLED);
if (!texture->image) {
goto error;
}
Expand Down

0 comments on commit 9498632

Please sign in to comment.