Hi! I’m trying to implement SFML classes with vulkan, everything worked fine when I encounter a problem when entering to this function which seems to copy a texture to a new one two times bigger :
int rowHeight = height + height / 10;
while ((page.nextRow + rowHeight >= page.texture.getSize().y()) || (width >= page.texture.getSize().x()))
{
// Not enough space: resize the texture if possible
unsigned int textureWidth = page.texture.getSize().x();
unsigned int textureHeight = page.texture.getSize().y();
if ((textureWidth * 2 <= page.texture.getMaximumSize()) && (textureHeight * 2 <= page.texture.getMaximumSize()))
{
//std::cout<<"find glyph rect"<<std::endl;
// Make the texture 2 times bigger
Texture newTexture(vkDevice);
newTexture.create(textureWidth * 2, textureHeight * 2);
newTexture.update(page.texture);
newTexture.setSmooth(true);
page.texture.swap(newTexture);
}
else
{
// Oops, we've reached the maximum texture size...
std::cerr << "Failed to add a new character to the font: the maximum texture size has been reached" << std::endl;
return IntRect(0, 0, 2, 2);
}
}
The problem is when I’m trying to blit the texture image nothing is blitted and I have black squares intead of the text…
Here is the function which is sensed to blit the texture :
void Texture::update(const Texture& texture, unsigned int x, unsigned int y) {
VkImageBlit2 blitRegion{ .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2, .pNext = nullptr };
blitRegion.srcOffsets[0].x = 0;
blitRegion.srcOffsets[0].y = 0;
blitRegion.srcOffsets[0].z = 0;
blitRegion.srcOffsets[1].x = texture.m_size.x();
blitRegion.srcOffsets[1].y = texture.m_size.y();
blitRegion.srcOffsets[1].z = 1;
blitRegion.dstOffsets[0].x = x;
blitRegion.dstOffsets[0].y = y;
blitRegion.dstOffsets[0].z = 0;
blitRegion.dstOffsets[1].x = x + texture.m_size.x();
blitRegion.dstOffsets[1].y = y + texture.m_size.y();
blitRegion.dstOffsets[1].z = 1;
blitRegion.srcSubresource.aspectMask = texture.imageAspectFlags;
blitRegion.srcSubresource.baseArrayLayer = 0;
blitRegion.srcSubresource.layerCount = 1;
blitRegion.srcSubresource.mipLevel = 0;
blitRegion.dstSubresource.aspectMask = imageAspectFlags;
blitRegion.dstSubresource.baseArrayLayer = 0;
blitRegion.dstSubresource.layerCount = 1;
blitRegion.dstSubresource.mipLevel = 0;
VkBlitImageInfo2 blitInfo{ .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2, .pNext = nullptr };
blitInfo.dstImage = textureImage;
blitInfo.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
blitInfo.srcImage = texture.textureImage;
blitInfo.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
blitInfo.filter = VK_FILTER_LINEAR;
blitInfo.regionCount = 1;
blitInfo.pRegions = &blitRegion;
VkCommandBuffer cmd = beginSingleTimeCommands();
transitionImageLayout(cmd, texture.textureImage, m_format, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
transitionImageLayout(cmd, textureImage, m_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
vkCmdBlitImage2(cmd, &blitInfo);
transitionImageLayout(cmd, texture.textureImage, m_format, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
transitionImageLayout(cmd, textureImage, m_format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
endSingleTimeCommands(cmd);
}
I really doesn’t understand why it’s not blitting my image and why I get black squares instead of the text…, probably I made something wrong it’s quite improbable it’s a driver issue but…, I do the same things with opengl and I’ve no problems with glBlitFrameBuffers :
////////////////////////////////////////////////////////////
void Texture::update(Texture texture, unsigned int x, unsigned int y)
{
GLint readFramebuffer = 0;
GLint drawFramebuffer = 0;
glCheck(glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &readFramebuffer));
glCheck(glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFramebuffer));
// Create the framebuffers
GLuint sourceFrameBuffer = 0;
GLuint destFrameBuffer = 0;
glCheck(glGenFramebuffers(1, &sourceFrameBuffer));
glCheck(glGenFramebuffers(1, &destFrameBuffer));
if (!sourceFrameBuffer || !destFrameBuffer)
{
std::cerr << "Cannot copy texture, failed to create a frame buffer object" << std::endl;
return;
}
// Link the source texture to the source frame buffer
glCheck(glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFrameBuffer));
glCheck(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.m_texture, 0));
// Link the destination texture to the destination frame buffer
glCheck(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destFrameBuffer));
glCheck(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0));
// A final check, just to be sure...
GLenum sourceStatus;
glCheck(sourceStatus = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
GLenum destStatus;
glCheck(destStatus = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
if ((sourceStatus == GL_FRAMEBUFFER_COMPLETE) && (destStatus == GL_FRAMEBUFFER_COMPLETE))
{
// Blit the texture contents from the source to the destination texture
glCheck(glBlitFramebuffer(
0, texture.m_pixelsFlipped ? texture.m_size.y() : 0, texture.m_size.x(), texture.m_pixelsFlipped ? 0 : texture.m_size.y(), // Source rectangle, flip y if source is flipped
x, y, x + texture.m_size.x(), y + texture.m_size.y(), // Destination rectangle
GL_COLOR_BUFFER_BIT, GL_NEAREST
));
}
else
{
std::cerr << "Cannot copy texture, failed to link texture to frame buffer" << std::endl;
}
// Restore previously bound framebuffers
glCheck(glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer));
glCheck(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFramebuffer));
// Delete the framebuffers
glCheck(glDeleteFramebuffers(1, &sourceFrameBuffer));
glCheck(glDeleteFramebuffers(1, &destFrameBuffer));
// Make sure that the current texture binding will be preserved
priv::TextureSaver save;
// Set the parameters of this texture
glCheck(glBindTexture(GL_TEXTURE_2D, m_texture));
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
m_pixelsFlipped = false;
m_cacheId = getUniqueId();
// Force an OpenGL flush, so that the texture data will appear updated
// in all contexts immediately (solves problems in multi-threaded apps)
glCheck(glFlush());
return;
What I’m messed up with ?
Thanks.