mirror of
https://github.com/CTCaer/RetroArch.git
synced 2025-01-27 14:23:06 +00:00
Vulkan: Allow configuring mip/wrap/filter for LUTs.
LUTs are feature complete with CGP now.
This commit is contained in:
parent
e846bd4955
commit
4ac9ebd579
@ -552,8 +552,13 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
VK_PIPELINE_STAGE_HOST_BIT,
|
VK_PIPELINE_STAGE_HOST_BIT,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
|
|
||||||
|
/* If doing mipmapping on upload, keep in general so we can easily do transfers to
|
||||||
|
* and transfers from the images without having to
|
||||||
|
* mess around with lots of extra transitions at per-level granularity.
|
||||||
|
*/
|
||||||
vulkan_image_layout_transition(vk, staging, tex.image,
|
vulkan_image_layout_transition(vk, staging, tex.image,
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
tex.mipmap ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
@ -568,23 +573,12 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
|
|
||||||
vkCmdCopyImage(staging,
|
vkCmdCopyImage(staging,
|
||||||
tmp.image, VK_IMAGE_LAYOUT_GENERAL,
|
tmp.image, VK_IMAGE_LAYOUT_GENERAL,
|
||||||
tex.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
tex.image,
|
||||||
|
tex.mipmap ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
1, ®ion);
|
1, ®ion);
|
||||||
|
|
||||||
if (tex.mipmap)
|
if (tex.mipmap)
|
||||||
{
|
{
|
||||||
/* Keep in general so we can easily do transfers to
|
|
||||||
* and transfers from the images without having to
|
|
||||||
* mess around with lots of extra transitions at per-level granularity.
|
|
||||||
*/
|
|
||||||
vulkan_image_layout_transition(vk, staging, tex.image,
|
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
||||||
VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
|
||||||
VK_ACCESS_TRANSFER_READ_BIT,
|
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
|
||||||
|
|
||||||
for (i = 1; i < info.mipLevels; i++)
|
for (i = 1; i < info.mipLevels; i++)
|
||||||
{
|
{
|
||||||
VkImageBlit blit_region;
|
VkImageBlit blit_region;
|
||||||
@ -607,23 +601,20 @@ struct vk_texture vulkan_create_texture(vk_t *vk,
|
|||||||
blit_region.dstOffsets[1].y = target_height;
|
blit_region.dstOffsets[1].y = target_height;
|
||||||
blit_region.dstOffsets[1].z = 1;
|
blit_region.dstOffsets[1].z = 1;
|
||||||
|
|
||||||
|
/* Only injects execution and memory barriers,
|
||||||
|
* not actual transition. */
|
||||||
|
vulkan_image_layout_transition(vk, staging, tex.image,
|
||||||
|
VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
VK_ACCESS_TRANSFER_READ_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
|
|
||||||
vkCmdBlitImage(staging,
|
vkCmdBlitImage(staging,
|
||||||
tex.image, VK_IMAGE_LAYOUT_GENERAL,
|
tex.image, VK_IMAGE_LAYOUT_GENERAL,
|
||||||
tex.image, VK_IMAGE_LAYOUT_GENERAL,
|
tex.image, VK_IMAGE_LAYOUT_GENERAL,
|
||||||
1, &blit_region, VK_FILTER_LINEAR);
|
1, &blit_region, VK_FILTER_LINEAR);
|
||||||
|
|
||||||
if (i + 1 < info.mipLevels)
|
|
||||||
{
|
|
||||||
/* Only injects execution and memory barriers,
|
|
||||||
* not actual transition. */
|
|
||||||
vulkan_image_layout_transition(vk, staging, tex.image,
|
|
||||||
VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
|
||||||
VK_ACCESS_TRANSFER_READ_BIT,
|
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Complete our texture. */
|
/* Complete our texture. */
|
||||||
|
@ -186,7 +186,10 @@ class StaticTexture
|
|||||||
VkImageView view,
|
VkImageView view,
|
||||||
VkDeviceMemory memory,
|
VkDeviceMemory memory,
|
||||||
unique_ptr<Buffer> buffer,
|
unique_ptr<Buffer> buffer,
|
||||||
unsigned width, unsigned height);
|
unsigned width, unsigned height,
|
||||||
|
bool linear,
|
||||||
|
bool mipmap,
|
||||||
|
vulkan_filter_chain_address address);
|
||||||
~StaticTexture();
|
~StaticTexture();
|
||||||
|
|
||||||
StaticTexture(StaticTexture&&) = delete;
|
StaticTexture(StaticTexture&&) = delete;
|
||||||
@ -1091,7 +1094,10 @@ StaticTexture::StaticTexture(string id,
|
|||||||
VkImageView view,
|
VkImageView view,
|
||||||
VkDeviceMemory memory,
|
VkDeviceMemory memory,
|
||||||
unique_ptr<Buffer> buffer,
|
unique_ptr<Buffer> buffer,
|
||||||
unsigned width, unsigned height)
|
unsigned width, unsigned height,
|
||||||
|
bool linear,
|
||||||
|
bool mipmap,
|
||||||
|
vulkan_filter_chain_address address)
|
||||||
: id(move(id)),
|
: id(move(id)),
|
||||||
device(device),
|
device(device),
|
||||||
image(image),
|
image(image),
|
||||||
@ -1099,9 +1105,10 @@ StaticTexture::StaticTexture(string id,
|
|||||||
memory(memory),
|
memory(memory),
|
||||||
buffer(move(buffer))
|
buffer(move(buffer))
|
||||||
{
|
{
|
||||||
texture.filter = VULKAN_FILTER_CHAIN_LINEAR;
|
texture.filter = linear ? VULKAN_FILTER_CHAIN_LINEAR : VULKAN_FILTER_CHAIN_NEAREST;
|
||||||
texture.mip_filter = VULKAN_FILTER_CHAIN_NEAREST;
|
texture.mip_filter =
|
||||||
texture.address = VULKAN_FILTER_CHAIN_ADDRESS_REPEAT;
|
mipmap && linear ? VULKAN_FILTER_CHAIN_LINEAR : VULKAN_FILTER_CHAIN_NEAREST;
|
||||||
|
texture.address = address;
|
||||||
texture.texture.image = image;
|
texture.texture.image = image;
|
||||||
texture.texture.view = view;
|
texture.texture.view = view;
|
||||||
texture.texture.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
texture.texture.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
@ -2316,6 +2323,37 @@ static VkFormat glslang_format_to_vk(glslang_format fmt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned num_miplevels(unsigned width, unsigned height)
|
||||||
|
{
|
||||||
|
unsigned size = std::max(width, height);
|
||||||
|
unsigned levels = 0;
|
||||||
|
while (size)
|
||||||
|
{
|
||||||
|
levels++;
|
||||||
|
size >>= 1;
|
||||||
|
}
|
||||||
|
return levels;
|
||||||
|
}
|
||||||
|
|
||||||
|
static vulkan_filter_chain_address wrap_to_address(gfx_wrap_type type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case RARCH_WRAP_BORDER:
|
||||||
|
return VULKAN_FILTER_CHAIN_ADDRESS_CLAMP_TO_BORDER;
|
||||||
|
|
||||||
|
case RARCH_WRAP_EDGE:
|
||||||
|
return VULKAN_FILTER_CHAIN_ADDRESS_CLAMP_TO_EDGE;
|
||||||
|
|
||||||
|
case RARCH_WRAP_REPEAT:
|
||||||
|
return VULKAN_FILTER_CHAIN_ADDRESS_REPEAT;
|
||||||
|
|
||||||
|
case RARCH_WRAP_MIRRORED_REPEAT:
|
||||||
|
return VULKAN_FILTER_CHAIN_ADDRESS_MIRRORED_REPEAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(VkCommandBuffer cmd,
|
static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(VkCommandBuffer cmd,
|
||||||
const struct vulkan_filter_chain_create_info *info,
|
const struct vulkan_filter_chain_create_info *info,
|
||||||
vulkan_filter_chain *chain,
|
vulkan_filter_chain *chain,
|
||||||
@ -2341,7 +2379,7 @@ static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(VkCommandBuffer cm
|
|||||||
image_info.extent.width = image.width;
|
image_info.extent.width = image.width;
|
||||||
image_info.extent.height = image.height;
|
image_info.extent.height = image.height;
|
||||||
image_info.extent.depth = 1;
|
image_info.extent.depth = 1;
|
||||||
image_info.mipLevels = 1;
|
image_info.mipLevels = shader->mipmap ? num_miplevels(image.width, image.height) : 1;
|
||||||
image_info.arrayLayers = 1;
|
image_info.arrayLayers = 1;
|
||||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
@ -2370,7 +2408,7 @@ static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(VkCommandBuffer cm
|
|||||||
view_info.components.b = VK_COMPONENT_SWIZZLE_B;
|
view_info.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||||
view_info.components.a = VK_COMPONENT_SWIZZLE_A;
|
view_info.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||||
view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
view_info.subresourceRange.levelCount = 1;
|
view_info.subresourceRange.levelCount = image_info.mipLevels;
|
||||||
view_info.subresourceRange.layerCount = 1;
|
view_info.subresourceRange.layerCount = 1;
|
||||||
vkCreateImageView(info->device, &view_info, nullptr, &view);
|
vkCreateImageView(info->device, &view_info, nullptr, &view);
|
||||||
|
|
||||||
@ -2381,7 +2419,8 @@ static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(VkCommandBuffer cm
|
|||||||
buffer->unmap();
|
buffer->unmap();
|
||||||
|
|
||||||
image_layout_transition(cmd, tex,
|
image_layout_transition(cmd, tex,
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
shader->mipmap ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
0, VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
|
|
||||||
@ -2393,11 +2432,50 @@ static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(VkCommandBuffer cm
|
|||||||
region.imageExtent.height = image.height;
|
region.imageExtent.height = image.height;
|
||||||
region.imageExtent.depth = 1;
|
region.imageExtent.depth = 1;
|
||||||
|
|
||||||
vkCmdCopyBufferToImage(cmd, buffer->get_buffer(), tex, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
vkCmdCopyBufferToImage(cmd, buffer->get_buffer(), tex,
|
||||||
|
shader->mipmap ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
1, ®ion);
|
1, ®ion);
|
||||||
|
|
||||||
|
for (unsigned i = 1; i < image_info.mipLevels; i++)
|
||||||
|
{
|
||||||
|
VkImageBlit blit_region = {};
|
||||||
|
unsigned src_width = std::max(image.width >> (i - 1), 1u);
|
||||||
|
unsigned src_height = std::max(image.height >> (i - 1), 1u);
|
||||||
|
unsigned target_width = std::max(image.width >> i, 1u);
|
||||||
|
unsigned target_height = std::max(image.height >> i, 1u);
|
||||||
|
|
||||||
|
blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
blit_region.srcSubresource.mipLevel = i - 1;
|
||||||
|
blit_region.srcSubresource.baseArrayLayer = 0;
|
||||||
|
blit_region.srcSubresource.layerCount = 1;
|
||||||
|
blit_region.dstSubresource = blit_region.srcSubresource;
|
||||||
|
blit_region.dstSubresource.mipLevel = i;
|
||||||
|
blit_region.srcOffsets[1].x = src_width;
|
||||||
|
blit_region.srcOffsets[1].y = src_height;
|
||||||
|
blit_region.srcOffsets[1].z = 1;
|
||||||
|
blit_region.dstOffsets[1].x = target_width;
|
||||||
|
blit_region.dstOffsets[1].y = target_height;
|
||||||
|
blit_region.dstOffsets[1].z = 1;
|
||||||
|
|
||||||
|
// Only injects execution and memory barriers,
|
||||||
|
// not actual transition.
|
||||||
|
image_layout_transition(cmd, tex,
|
||||||
|
VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
VK_ACCESS_TRANSFER_READ_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
|
|
||||||
|
vkCmdBlitImage(cmd,
|
||||||
|
tex, VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
tex, VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
1, &blit_region, VK_FILTER_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
image_layout_transition(cmd, tex,
|
image_layout_transition(cmd, tex,
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
shader->mipmap ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
|
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
|
|
||||||
@ -2405,7 +2483,10 @@ static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(VkCommandBuffer cm
|
|||||||
image.pixels = nullptr;
|
image.pixels = nullptr;
|
||||||
|
|
||||||
return unique_ptr<StaticTexture>(new StaticTexture(shader->id, info->device,
|
return unique_ptr<StaticTexture>(new StaticTexture(shader->id, info->device,
|
||||||
tex, view, memory, move(buffer), image.width, image.height));
|
tex, view, memory, move(buffer), image.width, image.height,
|
||||||
|
shader->filter != RARCH_FILTER_NEAREST,
|
||||||
|
image_info.mipLevels > 1,
|
||||||
|
wrap_to_address(shader->wrap)));
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (image.pixels)
|
if (image.pixels)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user