Support for r_texturebits=16. Reworked image upload code.

This commit is contained in:
Artem Kharytoniuk 2017-05-27 22:56:02 +03:00
parent a57c8382b1
commit 83d8d96e76
4 changed files with 189 additions and 243 deletions

View File

@ -716,8 +716,8 @@ void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int
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, false);
vk_upload_image_data(image.handle, cols, rows, false, data);
image = vk_create_image(cols, rows, VK_FORMAT_R8G8B8A8_UNORM, 1, false);
vk_upload_image_data(image.handle, cols, rows, false, data, 4);
}
} else {
if (dirty) {
@ -728,7 +728,7 @@ void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int
// VULKAN
if (vk.active) {
const Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index];
vk_upload_image_data(image.handle, cols, rows, false, data);
vk_upload_image_data(image.handle, cols, rows, false, data, 4);
}
}
}

View File

@ -511,37 +511,23 @@ byte mipBlendColors[16][4] = {
{0,0,255,128},
};
struct Image_Upload_Data {
byte* buffer;
int buffer_size;
int mip_levels;
int base_level_width;
int base_level_height;
};
/*
===============
Upload32
===============
*/
static void Upload32( unsigned *data,
int width, int height,
qboolean mipmap,
qboolean picmip,
qboolean lightMap,
int *format,
int *pUploadWidth, int *pUploadHeight,
// VULKAN
Vk_Image& image,
bool repeat_texture
)
{
int samples;
unsigned *scaledBuffer = NULL;
unsigned *resampledBuffer = NULL;
int scaled_width, scaled_height;
int i, c;
byte *scan;
GLenum internalFormat = GL_RGB;
int miplevel = 0;
static Image_Upload_Data generate_image_upload_data(const byte* data, int width, int height, qboolean mipmap, qboolean picmip) {
Image_Upload_Data upload_data;
upload_data.buffer = (byte*) ri.Hunk_AllocateTempMemory(2 * 4 * width * height);
//
// convert to exact power of 2 sizes
//
int scaled_width, scaled_height;
for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
;
for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
@ -551,10 +537,11 @@ static void Upload32( unsigned *data,
if ( r_roundImagesDown->integer && scaled_height > height )
scaled_height >>= 1;
byte* resampled_buffer = nullptr;
if ( scaled_width != width || scaled_height != height ) {
resampledBuffer = (unsigned int*) ri.Hunk_AllocateTempMemory( scaled_width * scaled_height * 4 );
ResampleTexture (data, width, height, resampledBuffer, scaled_width, scaled_height);
data = resampledBuffer;
resampled_buffer = (byte*) ri.Hunk_AllocateTempMemory( scaled_width * scaled_height * 4 );
ResampleTexture ((unsigned*)data, width, height, (unsigned*)resampled_buffer, scaled_width, scaled_height);
data = resampled_buffer;
width = scaled_width;
height = scaled_height;
}
@ -589,166 +576,168 @@ static void Upload32( unsigned *data,
scaled_height >>= 1;
}
scaledBuffer = (unsigned int*) ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height );
upload_data.base_level_width = scaled_width;
upload_data.base_level_height = scaled_height;
//
// scan the texture for each channel's max values
// and verify if the alpha channel is being used or not
//
c = width*height;
scan = ((byte *)data);
samples = 3;
if (!lightMap) {
for ( i = 0; i < c; i++ )
{
if ( scan[i*4 + 3] != 255 )
{
samples = 4;
break;
}
}
// select proper internal format
if ( samples == 3 )
{
if ( glConfig.textureCompression == TC_S3TC )
{
internalFormat = GL_RGB4_S3TC;
}
else if ( r_texturebits->integer == 16 )
{
internalFormat = GL_RGB5;
}
else if ( r_texturebits->integer == 32 )
{
internalFormat = GL_RGB8;
}
else
{
internalFormat = 3;
}
}
else if ( samples == 4 )
{
if ( r_texturebits->integer == 16 )
{
internalFormat = GL_RGBA4;
}
else if ( r_texturebits->integer == 32 )
{
internalFormat = GL_RGBA8;
}
else
{
internalFormat = 4;
}
}
} else {
internalFormat = 3;
if (scaled_width == width && scaled_height == height && !mipmap) {
upload_data.mip_levels = 1;
upload_data.buffer_size = scaled_width * scaled_height * 4;
Com_Memcpy(upload_data.buffer, data, upload_data.buffer_size);
if (resampled_buffer != nullptr)
ri.Hunk_FreeTempMemory(resampled_buffer);
return upload_data;
}
// VULKAN
auto mipmap_buffer = (byte*) ri.Hunk_AllocateTempMemory(int(2.0 * 4 * scaled_width * scaled_height));
// Use the normal mip-mapping to go down from [width, height] to [scaled_width, scaled_height] dimensions.
while (width > scaled_width || height > scaled_height) {
R_MipMap((byte *)data, width, height);
// copy or resample data as appropriate for first MIP level
if ( ( scaled_width == width ) &&
( scaled_height == height ) ) {
if (!mipmap)
{
qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
*pUploadWidth = scaled_width;
*pUploadHeight = scaled_height;
*format = internalFormat;
width >>= 1;
if (width < 1) width = 1;
// VULKAN
Com_Memcpy(mipmap_buffer, data, width * height * 4);
goto done;
}
Com_Memcpy (scaledBuffer, data, width*height*4);
}
else
{
// use the normal mip-mapping function to go down from here
while ( width > scaled_width || height > scaled_height ) {
R_MipMap( (byte *)data, width, height );
width >>= 1;
height >>= 1;
if ( width < 1 ) {
width = 1;
}
if ( height < 1 ) {
height = 1;
}
}
Com_Memcpy( scaledBuffer, data, width * height * 4 );
height >>= 1;
if (height < 1) height = 1;
}
R_LightScaleTexture (scaledBuffer, scaled_width, scaled_height, (qboolean) !mipmap );
// At this point width == scaled_width and height == scaled_height.
*pUploadWidth = scaled_width;
*pUploadHeight = scaled_height;
*format = internalFormat;
unsigned* scaled_buffer = (unsigned int*) ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height );
Com_Memcpy(scaled_buffer, data, scaled_width * scaled_height * 4);
R_LightScaleTexture(scaled_buffer, scaled_width, scaled_height, (qboolean) !mipmap);
qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer );
int miplevel = 0;
int mip_level_size = scaled_width * scaled_height * 4;
// VULKAN
Com_Memcpy(mipmap_buffer, scaledBuffer, scaled_width * scaled_height * 4);
int mipmap_buffer_size = scaled_width * scaled_height * 4;
Com_Memcpy(upload_data.buffer, scaled_buffer, mip_level_size);
upload_data.buffer_size = mip_level_size;
if (mipmap) {
while (scaled_width > 1 || scaled_height > 1) {
R_MipMap((byte *)scaled_buffer, scaled_width, scaled_height);
if (mipmap)
{
while (scaled_width > 1 || scaled_height > 1)
{
R_MipMap( (byte *)scaledBuffer, scaled_width, scaled_height );
scaled_width >>= 1;
if (scaled_width < 1) scaled_width = 1;
scaled_height >>= 1;
if (scaled_width < 1)
scaled_width = 1;
if (scaled_height < 1)
scaled_height = 1;
if (scaled_height < 1) scaled_height = 1;
miplevel++;
mip_level_size = scaled_width * scaled_height * 4;
if ( r_colorMipLevels->integer ) {
R_BlendOverTexture( (byte *)scaledBuffer, scaled_width * scaled_height, mipBlendColors[miplevel] );
R_BlendOverTexture( (byte *)scaled_buffer, scaled_width * scaled_height, mipBlendColors[miplevel] );
}
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;
Com_Memcpy(&upload_data.buffer[upload_data.buffer_size], scaled_buffer, mip_level_size);
upload_data.buffer_size += mip_level_size;
}
}
upload_data.mip_levels = miplevel + 1;
done:
ri.Hunk_FreeTempMemory(scaled_buffer);
if (resampled_buffer != nullptr)
ri.Hunk_FreeTempMemory(resampled_buffer);
// VULKAN
if (vk.active) {
image = vk_create_image(*pUploadWidth, *pUploadHeight, miplevel + 1, repeat_texture);
vk_upload_image_data(image.handle, *pUploadWidth, *pUploadHeight, mipmap == qtrue, mipmap_buffer);
}
if (mipmap_buffer != nullptr)
ri.Hunk_FreeTempMemory(mipmap_buffer);
return upload_data;
}
if (mipmap)
{
static int upload_gl_image(const Image_Upload_Data& upload_data, int texture_address_mode) {
int w = upload_data.base_level_width;
int h = upload_data.base_level_height;
bool has_alpha = false;
for (int i = 0; i < w * h; i++) {
if (upload_data.buffer[i*4 + 3] != 255) {
has_alpha = true;
break;
}
}
int internal_format = GL_RGBA8;
if (glConfig.textureCompression && !has_alpha) {
internal_format = GL_RGB4_S3TC;
} else if (r_texturebits->integer <= 16) {
internal_format = has_alpha ? GL_RGBA4 : GL_RGB5;
}
auto buffer = upload_data.buffer;
for (int i = 0; i < upload_data.mip_levels; i++) {
qglTexImage2D(GL_TEXTURE_2D, i, internal_format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
buffer += w * h * 4;
w >>= 1;
if (w < 1) w = 1;
h >>= 1;
if (h < 1) h = 1;
}
if (upload_data.mip_levels > 1) {
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
else
{
} else {
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
GL_CheckErrors();
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texture_address_mode);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texture_address_mode);
if ( scaledBuffer != 0 )
ri.Hunk_FreeTempMemory( scaledBuffer );
if ( resampledBuffer != 0 )
ri.Hunk_FreeTempMemory( resampledBuffer );
GL_CheckErrors();
return internal_format;
}
// VULKAN
static Vk_Image upload_vk_image(const Image_Upload_Data& upload_data, bool repeat_texture) {
int w = upload_data.base_level_width;
int h = upload_data.base_level_height;
bool has_alpha = false;
for (int i = 0; i < w * h; i++) {
if (upload_data.buffer[i*4 + 3] != 255) {
has_alpha = true;
break;
}
}
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
if (r_texturebits->integer <= 16) {
format = has_alpha ? VK_FORMAT_B4G4R4A4_UNORM_PACK16 : VK_FORMAT_A1R5G5B5_UNORM_PACK16;
}
int bytes_per_pixel = 4;
if (format == VK_FORMAT_A1R5G5B5_UNORM_PACK16) {
bytes_per_pixel = 2;
auto p = (uint16_t*)upload_data.buffer;
for (int i = 0; i < upload_data.buffer_size; i += 4, p++) {
byte r = upload_data.buffer[i+0];
byte g = upload_data.buffer[i+1];
byte b = upload_data.buffer[i+2];
*p = uint32_t((b/255.0) * 31.0 + 0.5) |
(uint32_t((g/255.0) * 31.0 + 0.5) << 5) |
(uint32_t((r/255.0) * 31.0 + 0.5) << 10) |
(1 << 15);
}
} else if (format == VK_FORMAT_B4G4R4A4_UNORM_PACK16) {
bytes_per_pixel = 2;
auto p = (uint16_t*)upload_data.buffer;
for (int i = 0; i < upload_data.buffer_size; i += 4, p++) {
byte r = upload_data.buffer[i+0];
byte g = upload_data.buffer[i+1];
byte b = upload_data.buffer[i+2];
byte a = upload_data.buffer[i+3];
*p = uint32_t((a/255.0) * 15.0 + 0.5) |
(uint32_t((r/255.0) * 15.0 + 0.5) << 4) |
(uint32_t((g/255.0) * 15.0 + 0.5) << 8) |
(uint32_t((b/255.0) * 15.0 + 0.5) << 12);
}
}
Vk_Image image = vk_create_image(w, h, format, upload_data.mip_levels, repeat_texture);
vk_upload_image_data(image.handle, w, h, upload_data.mip_levels > 1, upload_data.buffer, bytes_per_pixel);
return image;
}
/*
================
@ -759,62 +748,51 @@ This is the only way any image_t are created
*/
image_t *R_CreateImage( const char *name, const byte *pic, int width, int height,
qboolean mipmap, qboolean allowPicmip, int glWrapClampMode ) {
image_t *image;
qboolean isLightmap = qfalse;
long hash;
if (strlen(name) >= MAX_QPATH ) {
ri.Error (ERR_DROP, "R_CreateImage: \"%s\" is too long\n", name);
}
if ( !strncmp( name, "*lightmap", 9 ) ) {
isLightmap = qtrue;
}
if ( tr.numImages == MAX_DRAWIMAGES ) {
ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit\n");
}
image = tr.images[tr.numImages] = (image_t*) ri.Hunk_Alloc( sizeof( image_t ), h_low );
// Create image_t object.
auto image = tr.images[tr.numImages] = (image_t*) ri.Hunk_Alloc( sizeof( image_t ), h_low );
image->index = tr.numImages;
image->texnum = 1024 + tr.numImages;
tr.numImages++;
image->mipmap = mipmap;
image->allowPicmip = allowPicmip;
strcpy (image->imgName, name);
image->width = width;
image->height = height;
image->wrapClampMode = glWrapClampMode;
long hash = generateHashValue(name);
image->next = hashTable[hash];
hashTable[hash] = image;
tr.numImages++;
// Create corresponding GPU resource.
bool isLightmap = (strncmp(name, "*lightmap", 9) == 0);
GL_SelectTexture(isLightmap ? 1 : 0);
GL_Bind(image);
Image_Upload_Data upload_data = generate_image_upload_data(pic, width, height, mipmap, allowPicmip);
Upload32( (unsigned *)pic, image->width, image->height,
image->mipmap,
allowPicmip,
isLightmap,
&image->internalFormat,
&image->uploadWidth,
&image->uploadHeight,
vk_resources.images[image->index],
glWrapClampMode == GL_REPEAT
);
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode );
qglBindTexture( GL_TEXTURE_2D, 0 );
if (glActive) {
image->internalFormat = upload_gl_image(upload_data, glWrapClampMode);
}
// VULKAN
if (vk.active) {
vk_resources.images[image->index] = upload_vk_image(upload_data, glWrapClampMode == GL_REPEAT);
}
if (isLightmap) {
GL_SelectTexture( 0 );
}
hash = generateHashValue(name);
image->next = hashTable[hash];
hashTable[hash] = image;
ri.Hunk_FreeTempMemory(upload_data.buffer);
return image;
}

View File

@ -251,34 +251,9 @@ static void record_and_run_commands(VkCommandPool command_pool, VkQueue queue, s
vkFreeCommandBuffers(vk.device, command_pool, 1, &command_buffer);
}
static void record_image_layout_transition(VkCommandBuffer command_buffer, VkImage image, VkFormat format,
static void record_image_layout_transition(VkCommandBuffer command_buffer, VkImage image, VkImageAspectFlags image_aspect_flags,
VkAccessFlags src_access_flags, VkImageLayout old_layout, VkAccessFlags dst_access_flags, VkImageLayout new_layout) {
auto has_depth_component = [](VkFormat format) {
switch (format) {
case VK_FORMAT_D16_UNORM:
case VK_FORMAT_X8_D24_UNORM_PACK32:
case VK_FORMAT_D32_SFLOAT:
case VK_FORMAT_D16_UNORM_S8_UINT:
case VK_FORMAT_D24_UNORM_S8_UINT:
case VK_FORMAT_D32_SFLOAT_S8_UINT:
return true;
default:
return false;
}
};
auto has_stencil_component = [](VkFormat format) {
switch (format) {
case VK_FORMAT_S8_UINT:
case VK_FORMAT_D16_UNORM_S8_UINT:
case VK_FORMAT_D24_UNORM_S8_UINT:
case VK_FORMAT_D32_SFLOAT_S8_UINT:
return true;
default:
return false;
}
};
VkImageMemoryBarrier barrier;
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.pNext = nullptr;
@ -289,18 +264,7 @@ static void record_image_layout_transition(VkCommandBuffer command_buffer, VkIma
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
bool depth = has_depth_component(format);
bool stencil = has_stencil_component(format);
if (depth && stencil)
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
else if (depth)
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
else if (stencil)
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
else
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.aspectMask = image_aspect_flags;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
barrier.subresourceRange.baseArrayLayer = 0;
@ -860,8 +824,12 @@ void vk_initialize() {
VK_CHECK(vkCreateImageView(vk.device, &desc, nullptr, &vk.depth_image_view));
}
record_and_run_commands(vk.command_pool, vk.queue, [&depth_format](VkCommandBuffer command_buffer) {
record_image_layout_transition(command_buffer, vk.depth_image, depth_format, 0, VK_IMAGE_LAYOUT_UNDEFINED,
VkImageAspectFlags image_aspect_flags = VK_IMAGE_ASPECT_DEPTH_BIT;
if (r_stencilbits->integer)
image_aspect_flags |= VK_IMAGE_ASPECT_STENCIL_BIT;
record_and_run_commands(vk.command_pool, vk.queue, [&image_aspect_flags](VkCommandBuffer command_buffer) {
record_image_layout_transition(command_buffer, vk.depth_image, image_aspect_flags, 0, VK_IMAGE_LAYOUT_UNDEFINED,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
});
}
@ -1321,7 +1289,7 @@ static void record_buffer_memory_barrier(VkCommandBuffer cb, VkBuffer buffer,
vkCmdPipelineBarrier(cb, src_stages, dst_stages, 0, 0, nullptr, 1, &barrier, 0, nullptr);
}
Vk_Image vk_create_image(int width, int height, int mip_levels, bool repeat_texture) {
Vk_Image vk_create_image(int width, int height, VkFormat format, int mip_levels, bool repeat_texture) {
Vk_Image image;
// create image
@ -1331,7 +1299,7 @@ Vk_Image vk_create_image(int width, int height, int mip_levels, bool repeat_text
desc.pNext = nullptr;
desc.flags = 0;
desc.imageType = VK_IMAGE_TYPE_2D;
desc.format = VK_FORMAT_R8G8B8A8_UNORM;
desc.format = format;
desc.extent.width = width;
desc.extent.height = height;
desc.extent.depth = 1;
@ -1357,7 +1325,7 @@ Vk_Image vk_create_image(int width, int height, int mip_levels, bool repeat_text
desc.flags = 0;
desc.image = image.handle;
desc.viewType = VK_IMAGE_VIEW_TYPE_2D;
desc.format = VK_FORMAT_R8G8B8A8_UNORM;
desc.format = format;
desc.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
desc.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
desc.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
@ -1387,7 +1355,7 @@ Vk_Image vk_create_image(int width, int height, int mip_levels, bool repeat_text
return image;
}
void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, const uint8_t* rgba_pixels) {
void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, const uint8_t* pixels, int bytes_per_pixel) {
VkBufferImageCopy regions[16];
int num_regions = 0;
@ -1408,7 +1376,7 @@ void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, con
regions[num_regions] = region;
num_regions++;
buffer_size += width * height * 4;
buffer_size += width * height * bytes_per_pixel;
if (!mipmap || (width == 1 && height == 1))
break;
@ -1421,7 +1389,7 @@ void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, con
}
ensure_staging_buffer_allocation(buffer_size);
Com_Memcpy(vk_resources.staging_buffer_ptr, rgba_pixels, buffer_size);
Com_Memcpy(vk_resources.staging_buffer_ptr, pixels, buffer_size);
record_and_run_commands(vk.command_pool, vk.queue,
[&image, &num_regions, &regions](VkCommandBuffer command_buffer) {
@ -1430,12 +1398,12 @@ void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, con
VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
record_image_layout_transition(command_buffer, image, VK_FORMAT_R8G8B8A8_UNORM,
record_image_layout_transition(command_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT,
0, VK_IMAGE_LAYOUT_UNDEFINED, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
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,
record_image_layout_transition(command_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
});
}
@ -2336,11 +2304,11 @@ void vk_read_pixels(byte* buffer) {
VK_CHECK(vkBindImageMemory(vk.device, image, memory, 0));
record_and_run_commands(vk.command_pool, vk.queue, [&image](VkCommandBuffer command_buffer) {
record_image_layout_transition(command_buffer, vk.swapchain_images[vk.swapchain_image_index], vk.surface_format.format,
record_image_layout_transition(command_buffer, vk.swapchain_images[vk.swapchain_image_index], VK_IMAGE_ASPECT_COLOR_BIT,
VK_ACCESS_MEMORY_READ_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
record_image_layout_transition(command_buffer, image, VK_FORMAT_R8G8B8A8_UNORM,
record_image_layout_transition(command_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT,
0, VK_IMAGE_LAYOUT_UNDEFINED,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
});

View File

@ -86,8 +86,8 @@ void vk_release_resources();
//
// Resources allocation.
//
Vk_Image vk_create_image(int width, int height, int mip_levels, bool repeat_texture);
void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, const uint8_t* rgba_pixels);
Vk_Image vk_create_image(int width, int height, VkFormat format, int mip_levels, bool repeat_texture);
void vk_upload_image_data(VkImage image, int width, int height, bool mipmap, const uint8_t* pixels, int bytes_per_pixel);
void vk_update_descriptor_set(VkDescriptorSet set, VkImageView image_view, bool mipmap, bool repeat_texture);
VkSampler vk_find_sampler(const Vk_Sampler_Def& def);
VkPipeline vk_find_pipeline(const Vk_Pipeline_Def& def);