OpenGL command implemented, but not advertised with extension/version - opengl

I'm trying to support an Optimus system, that allows me to run my framework on an Intel GPU or on a NVIDIA GPU. No problems since I tried to support instanced drawing with instanced arrays.
While NVIDIA supports OpenGL 4.5, the Intel card supports OpenGL 3.1 with few extensions. During this debugging session, I discovered that glVertexAttribDivisor was defined by GL_ARB_instanced_arrays, not by GL_ARB_draw_instanced as I always believed till now.
However I've noticed that glVertexAttribDivisor is currently implemented (and it actually works!), but the relative extension is not advertised. Investigating on this issue, I found few other functions currently implemented, without being declared supported via the extension mechanism.
Here is a log of the extension retrieval:
glGetString(Version) = 3.1.0 - Build 8.15.10.2622
glGetError() = NoError
glGetIntegerv(NumExtensions, 117)
glGetError() = NoError
glGetStringi(0x1F03, 0) = GL_EXT_blend_minmax
glGetError() = NoError
glGetStringi(0x1F03, 1) = GL_EXT_blend_subtract
glGetError() = NoError
glGetStringi(0x1F03, 2) = GL_EXT_blend_color
glGetError() = NoError
glGetStringi(0x1F03, 3) = GL_EXT_abgr
glGetError() = NoError
glGetStringi(0x1F03, 4) = GL_EXT_texture3D
glGetError() = NoError
glGetStringi(0x1F03, 5) = GL_EXT_clip_volume_hint
glGetError() = NoError
glGetStringi(0x1F03, 6) = GL_EXT_compiled_vertex_array
glGetError() = NoError
glGetStringi(0x1F03, 7) = GL_SGIS_texture_edge_clamp
glGetError() = NoError
glGetStringi(0x1F03, 8) = GL_SGIS_generate_mipmap
glGetError() = NoError
glGetStringi(0x1F03, 9) = GL_EXT_draw_range_elements
glGetError() = NoError
glGetStringi(0x1F03, 10) = GL_SGIS_texture_lod
glGetError() = NoError
glGetStringi(0x1F03, 11) = GL_EXT_rescale_normal
glGetError() = NoError
glGetStringi(0x1F03, 12) = GL_EXT_packed_pixels
glGetError() = NoError
glGetStringi(0x1F03, 13) = GL_EXT_texture_edge_clamp
glGetError() = NoError
glGetStringi(0x1F03, 14) = GL_EXT_separate_specular_color
glGetError() = NoError
glGetStringi(0x1F03, 15) = GL_ARB_multitexture
glGetError() = NoError
glGetStringi(0x1F03, 16) = GL_EXT_texture_env_combine
glGetError() = NoError
glGetStringi(0x1F03, 17) = GL_EXT_bgra
glGetError() = NoError
glGetStringi(0x1F03, 18) = GL_EXT_blend_func_separate
glGetError() = NoError
glGetStringi(0x1F03, 19) = GL_EXT_secondary_color
glGetError() = NoError
glGetStringi(0x1F03, 20) = GL_EXT_fog_coord
glGetError() = NoError
glGetStringi(0x1F03, 21) = GL_EXT_tIl thread 0xe14 è terminato con il codice 0 (0x0).
exture_env_add
glGetError() = NoError
glGetStringi(0x1F03, 22) = GL_ARB_texture_cube_map
glGetError() = NoError
glGetStringi(0x1F03, 23) = GL_ARB_transpose_matrix
glGetError() = NoError
glGetStringi(0x1F03, 24) = GL_ARB_texture_env_add
glGetError() = NoError
glGetStringi(0x1F03, 25) = GL_IBM_texture_mirrored_repeat
glGetError() = NoError
glGetStringi(0x1F03, 26) = GL_EXT_multi_draw_arrays
glGetError() = NoError
glGetStringi(0x1F03, 27) = GL_NV_blend_square
glGetError() = NoError
glGetStringi(0x1F03, 28) = GL_ARB_texture_compression
glGetError() = NoError
glGetStringi(0x1F03, 29) = GL_3DFX_texture_compression_FXT1
glGetError() = NoError
glGetStringi(0x1F03, 30) = GL_EXT_texture_filter_anisotropic
glGetError() = NoError
glGetStringi(0x1F03, 31) = GL_ARB_texture_border_clamp
glGetError() = NoError
glGetStringi(0x1F03, 32) = GL_ARB_point_parameters
glGetError() = NoError
glGetStringi(0x1F03, 33) = GL_ARB_texture_env_combine
glGetError() = NoError
glGetStringi(0x1F03, 34) = GL_ARB_texture_env_dot3
glGetError() = NoError
glGetStringi(0x1F03, 35) = GL_ARB_texture_env_crossbar
glGetError() = NoError
glGetStringi(0x1F03, 36) = GL_EXT_texture_compression_s3tc
glGetError() = NoError
glGetStringi(0x1F03, 37) = GL_ARB_shadow
glGetError() = NoError
glGetStringi(0x1F03, 38) = GL_ARB_window_pos
glGetError() = NoError
glGetStringi(0x1F03, 39) = GL_EXT_shadow_funcs
glGetError() = NoError
glGetStringi(0x1F03, 40) = GL_EXT_stencil_wrap
glGetError() = NoError
glGetStringi(0x1F03, 41) = GL_ARB_vertex_program
glGetError() = NoError
glGetStringi(0x1F03, 42) = GL_EXT_texture_rectangle
glGetError() = NoError
glGetStringi(0x1F03, 43) = GL_ARB_fragment_program
glGetError() = NoError
glGetStringi(0x1F03, 44) = GL_EXT_stencil_two_side
glGetError() = NoError
glGetStringi(0x1F03, 45) = GL_ATI_separate_stencil
glGetError() = NoError
glGetStringi(0x1F03, 46) = GL_ARB_vertex_buffer_object
glGetError() = NoError
glGetStringi(0x1F03, 47) = GL_EXT_texture_lod_bias
glGetError() = NoError
glGetStringi(0x1F03, 48) = GL_ARB_occlusion_query
glGetError() = NoError
glGetStringi(0x1F03, 49) = GL_ARB_fragment_shader
glGetError() = NoError
glGetStringi(0x1F03, 50) = GL_ARB_shader_objects
glGetError() = NoError
glGetStringi(0x1F03, 51) = GL_ARB_shading_language_100
glGetError() = NoError
glGetStringi(0x1F03, 52) = GL_ARB_texture_non_power_of_two
glGetError() = NoError
glGetStringi(0x1F03, 53) = GL_ARB_vertex_shader
glGetError() = NoError
glGetStringi(0x1F03, 54) = GL_NV_texgen_reflection
glGetError() = NoError
glGetStringi(0x1F03, 55) = GL_ARB_point_sprite
glGetError() = NoError
glGetStringi(0x1F03, 56) = GL_ARB_fragment_program_shadow
glGetError() = NoError
glGetStringi(0x1F03, 57) = GL_EXT_blend_equation_separate
glGetError() = NoError
glGetStringi(0x1F03, 58) = GL_ARB_depth_texture
glGetError() = NoError
glGetStringi(0x1F03, 59) = GL_ARB_texture_rectangle
glGetError() = NoError
glGetStringi(0x1F03, 60) = GL_ARB_draw_buffers
glGetError() = NoError
glGetStringi(0x1F03, 61) = GL_ARB_color_buffer_float
glGetError() = NoError
glGetStringi(0x1F03, 62) = GL_ARB_half_float_pixel
glGetError() = NoError
glGetStringi(0x1F03, 63) = GL_ARB_texture_float
glGetError() = NoError
glGetStringi(0x1F03, 64) = GL_ARB_pixel_buffer_object
glGetError() = NoError
glGetStringi(0x1F03, 65) = GL_EXT_framebuffer_object
glGetError() = NoError
glGetStringi(0x1F03, 66) = GL_ARB_draw_instanced
glGetError() = NoError
glGetStringi(0x1F03, 67) = GL_ARB_half_float_vertex
glGetError() = NoError
glGetStringi(0x1F03, 68) = GL_EXT_draw_buffers2
glGetError() = NoError
glGetStringi(0x1F03, 69) = GL_WIN_swap_hint
glGetError() = NoError
glGetStringi(0x1F03, 70) = GL_EXT_texture_sRGB
glGetError() = NoError
glGetStringi(0x1F03, 71) = GL_ARB_multisample
glGetError() = NoError
glGetStringi(0x1F03, 72) = GL_EXT_packed_float
glGetError() = NoError
glGetStringi(0x1F03, 73) = GL_EXT_texture_shared_exponent
glGetError() = NoError
glGetStringi(0x1F03, 74) = GL_ARB_texture_rg
glGetError() = NoError
glGetStringi(0x1F03, 75) = GL_ARB_texture_compression_rgtc
glGetError() = NoError
glGetStringi(0x1F03, 76) = GL_NV_conditional_render
glGetError() = NoError
glGetStringi(0x1F03, 77) = GL_EXT_texture_swizzle
glGetError() = NoError
glGetStringi(0x1F03, 78) = GL_ARB_sync
glGetError() = NoError
glGetStringi(0x1F03, 79) = GL_ARB_framebuffer_sRGB
glGetError() = NoError
glGetStringi(0x1F03, 80) = GL_EXT_packed_depth_stencil
glGetError() = NoError
glGetStringi(0x1F03, 81) = GL_ARB_depth_buffer_float
glGetError() = NoError
glGetStringi(0x1F03, 82) = GL_EXT_transform_feedback
glGetError() = NoError
glGetStringi(0x1F03, 83) = GL_EXT_framebuffer_blit
glGetError() = NoError
glGetStringi(0x1F03, 84) = GL_EXT_framebuffer_multisample
glGetError() = NoError
glGetStringi(0x1F03, 85) = GL_ARB_framebuffer_object
glGetError() = NoError
glGetStringi(0x1F03, 86) = GL_EXT_texture_array
glGetError() = NoError
glGetStringi(0x1F03, 87) = GL_EXT_texture_integer
glGetError() = NoError
glGetStringi(0x1F03, 88) = GL_ARB_map_buffer_range
glGetError() = NoError
glGetStringi(0x1F03, 89) = GL_EXT_texture_snorm
glGetError() = NoError
glGetStringi(0x1F03, 90) = GL_INTEL_performance_queries
glGetError() = NoError
glGetStringi(0x1F03, 91) = GL_ARB_copy_buffer
glGetError() = NoError
glGetStringi(0x1F03, 92) = GL_ARB_sampler_objects
glGetError() = NoError
glGetStringi(0x1F03, 93) = GL_NV_primitive_restart
glGetError() = NoError
glGetStringi(0x1F03, 94) = GL_ARB_seamless_cube_map
glGetError() = NoError
glGetStringi(0x1F03, 95) = GL_ARB_uniform_buffer_object
glGetError() = NoError
glGetStringi(0x1F03, 96) = GL_ARB_depth_clamp
glGetError() = NoError
glGetStringi(0x1F03, 97) = GL_ARB_vertex_array_bgra
glGetError() = NoError
glGetStringi(0x1F03, 98) = GL_ARB_draw_elements_base_vertex
glGetError() = NoError
glGetStringi(0x1F03, 99) = GL_ARB_fragment_coord_conventions
glGetError() = NoError
glGetStringi(0x1F03, 100) = GL_EXT_gpu_program_parameters
glGetError() = NoError
glGetStringi(0x1F03, 101) = GL_ARB_compatibility
glGetError() = NoError
glGetStringi(0x1F03, 102) = GL_ARB_vertex_array_object
glGetError() = NoError
glGetStringi(0x1F03, 103) = WGL_EXT_depth_float
glGetError() = NoError
glGetStringi(0x1F03, 104) = WGL_ARB_buffer_region
glGetError() = NoError
glGetStringi(0x1F03, 105) = WGL_ARB_extensions_string
glGetError() = NoError
glGetStringi(0x1F03, 106) = WGL_ARB_make_current_read
glGetError() = NoError
glGetStringi(0x1F03, 107) = WGL_ARB_pixel_format
glGetError() = NoError
glGetStringi(0x1F03, 108) = WGL_ARB_pbuffer
glGetError() = NoError
glGetStringi(0x1F03, 109) = WGL_EXT_extensions_string
glGetError() = NoError
glGetStringi(0x1F03, 110) = WGL_EXT_swap_control
glGetError() = NoError
glGetStringi(0x1F03, 111) = WGL_EXT_swap_control_tear
glGetError() = NoError
glGetStringi(0x1F03, 112) = WGL_ARB_multisample
glGetError() = NoError
glGetStringi(0x1F03, 113) = WGL_ARB_pixel_format_float
glGetError() = NoError
glGetStringi(0x1F03, 114) = WGL_ARB_framebuffer_sRGB
glGetError() = NoError
glGetStringi(0x1F03, 115) = WGL_ARB_create_context
glGetError() = NoError
glGetStringi(0x1F03, 116) = WGL_EXT_pixel_format_packed_float
glGetError() = NoError
And here there is a log of the function mismatches:
// The command FramebufferTextureFaceARB is defined, but not supported by any feature.
// The command CullParameterdvEXT is defined, but not supported by any feature.
// The command CullParameterfvEXT is defined, but not supported by any feature.
// The command TransformFeedbackVaryings_Unmanaged is defined, but not supported by any feature.
// The command FramebufferTexture is defined, but not supported by any feature.
// The command TexImage2DMultisample is defined, but not supported by any feature.
// The command TexImage3DMultisample is defined, but not supported by any feature.
// The command GetMultisamplefv is defined, but not supported by any feature.
// The command SampleMaski is defined, but not supported by any feature.
// The command VertexAttribDivisor is defined, but not supported by any feature.
// The command ProgramParameteri is defined, but not supported by any feature.
// The command BeginPerfQueryINTEL is defined, but not supported by any feature.
// The command CreatePerfQueryINTEL is defined, but not supported by any feature.
// The command DeletePerfQueryINTEL is defined, but not supported by any feature.
// The command EndPerfQueryINTEL is defined, but not supported by any feature.
// The command GetFirstPerfQueryIdINTEL is defined, but not supported by any feature.
// The command GetNextPerfQueryIdINTEL is defined, but not supported by any feature.
// The command GetPerfCounterInfoINTEL is defined, but not supported by any feature.
// The command GetPerfQueryDataINTEL is defined, but not supported by any feature.
// The command GetPerfQueryIdByNameINTEL is defined, but not supported by any feature.
// The command GetPerfQueryInfoINTEL is defined, but not supported by any feature.
My question is: is it possible the usage of the above functions, even if they are not supported by any extension?
My first thought was that this is a way of the driver implementor to avoid the usage of those functions.
However, I want to use glVertexAttribDivisor to avoid multiple shader definition...

Is it possible? Yes. Is it a good idea to use it? No.
If an implementation doesn't feel confident enough in an implementation of an extension to actually advertise it, then you should not feel confident enough that it will work to use it.

On my box (Optimus with Nvidia M1000M and Intel HD graphics 530), I observed that the intel driver also supports OpenGL 4.5, but it requires to create a "core profile" OpenGL context (with a "compatibiity profile" context it reports OpenGL 3.1 only). This may explain why the function is there. I think it will be properly "advertised" by a core-profile context.

Related

How to fetch RSA public key modulus and exponent in C/C++?

I'm using the BCrypt Windows library to handle the RSA algorithm in my application.
Problem : I need to fetch the RSA public key modulus and exponent.
In C# language, I was using the RSACryptoProvider class to fetch these informations (ExportParameters method).
In my C/C++ application, BCrypt seems to be unable to fetch the right data...
What I've done so far:
BOOL RSA_New(RSA_CTX_ST* rsa_ctx, const BYTE key_data[256], DWORD key_len, BOOL cipher)
{
if (rsa_ctx == NULL || key_len != RSA_2048_BLOCK_SIZE)
{
return FALSE;
}
NTSTATUS status = STATUS_UNSUCCESSFUL;
BCRYPT_ALG_HANDLE* algo_handle = NULL;
BCRYPT_KEY_HANDLE* key_handle = NULL;
algo_handle = malloc(sizeof(BCRYPT_ALG_HANDLE));
key_handle = malloc(sizeof(BCRYPT_KEY_HANDLE));
if (algo_handle == NULL || key_handle == NULL) goto END;
//Creation handle Algo
if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(algo_handle, BCRYPT_RSA_ALGORITHM, NULL, 0)))
{
UTL_Trace("SEC", VRB_MAJOR, "RSA:Algorithm handle opening error");
if (status == STATUS_INVALID_HANDLE)
{
UTL_Trace("SEC", VRB_INFO, "INVALID HANDLE");
}
if (status == STATUS_INVALID_PARAMETER)
{
UTL_Trace("SEC", VRB_INFO, "INVALID PARAMS");
}
goto END;
}
// Key pair generation
if (!NT_SUCCESS(status = BCryptGenerateKeyPair(algo_handle, key_handle, 2048, 0)))
{
UTL_Trace("SEC", VRB_MAJOR, "RSA:Key pair generating error");
if (status == STATUS_INVALID_HANDLE)
{
UTL_Trace("SEC", VRB_INFO, "INVALID HANDLE");
}
if (status == STATUS_INVALID_PARAMETER)
{
UTL_Trace("SEC", VRB_INFO, "INVALID PARAMS");
}
goto END;
}
BCRYPT_RSAKEY_BLOB my_rsa_blob;
ULONG* pcbResult = NULL;
pcbResult = calloc(1, sizeof(ULONG));
if (pcbResult == NULL)
{
UTL_Trace("SEC", VRB_INFO, "Allocating RSA result error");
goto END;
}
// Export parameters of keys
if (!NT_SUCCESS(status = BCryptExportKey(key_handle, NULL, BCRYPT_RSAFULLPRIVATE_BLOB, &my_rsa_blob, sizeof(my_rsa_blob), pcbResult, 0)))
{
UTL_Trace("SEC", VRB_MAJOR, "RSA:Key pair exporting error");
if (status == STATUS_INVALID_HANDLE)
{
UTL_Trace("SEC", VRB_INFO, "INVALID HANDLE");
}
if (status == STATUS_INVALID_PARAMETER)
{
UTL_Trace("SEC", VRB_INFO, "INVALID PARAMS");
}
goto END;
}
return TRUE;
END:
if (algo_handle != NULL) free(algo_handle);
if (key_handle != NULL) free(key_handle);
return FALSE;
}
In my_rsa_blob, I should have the size of the modulus and exponent but not their values...
Does anyone have a solution to this problem ?
In fact, I did find a solution !
With the call of BCryptExportKey, the variable my_rsa_blob should have been a PUCHAR variable, which is a pointer to a string.
With this, I found a link in Microsoft Docs while searching...
The link is showing how the PUCHAR variable is designed :
https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/540b7b8b-2232-45c8-9d7c-af7a5d5218ed
After, you can try to manipulate data like this :
static BOOL RSA_RecoverKeyInformation(RSA_CTX_ST* rsa_ctx, PUCHAR ptrKey)
{
strncpy(rsa_ctx->key_information.header.Magic, ptrKey[0], 4);
strncpy(rsa_ctx->key_information.header.BitLength, ptrKey[1 * 4], 4);
strncpy(rsa_ctx->key_information.header.cbPublicExp, ptrKey[2 * 4], 4);
strncpy(rsa_ctx->key_information.header.cbModulus, ptrKey[3 * 4], 4);
strncpy(rsa_ctx->key_information.header.cbPrime1, ptrKey[4 * 4], 4);
strncpy(rsa_ctx->key_information.header.cbPrime2, ptrKey[5 * 4], 4);
size_t sizeOfModulus = rsa_ctx->key_information.header.cbModulus;
size_t sizeOfExponent = rsa_ctx->key_information.header.cbPublicExp;
rsa_ctx->key_information.keyExponent = malloc(sizeOfExponent);
rsa_ctx->key_information.keyModulus = malloc(sizeOfModulus);
if (rsa_ctx->key_information.keyExponent == NULL || rsa_ctx->key_information.keyModulus == NULL) goto END;
strncpy(rsa_ctx->key_information.keyExponent, ptrKey[6 * 4], sizeOfExponent);
strncpy(rsa_ctx->key_information.keyModulus, ptrKey[6 * 4 + sizeOfExponent], sizeOfModulus);
return TRUE;
END:
if (rsa_ctx->key_information.keyExponent != NULL) free(rsa_ctx->key_information.keyExponent);
if (rsa_ctx->key_information.keyModulus != NULL) free(rsa_ctx->key_information.keyModulus);
return FALSE;
}

How do you properly transition the image layout from transfer optimal to shader read optimal while also changing queue ownership in Vulkan?

I'm currently writing a rendering engine with the Vulkan API and my setup uses a different queue for transfer operations than for graphics operations if possible. When rendering images, they should be in the VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL layout, however since the image is currently owned by a queue that is only flagged with the transfer bit, i also need to transfer the ownership of the image to the graphics queue simultaneously.
This however seems to fail for some reason, as even though the command buffer with the pipeline barrier is executed, the image remains in the VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL layout, resulting in a validation error.
This is the method which transitions image layouts:
int PGraphicsContext::transitionImageLayout(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout)
{
VkCommandBuffer cmdBuffer = this->beginTransferCmdBuffer();
VkImageMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout;
barrier.image = image;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
VkPipelineStageFlags srcStage;
VkPipelineStageFlags dstStage;
if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
{
PApplication::getInstance()->getLogger()->debug("Transitioning image layout from VK_IMAGE_LAYOUT_UNDEFINED to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL");
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{
PApplication::getInstance()->getLogger()->debug("Transitioning image layout from VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL");
if (this->queueFamilies[PQueueIndex::TRANSFER_QUEUE].index != this->queueFamilies[PQueueIndex::GRAPHICS_QUEUE].index)
{
barrier.srcQueueFamilyIndex = this->queueFamilies[PQueueIndex::TRANSFER_QUEUE].index;
barrier.dstQueueFamilyIndex = this->queueFamilies[PQueueIndex::GRAPHICS_QUEUE].index;
}
else
{
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
}
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
else
{
// TODO: implement this
this->endTransferCmdBuffer(cmdBuffer);
PApplication::getInstance()->getLogger()->error("Failed to transition image layout from 0x%X to 0x%X", oldLayout, newLayout);
return PINE_ERROR_VULKAN_UNSUPPORTED_LAYER_TRANSITION;
}
vkCmdPipelineBarrier(cmdBuffer, srcStage, dstStage, {}, 0, nullptr, 0, nullptr, 1, &barrier);
this->endTransferCmdBuffer(cmdBuffer);
return PINE_SUCCESS;
}
This seems to work fine if the index of the transfer queue and the graphics queue are the same, meaning the source and destination queue family indices are both set to VK_QUEUE_FAMILY_IGNORED.
Here is an example of some log messages:
[15 JUN 23:17:27][Taiga::DEBUG]: Transitioning image layout from VK_IMAGE_LAYOUT_UNDEFINED to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
[15 JUN 23:17:27][Taiga::DEBUG]: Transitioning image layout from VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
[15 JUN 23:17:27][Taiga::ERROR]: Validation Error: [ UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout ] Object 0: handle = 0x7f34b4842668, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0x4dae5635 | Submitted command buffer expects VkImage 0xec4bec000000000b[] (subresource: aspectMask 0x1 array layer 0, mip level 0) to be in layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL--instead, current layout is VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
The validation error only occurs if this->queueFamilies[PQueueIndex::TRANSFER_QUEUE].index is a different queue family index than this->queueFamilies[PQueueIndex::GRAPHICS_QUEUE].index.
Is it even possible to transfer ownership and transition layout at the same time or would the correct way be to first record a command buffer that only transfers the ownership of the image from the transfer to the graphics queue and then a second one which actually transtitions the layout or should I scrap the whole idea of using a separate transfer queues (for images)?
Ok, I found the solution to my problem.
The documentation states that I have to issue the same pipeline barrier command in the other queue as well after the first barrier was executed, which I completely missed.
So here is a solution that works, although it is far from optimal because it runs synchronously on one thread on the CPU and recreates command buffers everytime I want to transition a layout.
int PGraphicsContext::beginCmdBuffer(VkCommandBuffer *cmdBuffer, const PQueueIndex queueIndex)
{
if (queueIndex != PQueueIndex::GRAPHICS_QUEUE && queueIndex != PQueueIndex::TRANSFER_QUEUE)
return PINE_ERROR_INVALID_ARGUMENT;
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandPool = queueIndex == PQueueIndex::TRANSFER_QUEUE ? this->transferCommandPool : this->graphicsCommandPool;
allocInfo.commandBufferCount = 1;
vkAllocateCommandBuffers(this->device, &allocInfo, cmdBuffer);
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(*cmdBuffer, &beginInfo);
return PINE_SUCCESS;
}
int PGraphicsContext::endCmdBuffer(VkCommandBuffer cmdBuffer, const PQueueIndex queueIndex, VkFence fence, const VkSemaphore *waitSemaphore, VkPipelineStageFlags *waitStageFlags, const VkSemaphore *signalSemaphore)
{
vkEndCommandBuffer(cmdBuffer);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &cmdBuffer;
if (waitSemaphore != nullptr)
{
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphore;
submitInfo.pWaitDstStageMask = waitStageFlags;
}
if (signalSemaphore != nullptr)
{
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphore;
}
vkQueueSubmit(this->queueFamilies[queueIndex].queue, 1, &submitInfo, fence);
return PINE_SUCCESS;
}
int PGraphicsContext::transitionImageLayout(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout)
{
VkCommandBuffer cmdBuffer;
this->beginCmdBuffer(&cmdBuffer);
VkImageMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout;
barrier.image = image;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
{
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, {}, 0, nullptr, 0, nullptr, 1, &barrier);
this->endCmdBuffer(cmdBuffer, PQueueIndex::TRANSFER_QUEUE, this->syncFence);
vkWaitForFences(this->device, 1, &this->syncFence, VK_TRUE, UINT64_MAX);
vkResetFences(this->device, 1, &this->syncFence);
vkFreeCommandBuffers(this->device, this->transferCommandPool, 1, &cmdBuffer);
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
if (this->queueFamilies[PQueueIndex::TRANSFER_QUEUE].index != this->queueFamilies[PQueueIndex::GRAPHICS_QUEUE].index)
{
barrier.dstAccessMask = VK_IMAGE_LAYOUT_UNDEFINED;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.srcQueueFamilyIndex = this->queueFamilies[PQueueIndex::TRANSFER_QUEUE].index;
barrier.dstQueueFamilyIndex = this->queueFamilies[PQueueIndex::GRAPHICS_QUEUE].index;
VkSemaphoreCreateInfo semaphoreInfo{};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
VkSemaphore transferSemaphore;
if (vkCreateSemaphore(this->device, &semaphoreInfo, this->allocator, &transferSemaphore) != VK_SUCCESS)
{
this->endCmdBuffer(cmdBuffer, PQueueIndex::TRANSFER_QUEUE);
return PINE_ERROR_VULKAN_UNSUPPORTED_LAYER_TRANSITION;
}
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, {}, 0, nullptr, 0, nullptr, 1, &barrier);
this->endCmdBuffer(cmdBuffer, PQueueIndex::TRANSFER_QUEUE, VK_NULL_HANDLE, nullptr, nullptr, &transferSemaphore);
barrier.srcAccessMask = VK_IMAGE_LAYOUT_UNDEFINED;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
VkCommandBuffer queueBuffer;
this->beginCmdBuffer(&queueBuffer, PQueueIndex::GRAPHICS_QUEUE);
vkCmdPipelineBarrier(queueBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, {}, 0, nullptr, 0, nullptr, 1, &barrier);
VkPipelineStageFlags flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
this->endCmdBuffer(queueBuffer, PQueueIndex::GRAPHICS_QUEUE, this->syncFence, &transferSemaphore, &flags, nullptr);
vkWaitForFences(this->device, 1, &this->syncFence, VK_TRUE, UINT64_MAX);
vkResetFences(this->device, 1, &this->syncFence);
vkFreeCommandBuffers(this->device, this->transferCommandPool, 1, &cmdBuffer);
vkFreeCommandBuffers(this->device, this->graphicsCommandPool, 1, &queueBuffer);
vkDestroySemaphore(this->device, transferSemaphore, this->allocator);
}
else
{
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, {}, 0, nullptr, 0, nullptr, 1, &barrier);
this->endCmdBuffer(cmdBuffer, PQueueIndex::TRANSFER_QUEUE, this->syncFence);
vkWaitForFences(this->device, 1, &this->syncFence, VK_TRUE, UINT64_MAX);
vkResetFences(this->device, 1, &this->syncFence);
vkFreeCommandBuffers(this->device, this->transferCommandPool, 1, &cmdBuffer);
}
}
else
{
// TODO: implement this
this->endCmdBuffer(cmdBuffer, PQueueIndex::TRANSFER_QUEUE, this->syncFence);
vkWaitForFences(this->device, 1, &this->syncFence, VK_TRUE, UINT64_MAX);
vkResetFences(this->device, 1, &this->syncFence);
vkFreeCommandBuffers(this->device, this->transferCommandPool, 1, &cmdBuffer);
PApplication::getInstance()->getLogger()->error("Failed to transition image layout from 0x%X to 0x%X", oldLayout, newLayout);
return PINE_ERROR_VULKAN_UNSUPPORTED_LAYER_TRANSITION;
}
return PINE_SUCCESS;
}
I have now added the ability to provide a wait and signal semaphore to the queue submit operation when ending a command buffer. In the transitionImageLayout() method I now use this to create a semaphore when I also need to change ownership which is signaled when the transfer queue is done with the pipeline barrier. I then also creates a second command buffer on the graphics queue which waits for the semaphore before it runs the same pipeline barrier command.

My c++ program spend so much CPU?

I have a project that I tried to run and it wasted more than 30% CPU. why?
The code is for a shortcut program and some reminders.
I am using visual studio 2017 c++ windows 10 Core Intel/i7
the command line:
/Yu"stdafx.h" /GS /analyze- /W3 /Zc:wchar_t /ZI /Gm /Od /sdl /Fd"Debug\vc141.pdb" /Zc:inline /fp:precise /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /Fa"Debug\" /EHsc /nologo /Fo"Debug\" /Fp"Debug\Clear.pch" /diagnostics:classic
the code:
#include "stdafx.h"
#include <Windows.h>
#include <shellapi.h>
bool pressed(int key) { return GetAsyncKeyState(key); }
namespace Main {
///to hide the console
void Main()
{
SetWindowPos(GetConsoleWindow(), nullptr, 0, 0, 0, 0, SWP_HIDEWINDOW);
}
///the shortcuts
void Main1() {
while (true) {
///Win-C = chrome
if (pressed(VK_LWIN)&&pressed('C')) system("chrome http://www.google.com");
///Menu = battery message
if (pressed(VK_APPS)) {
SYSTEM_POWER_STATUS a;
GetSystemPowerStatus(&a);
char title[15]; sprintf(title, "%d%% battery%s", a.BatteryLifePercent, a.BatteryFlag & 8 ? ", charging" : "");
char disp[100]; sprintf(disp, "You have %d hours and %d minutes left...", a.BatteryLifeTime / 3600 % 60, a.BatteryLifeTime / 60 % 60);
MessageBoxA(nullptr, disp, title, 0);
}
if (pressed(VK_LWIN) && pressed(VK_DELETE)) SHEmptyRecycleBinA(nullptr, "", 0);
if (pressed(VK_LWIN) && pressed('V')) system("C:\\Users\\steven\\source\\repos\\Clear\\Clear.sln");
if (pressed(VK_LWIN) && pressed('Z')) system("start cmd");
Sleep(GetDoubleClickTime());
}
}
///time
void Main2() {
while (true) {
SYSTEMTIME t;
GetSystemTime(&t);
if (t.wDayOfWeek != 4 && t.wDayOfWeek != 5 && t.wHour == 0 && t.wMinute == 0 && t.wSecond == 0 && t.wMilliseconds == 0) MessageBoxA(nullptr, "Its 00:00", "Sleep", 0);
if (t.wDayOfWeek == 0 && t.wHour == 15 && t.wMinute == 10 && t.wSecond == 0 && t.wMilliseconds == 0) MessageBoxA(nullptr, "Go to the Technion", "תירגול", 0);
if ((t.wDayOfWeek == 1 || t.wDayOfWeek == 2) && t.wHour == 12 && t.wMinute == 25 && t.wSecond == 0 && t.wMilliseconds == 0) MessageBoxA(nullptr, "Go to the lab", "Math is over", 0);
if (t.wDayOfWeek == 3 && t.wHour == 9 && t.wMinute == 35 && t.wSecond == 0 && t.wMilliseconds == 0) MessageBoxA(nullptr, "Go to the class", "Math is over", 0);
if (t.wDayOfWeek == 4 && t.wHour == 10 && t.wMinute == 50 && t.wSecond == 0 && t.wMilliseconds == 0) MessageBoxA(nullptr, "Go to the class", "Math is over", 0);
}
}
///the exit shortcut
void Main0() {
while (true) {
if (pressed(VK_LMENU) && pressed(VK_RMENU)) if (MessageBoxA(nullptr, "Do you want to exit?", "ShortCut", MB_YESNO|MB_ICONINFORMATION) == IDYES) exit(0);
Sleep(GetDoubleClickTime());
}
}
}
#include <thread>
using namespace std;
int main(){
using namespace Main;
thread a[4]={thread(Main), thread(Main0), thread(Main1), thread(Main2)};
for(thread& b:a) b.join();
return 0;}
Main2() is very processor intensive, as it's a tight loop.
As a crude fix, consider a Sleep on that thread too.
The correct way to find out is with a profiller; visual studio has one built in which you should get some practice with; since it would not only highlight your high CPU; but also which thread.
Knowing which thread, in this example, would be enough information to answer your question. If you plan to write threaded code you should get to grips with more of the tools in VS since threading gets very complex, very fast.

Opengl 4 debug output does not work

I am writing a game. I use ArchLinux most of time but I have tried to run my game on the Ubuntu 16.04 recently. On Ubuntu 16.04 there is a strange error: 1280. It is too difficult to find what causes the error so I wanted to see opengl's debug output but I don't see it too. I noticed one thing during shader validation - validation seems to be unsuccessful but the log is empty:
GLint status;
glValidateProgram(program_);
glGetProgramiv(program_, GL_VALIDATE_STATUS, &status);
if (status == GL_TRUE) {
return;
}
// Store log and return false
int length = 0;
glGetProgramiv(program_, GL_INFO_LOG_LENGTH, &length);
if (length > 0) {
GLchar infoLog[512];
glGetProgramInfoLog(program_, 512, nullptr, infoLog);
throw std::runtime_error(std::string("Program failed to validate:") + infoLog);
} else {
throw std::runtime_error(std::string("Program failed to validate. Unknown error"));
}
This gives me Unknown error. Also the opengl's debug output can't be seen, however, user messages are written there successfully. Here is the code:
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
int contextFlags = 0;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &contextFlags);
contextFlags |= SDL_GL_CONTEXT_DEBUG_FLAG;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, contextFlags);
sdlWindow_ = SDL_CreateWindow(title.c_str(),
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
0,
0,
SDL_WINDOW_OPENGL
| SDL_WINDOW_SHOWN
| SDL_WINDOW_FULLSCREEN_DESKTOP
| SDL_WINDOW_INPUT_GRABBED);
if (!sdlWindow_) {
throw std::runtime_error("Unable to create window");
}
SDL_Log("Window created");
glContext_ = SDL_GL_CreateContext(sdlWindow_);
if (!glContext_) {
throw std::runtime_error("Failed to init OpenGL");
}
SDL_Log("GL context created");
{
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (err != GLEW_OK) {
throw std::runtime_error(std::string("GLEW Error: ") + reinterpret_cast<const char*>(glewGetErrorString(err)));
}
}
if (glDebugMessageCallbackARB != nullptr) {
SDL_Log("GL debug is available.\n");
// Enable the debug callback
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(_openglDebugCallbackFunction, nullptr);
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0,
GL_DEBUG_SEVERITY_NOTIFICATION, -1 , "Started debugging");
} else {
SDL_Log("GL debug is not available.\n");
}
So the main question here is why I can't see the opengl's debug output. And, if it is possible, as an additional question, why does the shader validation fail without a log?
GLEW 1.x has some problems when beeing used in a core context (that's also why glewExperimental=true is needed). glewInit always generates an OpenGL error while loading the extensions. You don't get this error through the debug callback because the initialization of the callback happens after the point where the error happend.
You have kind of a chicken-egg problem here: You cannot setup the debug callback before initializing GLEW, but that's where you want to get the debug output from. I recommend calling glGetError() right after glewInit to get rid of the one error you know where it is coming from.

Compilation error compiling Qt with icpc on Ubuntu 14.04

I am trying to compile Qt with Intel icpc on Ubuntu 14.04 and I get a compilation error on this file - qpnghandler.cpp
From the qpnghandler.cpp file that I have this is the relevant code -
static
void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float screen_gamma=0.0)
{
if (screen_gamma != 0.0 && png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) {
double file_gamma;
png_get_gAMA(png_ptr, info_ptr, &file_gamma);
png_set_gamma(png_ptr, screen_gamma, file_gamma);
}
png_uint_32 width;
png_uint_32 height;
int bit_depth;
int color_type;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
if (color_type == PNG_COLOR_TYPE_GRAY) {
// Black & White or 8-bit grayscale
if (bit_depth == 1 && info_ptr->channels == 1) {
png_set_invert_mono(png_ptr);
png_read_update_info(png_ptr, info_ptr);
if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) {
image = QImage(width, height, QImage::Format_Mono);
if (image.isNull())
return;
}
image.setColorCount(2);
image.setColor(1, qRgb(0,0,0));
image.setColor(0, qRgb(255,255,255));
} else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_set_expand(png_ptr);
png_set_strip_16(png_ptr);
png_set_gray_to_rgb(png_ptr);
if (image.size() != QSize(width, height) || image.format() != QImage::Format_ARGB32) {
image = QImage(width, height, QImage::Format_ARGB32);
if (image.isNull())
return;
}
if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
png_set_swap_alpha(png_ptr);
png_read_update_info(png_ptr, info_ptr);
} else {
if (bit_depth == 16)
png_set_strip_16(png_ptr);
else if (bit_depth < 8)
png_set_packing(png_ptr);
int ncols = bit_depth < 8 ? 1 << bit_depth : 256;
png_read_update_info(png_ptr, info_ptr);
if (image.size() != QSize(width, height) || image.format() != QImage::Format_Indexed8) {
image = QImage(width, height, QImage::Format_Indexed8);
if (image.isNull())
return;
}
image.setColorCount(ncols);
for (int i=0; i<ncols; i++) {
int c = i*255/(ncols-1);
image.setColor(i, qRgba(c,c,c,0xff));
}
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
const int g = info_ptr->trans_values.gray;
#else
const int g = info_ptr->trans_color.gray;
#endif
if (g < ncols) {
image.setColor(g, 0);
}
}
}
} else if (color_type == PNG_COLOR_TYPE_PALETTE
&& png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
&& info_ptr->num_palette <= 256)
{
// 1-bit and 8-bit color
if (bit_depth != 1)
png_set_packing(png_ptr);
png_read_update_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
QImage::Format format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
if (image.size() != QSize(width, height) || image.format() != format) {
image = QImage(width, height, format);
if (image.isNull())
return;
}
image.setColorCount(info_ptr->num_palette);
int i = 0;
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
while (i < info_ptr->num_trans) {
image.setColor(i, qRgba(
info_ptr->palette[i].red,
info_ptr->palette[i].green,
info_ptr->palette[i].blue,
#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
info_ptr->trans[i]
#else
info_ptr->trans_alpha[i]
#endif
)
);
i++;
}
}
while (i < info_ptr->num_palette) {
image.setColor(i, qRgba(
info_ptr->palette[i].red,
info_ptr->palette[i].green,
info_ptr->palette[i].blue,
0xff
)
);
i++;
}
} else {
// 32-bit
if (bit_depth == 16)
png_set_strip_16(png_ptr);
png_set_expand(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
QImage::Format format = QImage::Format_ARGB32;
// Only add filler if no alpha, or we can get 5 channel data.
if (!(color_type & PNG_COLOR_MASK_ALPHA)
&& !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_set_filler(png_ptr, 0xff, QSysInfo::ByteOrder == QSysInfo::BigEndian ?
PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
// We want 4 bytes, but it isn't an alpha channel
format = QImage::Format_RGB32;
}
if (image.size() != QSize(width, height) || image.format() != format) {
image = QImage(width, height, format);
if (image.isNull())
return;
}
if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
png_set_swap_alpha(png_ptr);
png_read_update_info(png_ptr, info_ptr);
}
// Qt==ARGB==Big(ARGB)==Little(BGRA)
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
png_set_bgr(png_ptr);
}
}
Can somebody guide me on what modifications I can bring to that file so that I can compile qpnghandler.cpp ?
icpc -c -wd654,1572 -g -pthread -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -O2 -fvisibility=hidden -fvisibility-inlines-hidden -D_REENTRANT -I/usr/include/freetype2 -fPIC -DQT_SHARED -DQT_BUILD_GUI_LIB -DQT_NO_USING_NAMESPACE -DQT_NO_CAST_TO_ASCII -DQT_ASCII_CAST_WARNINGS -DQT3_SUPPORT -DQT_MOC_COMPAT -DQT_HAVE_MMX -DQT_HAVE_SSE -DQT_HAVE_MMXEXT -DQT_HAVE_SSE2 -DQT_NO_OPENTYPE -DQT_NO_STYLE_MAC -DQT_NO_STYLE_WINDOWSVISTA -DQT_NO_STYLE_WINDOWSXP -DQT_NO_STYLE_WINDOWSCE -DQT_NO_STYLE_WINDOWSMOBILE -DQT_NO_STYLE_S60 -DQ_INTERNAL_QAPP_SRC -DQT_NO_DEBUG -DQT_CORE_LIB -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -I../../mkspecs/linux-icc -I. -I../../include/QtCore -I../../include -I../../include/QtGui -I.rcc/release-shared -I../3rdparty/xorg -I/usr/include/freetype2 -I../3rdparty/harfbuzz/src -Idialogs -I.moc/release-shared -I/usr/X11R6/include -I.uic/release-shared -o .obj/release-shared/qpnghandler.o image/qpnghandler.cpp
image/qpnghandler.cpp(169): error: pointer to incomplete class type is not allowed
if (bit_depth == 1 && info_ptr->channels == 1) {
^
image/qpnghandler.cpp(214): error: pointer to incomplete class type is not allowed
const int g = info_ptr->trans_color.gray;
^
image/qpnghandler.cpp(223): error: pointer to incomplete class type is not allowed
&& info_ptr->num_palette <= 256)
^
image/qpnghandler.cpp(236): error: pointer to incomplete class type is not allowed
image.setColorCount(info_ptr->num_palette);
^
image/qpnghandler.cpp(239): error: pointer to incomplete class type is not allowed
while (i < info_ptr->num_trans) {
^
image/qpnghandler.cpp(241): error: pointer to incomplete class type is not allowed
info_ptr->palette[i].red,
^
image/qpnghandler.cpp(242): error: pointer to incomplete class type is not allowed
info_ptr->palette[i].green,
^
TL;DR: you're compiling an ancient Qt against a new libpng. This new libpng has changed its API in an incompatible way. Newer Qt supports this newer libpng just fine.
Qt 4.6 was released in 2009. If you're for some reason stuck with Qt 4.x, you should definitely use the 4.8 branch -- because it contains security and portability fixes like the one which solves the problem that you're hitting. However, upstream support for the 4.x branch of Qt has ended, so you should probably look into porting your code to Qt 5.x if you're actively working on this project (and if you expect to continue working on it in future).
If you desperately want to create a Frankenstein build of Qt 4.6 for some reason (maybe you're bisecting a tricky error in Qt 4 and want to reach back seven years into the history to see if that version was buggy, too), you should look into using the 1.4 branch of libpng. If that is not possible for you for some reason, then you can carefully port the Qt's PNG code to the API of libpng-1.5 or libpng-1.6. Details on how to do this are available at libpng 1.5.10 error: dereferencing pointer to incomplete type.