Mipmaps.
This commit is contained in:
parent
d110d15a06
commit
a8fc2da718
|
|
@ -733,30 +733,12 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
|
|||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
|
||||
|
||||
// VULKAN
|
||||
Vk_Image& vk_image = vk_resources.images[tr.scratchImage[client]->index];
|
||||
vkDestroyImage(vk.device, vk_image.image, nullptr);
|
||||
vkDestroyImageView(vk.device, vk_image.image_view, nullptr);
|
||||
vk_image.image = vk_create_image(cols, rows, vk_image.image_view);
|
||||
vk_upload_image_data(vk_image.image, cols, rows, data);
|
||||
|
||||
VkDescriptorImageInfo image_info;
|
||||
image_info.sampler = vk.sampler;
|
||||
image_info.imageView = vk_image.image_view;
|
||||
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
VkWriteDescriptorSet descriptor_write;
|
||||
descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptor_write.dstSet = vk_image.descriptor_set;
|
||||
descriptor_write.dstBinding = 0;
|
||||
descriptor_write.dstArrayElement = 0;
|
||||
descriptor_write.descriptorCount = 1;
|
||||
descriptor_write.pNext = nullptr;
|
||||
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
descriptor_write.pImageInfo = &image_info;
|
||||
descriptor_write.pBufferInfo = nullptr;
|
||||
descriptor_write.pTexelBufferView = nullptr;
|
||||
|
||||
vkUpdateDescriptorSets(vk.device, 1, &descriptor_write, 0, nullptr);
|
||||
Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index];
|
||||
vkDestroyImage(vk.device, image.handle, nullptr);
|
||||
vkDestroyImageView(vk.device, image.view, nullptr);
|
||||
vkFreeDescriptorSets(vk.device, vk.descriptor_pool, 1, &image.descriptor_set);
|
||||
image = vk_create_image(cols, rows, 1);
|
||||
vk_upload_image_data(image.handle, cols, rows, false, data);
|
||||
} else {
|
||||
if (dirty) {
|
||||
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
|
||||
|
|
@ -764,8 +746,8 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
|
|||
qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
|
||||
|
||||
// VULKAN
|
||||
const Vk_Image& vk_image = vk_resources.images[tr.scratchImage[client]->index];
|
||||
vk_upload_image_data(vk_image.image, cols, rows, data);
|
||||
const Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index];
|
||||
vk_upload_image_data(image.handle, cols, rows, false, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -513,6 +513,7 @@ static void Upload32( unsigned *data,
|
|||
qboolean mipmap,
|
||||
qboolean picmip,
|
||||
qboolean lightMap,
|
||||
Vk_Image& image,
|
||||
int *format,
|
||||
int *pUploadWidth, int *pUploadHeight )
|
||||
{
|
||||
|
|
@ -523,6 +524,7 @@ static void Upload32( unsigned *data,
|
|||
int i, c;
|
||||
byte *scan;
|
||||
GLenum internalFormat = GL_RGB;
|
||||
int miplevel = 0;
|
||||
|
||||
//
|
||||
// convert to exact power of 2 sizes
|
||||
|
|
@ -629,6 +631,10 @@ static void Upload32( unsigned *data,
|
|||
} else {
|
||||
internalFormat = 3;
|
||||
}
|
||||
|
||||
// VULKAN
|
||||
auto mipmap_buffer = (byte*) ri.Hunk_AllocateTempMemory(int(2.0 * 4 * scaled_width * scaled_height));
|
||||
|
||||
// copy or resample data as appropriate for first MIP level
|
||||
if ( ( scaled_width == width ) &&
|
||||
( scaled_height == height ) ) {
|
||||
|
|
@ -639,6 +645,9 @@ static void Upload32( unsigned *data,
|
|||
*pUploadHeight = scaled_height;
|
||||
*format = internalFormat;
|
||||
|
||||
// VULKAN
|
||||
Com_Memcpy(mipmap_buffer, data, width * height * 4);
|
||||
|
||||
goto done;
|
||||
}
|
||||
Com_Memcpy (scaledBuffer, data, width*height*4);
|
||||
|
|
@ -668,11 +677,12 @@ static void Upload32( unsigned *data,
|
|||
|
||||
qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer );
|
||||
|
||||
// VULKAN
|
||||
Com_Memcpy(mipmap_buffer, scaledBuffer, scaled_width * scaled_height * 4);
|
||||
int mipmap_buffer_size = scaled_width * scaled_height * 4;
|
||||
|
||||
if (mipmap)
|
||||
{
|
||||
int miplevel;
|
||||
|
||||
miplevel = 0;
|
||||
while (scaled_width > 1 || scaled_height > 1)
|
||||
{
|
||||
R_MipMap( (byte *)scaledBuffer, scaled_width, scaled_height );
|
||||
|
|
@ -689,10 +699,22 @@ static void Upload32( unsigned *data,
|
|||
}
|
||||
|
||||
qglTexImage2D (GL_TEXTURE_2D, miplevel, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer );
|
||||
|
||||
// VULKAN
|
||||
Com_Memcpy(&mipmap_buffer[mipmap_buffer_size], scaledBuffer, scaled_width * scaled_height * 4);
|
||||
mipmap_buffer_size += scaled_width * scaled_height * 4;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
// VULKAN
|
||||
image = vk_create_image(*pUploadWidth, *pUploadHeight, miplevel + 1);
|
||||
vk_upload_image_data(image.handle, *pUploadWidth, *pUploadHeight, mipmap == qtrue, mipmap_buffer);
|
||||
|
||||
if (mipmap_buffer != nullptr)
|
||||
ri.Hunk_FreeTempMemory(mipmap_buffer);
|
||||
|
||||
if (mipmap)
|
||||
{
|
||||
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
||||
|
|
@ -758,6 +780,7 @@ image_t *R_CreateImage( const char *name, const byte *pic, int width, int height
|
|||
image->mipmap,
|
||||
allowPicmip,
|
||||
isLightmap,
|
||||
vk_resources.images[image->index],
|
||||
&image->internalFormat,
|
||||
&image->uploadWidth,
|
||||
&image->uploadHeight );
|
||||
|
|
@ -775,12 +798,6 @@ image_t *R_CreateImage( const char *name, const byte *pic, int width, int height
|
|||
image->next = hashTable[hash];
|
||||
hashTable[hash] = image;
|
||||
|
||||
// VULKAN
|
||||
Vk_Image& vk_image = vk_resources.images[image->index];
|
||||
vk_image.image = vk_create_image(width, height, vk_image.image_view);
|
||||
vk_upload_image_data(vk_image.image, width, height, pic);
|
||||
vk_image.descriptor_set = vk_create_descriptor_set(vk_image.image_view);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ static VkImageView create_image_view(VkImage image, VkFormat format, VkImageAspe
|
|||
desc.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
desc.subresourceRange.aspectMask = aspect_flags;
|
||||
desc.subresourceRange.baseMipLevel = 0;
|
||||
desc.subresourceRange.levelCount = 1;
|
||||
desc.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
desc.subresourceRange.baseArrayLayer = 0;
|
||||
desc.subresourceRange.layerCount = 1;
|
||||
|
||||
|
|
@ -677,7 +677,7 @@ void vk_create_instance(HWND hwnd) {
|
|||
VkDescriptorPoolCreateInfo desc;
|
||||
desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
desc.pNext = nullptr;
|
||||
desc.flags = 0;
|
||||
desc.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; // used by the cinematic images
|
||||
desc.maxSets = MAX_DRAWIMAGES;
|
||||
desc.poolSizeCount = 1;
|
||||
desc.pPoolSizes = &pool_size;
|
||||
|
|
@ -857,7 +857,7 @@ void vk_create_instance(HWND hwnd) {
|
|||
desc.compareEnable = VK_FALSE;
|
||||
desc.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||
desc.minLod = 0.0f;
|
||||
desc.maxLod = 0.0f;
|
||||
desc.maxLod = 12.0f;
|
||||
desc.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
||||
desc.unnormalizedCoordinates = VK_FALSE;
|
||||
|
||||
|
|
@ -944,16 +944,18 @@ void vk_destroy_resources() {
|
|||
pipeline_create_time = 0.0f;
|
||||
|
||||
for (int i = 0; i < MAX_VK_IMAGES; i++) {
|
||||
Vk_Image& vk_image = res.images[i];
|
||||
Vk_Image& image = res.images[i];
|
||||
|
||||
if (vk_image.image != VK_NULL_HANDLE) {
|
||||
vkDestroyImage(vk.device, vk_image.image, nullptr);
|
||||
vkDestroyImageView(vk.device, vk_image.image_view, nullptr);
|
||||
if (image.handle != VK_NULL_HANDLE) {
|
||||
vkDestroyImage(vk.device, image.handle, nullptr);
|
||||
vkDestroyImageView(vk.device, image.view, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
Com_Memset(&res, 0, sizeof(res));
|
||||
|
||||
VK_CHECK(vkResetDescriptorPool(vk.device, vk.descriptor_pool, 0));
|
||||
|
||||
// Reset geometry buffer's current offsets.
|
||||
vk.xyz_elements = 0;
|
||||
vk.color_st_elements = 0;
|
||||
|
|
@ -978,7 +980,11 @@ static void record_buffer_memory_barrier(VkCommandBuffer cb, VkBuffer buffer,
|
|||
vkCmdPipelineBarrier(cb, src_stages, dst_stages, 0, 0, nullptr, 1, &barrier, 0, nullptr);
|
||||
}
|
||||
|
||||
VkImage vk_create_image(int width, int height, VkImageView& image_view) {
|
||||
Vk_Image vk_create_image(int width, int height, int mip_levels) {
|
||||
Vk_Image image;
|
||||
|
||||
// create image
|
||||
{
|
||||
VkImageCreateInfo desc;
|
||||
desc.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
desc.pNext = nullptr;
|
||||
|
|
@ -988,7 +994,7 @@ VkImage vk_create_image(int width, int height, VkImageView& image_view) {
|
|||
desc.extent.width = width;
|
||||
desc.extent.height = height;
|
||||
desc.extent.depth = 1;
|
||||
desc.mipLevels = 1;
|
||||
desc.mipLevels = mip_levels;
|
||||
desc.arrayLayers = 1;
|
||||
desc.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
desc.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
|
|
@ -998,21 +1004,84 @@ VkImage vk_create_image(int width, int height, VkImageView& image_view) {
|
|||
desc.pQueueFamilyIndices = nullptr;
|
||||
desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
VkImage image;
|
||||
VK_CHECK(vkCreateImage(vk.device, &desc, nullptr, &image));
|
||||
allocate_and_bind_image_memory(image);
|
||||
image_view = create_image_view(image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
VK_CHECK(vkCreateImage(vk.device, &desc, nullptr, &image.handle));
|
||||
allocate_and_bind_image_memory(image.handle);
|
||||
}
|
||||
|
||||
image.view = create_image_view(image.handle, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
|
||||
// create associated descriptor set
|
||||
{
|
||||
VkDescriptorSetAllocateInfo desc;
|
||||
desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
desc.pNext = nullptr;
|
||||
desc.descriptorPool = vk.descriptor_pool;
|
||||
desc.descriptorSetCount = 1;
|
||||
desc.pSetLayouts = &vk.set_layout;
|
||||
|
||||
VK_CHECK(vkAllocateDescriptorSets(vk.device, &desc, &image.descriptor_set));
|
||||
|
||||
VkDescriptorImageInfo image_info;
|
||||
image_info.sampler = vk.sampler;
|
||||
image_info.imageView = image.view;
|
||||
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
VkWriteDescriptorSet descriptor_write;
|
||||
descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptor_write.dstSet = image.descriptor_set;
|
||||
descriptor_write.dstBinding = 0;
|
||||
descriptor_write.dstArrayElement = 0;
|
||||
descriptor_write.descriptorCount = 1;
|
||||
descriptor_write.pNext = nullptr;
|
||||
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
descriptor_write.pImageInfo = &image_info;
|
||||
descriptor_write.pBufferInfo = nullptr;
|
||||
descriptor_write.pTexelBufferView = nullptr;
|
||||
|
||||
vkUpdateDescriptorSets(vk.device, 1, &descriptor_write, 0, nullptr);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
void vk_upload_image_data(VkImage image, int width, int height, const uint8_t* rgba_pixels) {
|
||||
VkDeviceSize size = width * height * 4;
|
||||
void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, const uint8_t* rgba_pixels) {
|
||||
VkBufferImageCopy regions[16];
|
||||
int num_regions = 0;
|
||||
|
||||
ensure_staging_buffer_allocation(size);
|
||||
Com_Memcpy(vk_resources.staging_buffer_ptr, rgba_pixels, size);
|
||||
int buffer_size = 0;
|
||||
|
||||
while (true) {
|
||||
VkBufferImageCopy region;
|
||||
region.bufferOffset = buffer_size;
|
||||
region.bufferRowLength = 0;
|
||||
region.bufferImageHeight = 0;
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.mipLevel = num_regions;
|
||||
region.imageSubresource.baseArrayLayer = 0;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageOffset = VkOffset3D{ 0, 0, 0 };
|
||||
region.imageExtent = VkExtent3D{ (uint32_t)width, (uint32_t)height, 1 };
|
||||
|
||||
regions[num_regions] = region;
|
||||
num_regions++;
|
||||
|
||||
buffer_size += width * height * 4;
|
||||
|
||||
if (!mipmap || (width == 1 && height == 1))
|
||||
break;
|
||||
|
||||
width >>= 1;
|
||||
if (width < 1) width = 1;
|
||||
|
||||
height >>= 1;
|
||||
if (height < 1) height = 1;
|
||||
}
|
||||
|
||||
ensure_staging_buffer_allocation(buffer_size);
|
||||
Com_Memcpy(vk_resources.staging_buffer_ptr, rgba_pixels, buffer_size);
|
||||
|
||||
record_and_run_commands(vk.command_pool, vk.queue,
|
||||
[&image, &width, &height](VkCommandBuffer command_buffer) {
|
||||
[&image, &num_regions, ®ions](VkCommandBuffer command_buffer) {
|
||||
|
||||
record_buffer_memory_barrier(command_buffer, vk_resources.staging_buffer,
|
||||
VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
|
|
@ -1021,18 +1090,7 @@ void vk_upload_image_data(VkImage image, int width, int height, const uint8_t* r
|
|||
record_image_layout_transition(command_buffer, image, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
0, VK_IMAGE_LAYOUT_UNDEFINED, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
VkBufferImageCopy region;
|
||||
region.bufferOffset = 0;
|
||||
region.bufferRowLength = 0;
|
||||
region.bufferImageHeight = 0;
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.mipLevel = 0;
|
||||
region.imageSubresource.baseArrayLayer = 0;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageOffset = VkOffset3D{ 0, 0, 0 };
|
||||
region.imageExtent = VkExtent3D{ (uint32_t)width, (uint32_t)height, 1 };
|
||||
|
||||
vkCmdCopyBufferToImage(command_buffer, vk_resources.staging_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
vkCmdCopyBufferToImage(command_buffer, vk_resources.staging_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, num_regions, regions);
|
||||
|
||||
record_image_layout_transition(command_buffer, image, VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
|
|
@ -1383,38 +1441,6 @@ VkPipeline vk_find_pipeline(const Vk_Pipeline_Desc& desc) {
|
|||
return pipeline;
|
||||
}
|
||||
|
||||
VkDescriptorSet vk_create_descriptor_set(VkImageView image_view) {
|
||||
VkDescriptorSetAllocateInfo desc;
|
||||
desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
desc.pNext = nullptr;
|
||||
desc.descriptorPool = vk.descriptor_pool;
|
||||
desc.descriptorSetCount = 1;
|
||||
desc.pSetLayouts = &vk.set_layout;
|
||||
|
||||
VkDescriptorSet set;
|
||||
VK_CHECK(vkAllocateDescriptorSets(vk.device, &desc, &set));
|
||||
|
||||
VkDescriptorImageInfo image_info;
|
||||
image_info.sampler = vk.sampler;
|
||||
image_info.imageView = image_view;
|
||||
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
VkWriteDescriptorSet descriptor_write;
|
||||
descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptor_write.dstSet = set;
|
||||
descriptor_write.dstBinding = 0;
|
||||
descriptor_write.dstArrayElement = 0;
|
||||
descriptor_write.descriptorCount = 1;
|
||||
descriptor_write.pNext = nullptr;
|
||||
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
descriptor_write.pImageInfo = &image_info;
|
||||
descriptor_write.pBufferInfo = nullptr;
|
||||
descriptor_write.pTexelBufferView = nullptr;
|
||||
|
||||
vkUpdateDescriptorSets(vk.device, 1, &descriptor_write, 0, nullptr);
|
||||
return set;
|
||||
}
|
||||
|
||||
VkRect2D vk_get_viewport_rect() {
|
||||
VkRect2D r;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ const int MAX_IMAGE_CHUNKS = 16;
|
|||
#define VK_CHECK(function_call) { \
|
||||
VkResult result = function_call; \
|
||||
if (result < 0) \
|
||||
ri.Error(ERR_FATAL, "Vulkan error: function %s, error code %d", function_call, result); \
|
||||
ri.Error(ERR_FATAL, "Vulkan error: function %s, error code %d", #function_call, result); \
|
||||
}
|
||||
|
||||
enum class Vk_Shader_Type {
|
||||
|
|
@ -42,15 +42,14 @@ struct Vk_Pipeline_Desc {
|
|||
};
|
||||
|
||||
struct Vk_Image {
|
||||
VkImage image = VK_NULL_HANDLE;
|
||||
VkImageView image_view = VK_NULL_HANDLE;
|
||||
VkImage handle = VK_NULL_HANDLE;
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
|
||||
// One to one correspondence between images and descriptor sets.
|
||||
// We update descriptor set during image initialization and then never touch it again (except for cinematic images).
|
||||
VkDescriptorSet descriptor_set;
|
||||
// Descriptor set that contains single descriptor used to access the given image.
|
||||
// It is updated only once during image initialization.
|
||||
VkDescriptorSet descriptor_set = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Initialization.
|
||||
//
|
||||
|
|
@ -61,10 +60,9 @@ void vk_destroy_resources(); // destroys Vk_Resources resources
|
|||
//
|
||||
// Resources allocation.
|
||||
//
|
||||
VkImage vk_create_image(int width, int height, VkImageView& image_view);
|
||||
void vk_upload_image_data(VkImage image, int width, int height, const uint8_t* rgba_pixels);
|
||||
Vk_Image vk_create_image(int width, int height, int mip_levels);
|
||||
void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, const uint8_t* rgba_pixels);
|
||||
VkPipeline vk_find_pipeline(const Vk_Pipeline_Desc& desc);
|
||||
VkDescriptorSet vk_create_descriptor_set(VkImageView image_view);
|
||||
|
||||
//
|
||||
// Rendering setup.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user