(drivers_shader) Move static functions to top of files
This commit is contained in:
parent
80581f14a8
commit
808c00db41
|
@ -28,6 +28,45 @@
|
|||
#include "glslang_util.h"
|
||||
#include "../../verbosity.h"
|
||||
|
||||
static const char *glslang_formats[] = {
|
||||
"UNKNOWN",
|
||||
|
||||
"R8_UNORM",
|
||||
"R8_UINT",
|
||||
"R8_SINT",
|
||||
"R8G8_UNORM",
|
||||
"R8G8_UINT",
|
||||
"R8G8_SINT",
|
||||
"R8G8B8A8_UNORM",
|
||||
"R8G8B8A8_UINT",
|
||||
"R8G8B8A8_SINT",
|
||||
"R8G8B8A8_SRGB",
|
||||
|
||||
"A2B10G10R10_UNORM_PACK32",
|
||||
"A2B10G10R10_UINT_PACK32",
|
||||
|
||||
"R16_UINT",
|
||||
"R16_SINT",
|
||||
"R16_SFLOAT",
|
||||
"R16G16_UINT",
|
||||
"R16G16_SINT",
|
||||
"R16G16_SFLOAT",
|
||||
"R16G16B16A16_UINT",
|
||||
"R16G16B16A16_SINT",
|
||||
"R16G16B16A16_SFLOAT",
|
||||
|
||||
"R32_UINT",
|
||||
"R32_SINT",
|
||||
"R32_SFLOAT",
|
||||
"R32G32_UINT",
|
||||
"R32G32_SINT",
|
||||
"R32G32_SFLOAT",
|
||||
"R32G32B32A32_UINT",
|
||||
"R32G32B32A32_SINT",
|
||||
"R32G32B32A32_SFLOAT",
|
||||
};
|
||||
|
||||
|
||||
static void get_include_file(
|
||||
const char *line, char *include_file, size_t len)
|
||||
{
|
||||
|
@ -249,44 +288,6 @@ error:
|
|||
return false;
|
||||
}
|
||||
|
||||
static const char *glslang_formats[] = {
|
||||
"UNKNOWN",
|
||||
|
||||
"R8_UNORM",
|
||||
"R8_UINT",
|
||||
"R8_SINT",
|
||||
"R8G8_UNORM",
|
||||
"R8G8_UINT",
|
||||
"R8G8_SINT",
|
||||
"R8G8B8A8_UNORM",
|
||||
"R8G8B8A8_UINT",
|
||||
"R8G8B8A8_SINT",
|
||||
"R8G8B8A8_SRGB",
|
||||
|
||||
"A2B10G10R10_UNORM_PACK32",
|
||||
"A2B10G10R10_UINT_PACK32",
|
||||
|
||||
"R16_UINT",
|
||||
"R16_SINT",
|
||||
"R16_SFLOAT",
|
||||
"R16G16_UINT",
|
||||
"R16G16_SINT",
|
||||
"R16G16_SFLOAT",
|
||||
"R16G16B16A16_UINT",
|
||||
"R16G16B16A16_SINT",
|
||||
"R16G16B16A16_SFLOAT",
|
||||
|
||||
"R32_UINT",
|
||||
"R32_SINT",
|
||||
"R32_SFLOAT",
|
||||
"R32G32_UINT",
|
||||
"R32G32_SINT",
|
||||
"R32G32_SFLOAT",
|
||||
"R32G32B32A32_UINT",
|
||||
"R32G32B32A32_SINT",
|
||||
"R32G32B32A32_SFLOAT",
|
||||
};
|
||||
|
||||
const char *glslang_format_to_string(enum glslang_format fmt)
|
||||
{
|
||||
return glslang_formats[fmt];
|
||||
|
|
|
@ -1591,6 +1591,11 @@ static struct video_shader *gl_glsl_get_current_shader(void *data)
|
|||
return glsl->shader;
|
||||
}
|
||||
|
||||
static void gl_glsl_get_flags(uint32_t *flags)
|
||||
{
|
||||
BIT32_SET(*flags, GFX_CTX_FLAGS_SHADERS_GLSL);
|
||||
}
|
||||
|
||||
void gl_glsl_set_get_proc_address(gfx_ctx_proc_t (*proc)(const char*))
|
||||
{
|
||||
glsl_get_proc_address = proc;
|
||||
|
@ -1604,10 +1609,6 @@ void gl_glsl_set_context_type(bool core_profile,
|
|||
glsl_minor = minor;
|
||||
}
|
||||
|
||||
static void gl_glsl_get_flags(uint32_t *flags)
|
||||
{
|
||||
BIT32_SET(*flags, GFX_CTX_FLAGS_SHADERS_GLSL);
|
||||
}
|
||||
|
||||
const shader_backend_t gl_glsl_backend = {
|
||||
gl_glsl_init,
|
||||
|
|
|
@ -45,77 +45,6 @@ static const uint32_t opaque_frag[] =
|
|||
#include "../drivers/vulkan_shaders/opaque.frag.inc"
|
||||
;
|
||||
|
||||
template <typename P>
|
||||
static bool vk_shader_set_unique_map(unordered_map<string, P> &m,
|
||||
const string &name, const P &p)
|
||||
{
|
||||
auto itr = m.find(name);
|
||||
if (itr != end(m))
|
||||
{
|
||||
RARCH_ERR("[slang]: Alias \"%s\" already exists.\n",
|
||||
name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
m[name] = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned num_miplevels(unsigned width, unsigned height)
|
||||
{
|
||||
unsigned size = MAX(width, height);
|
||||
unsigned levels = 0;
|
||||
while (size)
|
||||
{
|
||||
levels++;
|
||||
size >>= 1;
|
||||
}
|
||||
return levels;
|
||||
}
|
||||
|
||||
static uint32_t find_memory_type_fallback(
|
||||
const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
uint32_t device_reqs, uint32_t host_reqs)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < VK_MAX_MEMORY_TYPES; i++)
|
||||
{
|
||||
if ((device_reqs & (1u << i)) &&
|
||||
(mem_props.memoryTypes[i].propertyFlags & host_reqs) == host_reqs)
|
||||
return i;
|
||||
}
|
||||
|
||||
return vulkan_find_memory_type(&mem_props, device_reqs, 0);
|
||||
}
|
||||
|
||||
static void build_identity_matrix(float *data)
|
||||
{
|
||||
data[ 0] = 1.0f;
|
||||
data[ 1] = 0.0f;
|
||||
data[ 2] = 0.0f;
|
||||
data[ 3] = 0.0f;
|
||||
data[ 4] = 0.0f;
|
||||
data[ 5] = 1.0f;
|
||||
data[ 6] = 0.0f;
|
||||
data[ 7] = 0.0f;
|
||||
data[ 8] = 0.0f;
|
||||
data[ 9] = 0.0f;
|
||||
data[10] = 1.0f;
|
||||
data[11] = 0.0f;
|
||||
data[12] = 0.0f;
|
||||
data[13] = 0.0f;
|
||||
data[14] = 0.0f;
|
||||
data[15] = 1.0f;
|
||||
}
|
||||
|
||||
static void build_vec4(float *data, unsigned width, unsigned height)
|
||||
{
|
||||
data[0] = float(width);
|
||||
data[1] = float(height);
|
||||
data[2] = 1.0f / float(width);
|
||||
data[3] = 1.0f / float(height);
|
||||
}
|
||||
|
||||
struct Texture
|
||||
{
|
||||
vulkan_filter_chain_texture texture;
|
||||
|
@ -502,6 +431,351 @@ struct vulkan_filter_chain
|
|||
void update_history_info();
|
||||
};
|
||||
|
||||
template <typename P>
|
||||
static bool vk_shader_set_unique_map(unordered_map<string, P> &m,
|
||||
const string &name, const P &p)
|
||||
{
|
||||
auto itr = m.find(name);
|
||||
if (itr != end(m))
|
||||
{
|
||||
RARCH_ERR("[slang]: Alias \"%s\" already exists.\n",
|
||||
name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
m[name] = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned num_miplevels(unsigned width, unsigned height)
|
||||
{
|
||||
unsigned size = MAX(width, height);
|
||||
unsigned levels = 0;
|
||||
while (size)
|
||||
{
|
||||
levels++;
|
||||
size >>= 1;
|
||||
}
|
||||
return levels;
|
||||
}
|
||||
|
||||
static uint32_t find_memory_type_fallback(
|
||||
const VkPhysicalDeviceMemoryProperties &mem_props,
|
||||
uint32_t device_reqs, uint32_t host_reqs)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < VK_MAX_MEMORY_TYPES; i++)
|
||||
{
|
||||
if ((device_reqs & (1u << i)) &&
|
||||
(mem_props.memoryTypes[i].propertyFlags & host_reqs) == host_reqs)
|
||||
return i;
|
||||
}
|
||||
|
||||
return vulkan_find_memory_type(&mem_props, device_reqs, 0);
|
||||
}
|
||||
|
||||
static void build_identity_matrix(float *data)
|
||||
{
|
||||
data[ 0] = 1.0f;
|
||||
data[ 1] = 0.0f;
|
||||
data[ 2] = 0.0f;
|
||||
data[ 3] = 0.0f;
|
||||
data[ 4] = 0.0f;
|
||||
data[ 5] = 1.0f;
|
||||
data[ 6] = 0.0f;
|
||||
data[ 7] = 0.0f;
|
||||
data[ 8] = 0.0f;
|
||||
data[ 9] = 0.0f;
|
||||
data[10] = 1.0f;
|
||||
data[11] = 0.0f;
|
||||
data[12] = 0.0f;
|
||||
data[13] = 0.0f;
|
||||
data[14] = 0.0f;
|
||||
data[15] = 1.0f;
|
||||
}
|
||||
|
||||
static void build_vec4(float *data, unsigned width, unsigned height)
|
||||
{
|
||||
data[0] = float(width);
|
||||
data[1] = float(height);
|
||||
data[2] = 1.0f / float(width);
|
||||
data[3] = 1.0f / float(height);
|
||||
}
|
||||
|
||||
static VkFormat glslang_format_to_vk(glslang_format fmt)
|
||||
{
|
||||
#undef FMT
|
||||
#define FMT(x) case SLANG_FORMAT_##x: return VK_FORMAT_##x
|
||||
switch (fmt)
|
||||
{
|
||||
FMT(R8_UNORM);
|
||||
FMT(R8_SINT);
|
||||
FMT(R8_UINT);
|
||||
FMT(R8G8_UNORM);
|
||||
FMT(R8G8_SINT);
|
||||
FMT(R8G8_UINT);
|
||||
FMT(R8G8B8A8_UNORM);
|
||||
FMT(R8G8B8A8_SINT);
|
||||
FMT(R8G8B8A8_UINT);
|
||||
FMT(R8G8B8A8_SRGB);
|
||||
|
||||
FMT(A2B10G10R10_UNORM_PACK32);
|
||||
FMT(A2B10G10R10_UINT_PACK32);
|
||||
|
||||
FMT(R16_UINT);
|
||||
FMT(R16_SINT);
|
||||
FMT(R16_SFLOAT);
|
||||
FMT(R16G16_UINT);
|
||||
FMT(R16G16_SINT);
|
||||
FMT(R16G16_SFLOAT);
|
||||
FMT(R16G16B16A16_UINT);
|
||||
FMT(R16G16B16A16_SINT);
|
||||
FMT(R16G16B16A16_SFLOAT);
|
||||
|
||||
FMT(R32_UINT);
|
||||
FMT(R32_SINT);
|
||||
FMT(R32_SFLOAT);
|
||||
FMT(R32G32_UINT);
|
||||
FMT(R32G32_SINT);
|
||||
FMT(R32G32_SFLOAT);
|
||||
FMT(R32G32B32A32_UINT);
|
||||
FMT(R32G32B32A32_SINT);
|
||||
FMT(R32G32B32A32_SFLOAT);
|
||||
|
||||
default:
|
||||
return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(
|
||||
VkCommandBuffer cmd,
|
||||
const struct vulkan_filter_chain_create_info *info,
|
||||
vulkan_filter_chain *chain,
|
||||
const video_shader_lut *shader)
|
||||
{
|
||||
unsigned i;
|
||||
texture_image image;
|
||||
unique_ptr<Buffer> buffer;
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkImageCreateInfo image_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
|
||||
VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
||||
VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
|
||||
VkImage tex = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
VkBufferImageCopy region = {};
|
||||
void *ptr = nullptr;
|
||||
|
||||
image.width = 0;
|
||||
image.height = 0;
|
||||
image.pixels = NULL;
|
||||
image.supports_rgba = video_driver_supports_rgba();
|
||||
|
||||
if (!image_texture_load(&image, shader->path))
|
||||
return {};
|
||||
|
||||
image_info.imageType = VK_IMAGE_TYPE_2D;
|
||||
image_info.format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
image_info.extent.width = image.width;
|
||||
image_info.extent.height = image.height;
|
||||
image_info.extent.depth = 1;
|
||||
image_info.mipLevels = shader->mipmap
|
||||
? num_miplevels(image.width, image.height) : 1;
|
||||
image_info.arrayLayers = 1;
|
||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
vkCreateImage(info->device, &image_info, nullptr, &tex);
|
||||
vkGetImageMemoryRequirements(info->device, tex, &mem_reqs);
|
||||
|
||||
alloc.allocationSize = mem_reqs.size;
|
||||
alloc.memoryTypeIndex = vulkan_find_memory_type(
|
||||
&*info->memory_properties,
|
||||
mem_reqs.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
if (vkAllocateMemory(info->device, &alloc, nullptr, &memory) != VK_SUCCESS)
|
||||
goto error;
|
||||
|
||||
vkBindImageMemory(info->device, tex, memory, 0);
|
||||
|
||||
view_info.image = tex;
|
||||
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
view_info.format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
view_info.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
view_info.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||
view_info.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
view_info.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||
view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
view_info.subresourceRange.levelCount = image_info.mipLevels;
|
||||
view_info.subresourceRange.layerCount = 1;
|
||||
vkCreateImageView(info->device, &view_info, nullptr, &view);
|
||||
|
||||
buffer =
|
||||
unique_ptr<Buffer>(new Buffer(info->device, *info->memory_properties,
|
||||
image.width * image.height * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT));
|
||||
ptr = buffer->map();
|
||||
memcpy(ptr, image.pixels, image.width * image.height * sizeof(uint32_t));
|
||||
buffer->unmap();
|
||||
|
||||
vulkan_image_layout_transition_levels(cmd, tex,
|
||||
VK_REMAINING_MIP_LEVELS,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
shader->mipmap ? VK_IMAGE_LAYOUT_GENERAL
|
||||
: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
0,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.mipLevel = 0;
|
||||
region.imageSubresource.baseArrayLayer = 0;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageExtent.width = image.width;
|
||||
region.imageExtent.height = image.height;
|
||||
region.imageExtent.depth = 1;
|
||||
|
||||
vkCmdCopyBufferToImage(cmd,
|
||||
buffer->get_buffer(),
|
||||
tex,
|
||||
shader->mipmap
|
||||
? VK_IMAGE_LAYOUT_GENERAL
|
||||
: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ®ion);
|
||||
|
||||
for (i = 1; i < image_info.mipLevels; i++)
|
||||
{
|
||||
VkImageBlit blit_region = {};
|
||||
unsigned src_width = MAX(image.width >> (i - 1), 1u);
|
||||
unsigned src_height = MAX(image.height >> (i - 1), 1u);
|
||||
unsigned target_width = MAX(image.width >> i, 1u);
|
||||
unsigned target_height = 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. */
|
||||
vulkan_image_layout_transition_levels(
|
||||
cmd,
|
||||
tex,
|
||||
VK_REMAINING_MIP_LEVELS,
|
||||
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);
|
||||
}
|
||||
|
||||
vulkan_image_layout_transition_levels(
|
||||
cmd,
|
||||
tex,
|
||||
VK_REMAINING_MIP_LEVELS,
|
||||
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_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
|
||||
image_texture_free(&image);
|
||||
image.pixels = nullptr;
|
||||
|
||||
return unique_ptr<StaticTexture>(new StaticTexture(shader->id, info->device,
|
||||
tex, view, memory, move(buffer), image.width, image.height,
|
||||
shader->filter != RARCH_FILTER_NEAREST,
|
||||
image_info.mipLevels > 1,
|
||||
vk_wrap_to_address(shader->wrap)));
|
||||
|
||||
error:
|
||||
if (image.pixels)
|
||||
image_texture_free(&image);
|
||||
if (tex != VK_NULL_HANDLE)
|
||||
vkDestroyImage(info->device, tex, nullptr);
|
||||
if (view != VK_NULL_HANDLE)
|
||||
vkDestroyImageView(info->device, view, nullptr);
|
||||
if (memory != VK_NULL_HANDLE)
|
||||
vkFreeMemory(info->device, memory, nullptr);
|
||||
return {};
|
||||
}
|
||||
|
||||
static bool vulkan_filter_chain_load_luts(
|
||||
const struct vulkan_filter_chain_create_info *info,
|
||||
vulkan_filter_chain *chain,
|
||||
video_shader *shader)
|
||||
{
|
||||
unsigned i;
|
||||
VkCommandBufferBeginInfo begin_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
VkSubmitInfo submit_info = {
|
||||
VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||
VkCommandBuffer cmd = VK_NULL_HANDLE;
|
||||
VkCommandBufferAllocateInfo cmd_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
|
||||
bool recording = false;
|
||||
|
||||
cmd_info.commandPool = info->command_pool;
|
||||
cmd_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
cmd_info.commandBufferCount = 1;
|
||||
|
||||
vkAllocateCommandBuffers(info->device, &cmd_info, &cmd);
|
||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
vkBeginCommandBuffer(cmd, &begin_info);
|
||||
recording = true;
|
||||
|
||||
for (i = 0; i < shader->luts; i++)
|
||||
{
|
||||
unique_ptr<StaticTexture> image =
|
||||
vulkan_filter_chain_load_lut(cmd, info, chain, &shader->lut[i]);
|
||||
if (!image)
|
||||
{
|
||||
RARCH_ERR("[Vulkan]: Failed to load LUT \"%s\".\n", shader->lut[i].path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
chain->add_static_texture(move(image));
|
||||
}
|
||||
|
||||
vkEndCommandBuffer(cmd);
|
||||
submit_info.commandBufferCount = 1;
|
||||
submit_info.pCommandBuffers = &cmd;
|
||||
vkQueueSubmit(info->queue, 1, &submit_info, VK_NULL_HANDLE);
|
||||
vkQueueWaitIdle(info->queue);
|
||||
vkFreeCommandBuffers(info->device, info->command_pool, 1, &cmd);
|
||||
chain->release_staging_buffers();
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (recording)
|
||||
vkEndCommandBuffer(cmd);
|
||||
if (cmd != VK_NULL_HANDLE)
|
||||
vkFreeCommandBuffers(info->device, info->command_pool, 1, &cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
vulkan_filter_chain::vulkan_filter_chain(
|
||||
const vulkan_filter_chain_create_info &info)
|
||||
: device(info.device),
|
||||
|
@ -1080,235 +1354,6 @@ void vulkan_filter_chain::set_pass_name(unsigned pass, const char *name)
|
|||
passes[pass]->set_name(name);
|
||||
}
|
||||
|
||||
static unique_ptr<StaticTexture> vulkan_filter_chain_load_lut(
|
||||
VkCommandBuffer cmd,
|
||||
const struct vulkan_filter_chain_create_info *info,
|
||||
vulkan_filter_chain *chain,
|
||||
const video_shader_lut *shader)
|
||||
{
|
||||
unsigned i;
|
||||
texture_image image;
|
||||
unique_ptr<Buffer> buffer;
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkImageCreateInfo image_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
|
||||
VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
|
||||
VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
|
||||
VkImage tex = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
VkBufferImageCopy region = {};
|
||||
void *ptr = nullptr;
|
||||
|
||||
image.width = 0;
|
||||
image.height = 0;
|
||||
image.pixels = NULL;
|
||||
image.supports_rgba = video_driver_supports_rgba();
|
||||
|
||||
if (!image_texture_load(&image, shader->path))
|
||||
return {};
|
||||
|
||||
image_info.imageType = VK_IMAGE_TYPE_2D;
|
||||
image_info.format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
image_info.extent.width = image.width;
|
||||
image_info.extent.height = image.height;
|
||||
image_info.extent.depth = 1;
|
||||
image_info.mipLevels = shader->mipmap
|
||||
? num_miplevels(image.width, image.height) : 1;
|
||||
image_info.arrayLayers = 1;
|
||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
vkCreateImage(info->device, &image_info, nullptr, &tex);
|
||||
vkGetImageMemoryRequirements(info->device, tex, &mem_reqs);
|
||||
|
||||
alloc.allocationSize = mem_reqs.size;
|
||||
alloc.memoryTypeIndex = vulkan_find_memory_type(
|
||||
&*info->memory_properties,
|
||||
mem_reqs.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
if (vkAllocateMemory(info->device, &alloc, nullptr, &memory) != VK_SUCCESS)
|
||||
goto error;
|
||||
|
||||
vkBindImageMemory(info->device, tex, memory, 0);
|
||||
|
||||
view_info.image = tex;
|
||||
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
view_info.format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
view_info.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
view_info.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||
view_info.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
view_info.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||
view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
view_info.subresourceRange.levelCount = image_info.mipLevels;
|
||||
view_info.subresourceRange.layerCount = 1;
|
||||
vkCreateImageView(info->device, &view_info, nullptr, &view);
|
||||
|
||||
buffer =
|
||||
unique_ptr<Buffer>(new Buffer(info->device, *info->memory_properties,
|
||||
image.width * image.height * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT));
|
||||
ptr = buffer->map();
|
||||
memcpy(ptr, image.pixels, image.width * image.height * sizeof(uint32_t));
|
||||
buffer->unmap();
|
||||
|
||||
vulkan_image_layout_transition_levels(cmd, tex,
|
||||
VK_REMAINING_MIP_LEVELS,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
shader->mipmap ? VK_IMAGE_LAYOUT_GENERAL
|
||||
: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
0,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.mipLevel = 0;
|
||||
region.imageSubresource.baseArrayLayer = 0;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageExtent.width = image.width;
|
||||
region.imageExtent.height = image.height;
|
||||
region.imageExtent.depth = 1;
|
||||
|
||||
vkCmdCopyBufferToImage(cmd,
|
||||
buffer->get_buffer(),
|
||||
tex,
|
||||
shader->mipmap
|
||||
? VK_IMAGE_LAYOUT_GENERAL
|
||||
: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ®ion);
|
||||
|
||||
for (i = 1; i < image_info.mipLevels; i++)
|
||||
{
|
||||
VkImageBlit blit_region = {};
|
||||
unsigned src_width = MAX(image.width >> (i - 1), 1u);
|
||||
unsigned src_height = MAX(image.height >> (i - 1), 1u);
|
||||
unsigned target_width = MAX(image.width >> i, 1u);
|
||||
unsigned target_height = 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. */
|
||||
vulkan_image_layout_transition_levels(
|
||||
cmd,
|
||||
tex,
|
||||
VK_REMAINING_MIP_LEVELS,
|
||||
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);
|
||||
}
|
||||
|
||||
vulkan_image_layout_transition_levels(
|
||||
cmd,
|
||||
tex,
|
||||
VK_REMAINING_MIP_LEVELS,
|
||||
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_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
|
||||
image_texture_free(&image);
|
||||
image.pixels = nullptr;
|
||||
|
||||
return unique_ptr<StaticTexture>(new StaticTexture(shader->id, info->device,
|
||||
tex, view, memory, move(buffer), image.width, image.height,
|
||||
shader->filter != RARCH_FILTER_NEAREST,
|
||||
image_info.mipLevels > 1,
|
||||
vk_wrap_to_address(shader->wrap)));
|
||||
|
||||
error:
|
||||
if (image.pixels)
|
||||
image_texture_free(&image);
|
||||
if (tex != VK_NULL_HANDLE)
|
||||
vkDestroyImage(info->device, tex, nullptr);
|
||||
if (view != VK_NULL_HANDLE)
|
||||
vkDestroyImageView(info->device, view, nullptr);
|
||||
if (memory != VK_NULL_HANDLE)
|
||||
vkFreeMemory(info->device, memory, nullptr);
|
||||
return {};
|
||||
}
|
||||
|
||||
static bool vulkan_filter_chain_load_luts(
|
||||
const struct vulkan_filter_chain_create_info *info,
|
||||
vulkan_filter_chain *chain,
|
||||
video_shader *shader)
|
||||
{
|
||||
unsigned i;
|
||||
VkCommandBufferBeginInfo begin_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
VkSubmitInfo submit_info = {
|
||||
VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||
VkCommandBuffer cmd = VK_NULL_HANDLE;
|
||||
VkCommandBufferAllocateInfo cmd_info = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
|
||||
bool recording = false;
|
||||
|
||||
cmd_info.commandPool = info->command_pool;
|
||||
cmd_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
cmd_info.commandBufferCount = 1;
|
||||
|
||||
vkAllocateCommandBuffers(info->device, &cmd_info, &cmd);
|
||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
vkBeginCommandBuffer(cmd, &begin_info);
|
||||
recording = true;
|
||||
|
||||
for (i = 0; i < shader->luts; i++)
|
||||
{
|
||||
unique_ptr<StaticTexture> image =
|
||||
vulkan_filter_chain_load_lut(cmd, info, chain, &shader->lut[i]);
|
||||
if (!image)
|
||||
{
|
||||
RARCH_ERR("[Vulkan]: Failed to load LUT \"%s\".\n", shader->lut[i].path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
chain->add_static_texture(move(image));
|
||||
}
|
||||
|
||||
vkEndCommandBuffer(cmd);
|
||||
submit_info.commandBufferCount = 1;
|
||||
submit_info.pCommandBuffers = &cmd;
|
||||
vkQueueSubmit(info->queue, 1, &submit_info, VK_NULL_HANDLE);
|
||||
vkQueueWaitIdle(info->queue);
|
||||
vkFreeCommandBuffers(info->device, info->command_pool, 1, &cmd);
|
||||
chain->release_staging_buffers();
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (recording)
|
||||
vkEndCommandBuffer(cmd);
|
||||
if (cmd != VK_NULL_HANDLE)
|
||||
vkFreeCommandBuffers(info->device, info->command_pool, 1, &cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
StaticTexture::StaticTexture(string id,
|
||||
VkDevice device,
|
||||
VkImage image,
|
||||
|
@ -2509,51 +2554,6 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_default(
|
|||
return chain.release();
|
||||
}
|
||||
|
||||
static VkFormat glslang_format_to_vk(glslang_format fmt)
|
||||
{
|
||||
#undef FMT
|
||||
#define FMT(x) case SLANG_FORMAT_##x: return VK_FORMAT_##x
|
||||
switch (fmt)
|
||||
{
|
||||
FMT(R8_UNORM);
|
||||
FMT(R8_SINT);
|
||||
FMT(R8_UINT);
|
||||
FMT(R8G8_UNORM);
|
||||
FMT(R8G8_SINT);
|
||||
FMT(R8G8_UINT);
|
||||
FMT(R8G8B8A8_UNORM);
|
||||
FMT(R8G8B8A8_SINT);
|
||||
FMT(R8G8B8A8_UINT);
|
||||
FMT(R8G8B8A8_SRGB);
|
||||
|
||||
FMT(A2B10G10R10_UNORM_PACK32);
|
||||
FMT(A2B10G10R10_UINT_PACK32);
|
||||
|
||||
FMT(R16_UINT);
|
||||
FMT(R16_SINT);
|
||||
FMT(R16_SFLOAT);
|
||||
FMT(R16G16_UINT);
|
||||
FMT(R16G16_SINT);
|
||||
FMT(R16G16_SFLOAT);
|
||||
FMT(R16G16B16A16_UINT);
|
||||
FMT(R16G16B16A16_SINT);
|
||||
FMT(R16G16B16A16_SFLOAT);
|
||||
|
||||
FMT(R32_UINT);
|
||||
FMT(R32_SINT);
|
||||
FMT(R32_SFLOAT);
|
||||
FMT(R32G32_UINT);
|
||||
FMT(R32G32_SINT);
|
||||
FMT(R32G32_SFLOAT);
|
||||
FMT(R32G32B32A32_UINT);
|
||||
FMT(R32G32B32A32_SINT);
|
||||
FMT(R32G32B32A32_SFLOAT);
|
||||
|
||||
default:
|
||||
return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset(
|
||||
const struct vulkan_filter_chain_create_info *info,
|
||||
const char *path, vulkan_filter_chain_filter filter)
|
||||
|
|
|
@ -54,17 +54,6 @@ static const char *semantic_uniform_names[] = {
|
|||
"FrameDirection",
|
||||
};
|
||||
|
||||
slang_reflection::slang_reflection()
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < SLANG_NUM_TEXTURE_SEMANTICS; i++)
|
||||
semantic_textures[i].resize(
|
||||
slang_texture_semantic_is_array(
|
||||
static_cast<slang_texture_semantic>(i))
|
||||
? 0 : 1);
|
||||
}
|
||||
|
||||
static slang_texture_semantic slang_name_to_texture_semantic(
|
||||
const unordered_map<string, slang_texture_semantic_map> &semantic_map,
|
||||
const string &name, unsigned *index)
|
||||
|
@ -354,6 +343,18 @@ static bool add_active_buffer_ranges(
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
slang_reflection::slang_reflection()
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < SLANG_NUM_TEXTURE_SEMANTICS; i++)
|
||||
semantic_textures[i].resize(
|
||||
slang_texture_semantic_is_array(
|
||||
static_cast<slang_texture_semantic>(i))
|
||||
? 0 : 1);
|
||||
}
|
||||
|
||||
bool slang_reflect(
|
||||
const Compiler &vertex_compiler,
|
||||
const Compiler &fragment_compiler,
|
||||
|
|
Loading…
Reference in New Issue