From 72abfdc8a431b315fd5368710518a715bda383df Mon Sep 17 00:00:00 2001 From: Rinthel Date: Sun, 4 Aug 2019 12:16:45 +0900 Subject: [PATCH] implement framebuffer / mipmap / cached sampler - fix texture mipmap setting / texture update bug - implement framebuffer - fix image memory barrier bug - vkstruct explicit initialization - sampler caching --- src/renderer_vk.cpp | 531 ++++++++++++++++++++++++++++++++------------ src/renderer_vk.h | 18 +- 2 files changed, 403 insertions(+), 146 deletions(-) diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index 71fbfb727..51fcac6f1 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -684,7 +684,7 @@ VK_IMPORT_DEVICE } } - void setImageMemoryBarrier(VkCommandBuffer _commandBuffer, VkImage _image, VkImageLayout _oldLayout, VkImageLayout _newLayout, uint32_t levelCount, uint32_t layerCount) + void setImageMemoryBarrier(VkCommandBuffer _commandBuffer, VkImage _image, VkImageAspectFlags _aspectMask, VkImageLayout _oldLayout, VkImageLayout _newLayout, uint32_t _levelCount, uint32_t _layerCount) { BX_CHECK(true && _newLayout != VK_IMAGE_LAYOUT_UNDEFINED @@ -694,7 +694,6 @@ VK_IMPORT_DEVICE VkAccessFlags srcAccessMask = 0; VkAccessFlags dstAccessMask = 0; - VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; switch (_oldLayout) { @@ -753,7 +752,7 @@ VK_IMPORT_DEVICE case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + // aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; break; case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: @@ -792,11 +791,11 @@ VK_IMPORT_DEVICE imb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; imb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; imb.image = _image; - imb.subresourceRange.aspectMask = aspectMask; + imb.subresourceRange.aspectMask = _aspectMask; imb.subresourceRange.baseMipLevel = 0; - imb.subresourceRange.levelCount = levelCount; + imb.subresourceRange.levelCount = _levelCount; imb.subresourceRange.baseArrayLayer = 0; - imb.subresourceRange.layerCount = layerCount; + imb.subresourceRange.layerCount = _layerCount; vkCmdPipelineBarrier(_commandBuffer , VK_PIPELINE_STAGE_ALL_COMMANDS_BIT , VK_PIPELINE_STAGE_ALL_COMMANDS_BIT @@ -1189,7 +1188,7 @@ VK_IMPORT_INSTANCE , NULL ); - VkQueueFamilyProperties queueFamilyPropertices[10] = {}; + VkQueueFamilyProperties queueFamilyPropertices[10]; queueFamilyPropertyCount = bx::min(queueFamilyPropertyCount, BX_COUNTOF(queueFamilyPropertices) ); vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice , &queueFamilyPropertyCount @@ -1868,6 +1867,7 @@ VK_IMPORT_DEVICE setImageMemoryBarrier( commandBuffer , m_backBufferDepthStencilImage + , VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT , VK_IMAGE_LAYOUT_UNDEFINED , VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL , 1 @@ -1879,6 +1879,7 @@ VK_IMPORT_DEVICE setImageMemoryBarrier( commandBuffer , m_backBufferColorImage[ii] + , VK_IMAGE_ASPECT_COLOR_BIT , VK_IMAGE_LAYOUT_UNDEFINED , VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL , 1 @@ -1892,6 +1893,7 @@ VK_IMPORT_DEVICE setImageMemoryBarrier( commandBuffer , m_backBufferColorImage[ii] + , VK_IMAGE_ASPECT_COLOR_BIT , VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL , VK_IMAGE_LAYOUT_PRESENT_SRC_KHR , 1 @@ -2108,6 +2110,8 @@ VK_IMPORT_DEVICE m_pipelineStateCache.invalidate(); m_descriptorSetLayoutCache.invalidate(); + m_renderPassCache.invalidate(); + m_samplerCache.invalidate(); for (uint32_t ii = 0; ii < BX_COUNTOF(m_scratchBuffer); ++ii) { @@ -2346,16 +2350,18 @@ VK_IMPORT_DEVICE m_textures[_handle.idx].destroy(); } - void createFrameBuffer(FrameBufferHandle /*_handle*/, uint8_t /*_num*/, const Attachment* /*_attachment*/) override + void createFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const Attachment* _attachment) override { + m_frameBuffers[_handle.idx].create(_num, _attachment); } void createFrameBuffer(FrameBufferHandle /*_handle*/, void* /*_nwh*/, uint32_t /*_width*/, uint32_t /*_height*/, TextureFormat::Enum /*_format*/, TextureFormat::Enum /*_depthFormat*/) override { } - void destroyFrameBuffer(FrameBufferHandle /*_handle*/) override + void destroyFrameBuffer(FrameBufferHandle _handle) override { + m_frameBuffers[_handle.idx].destroy(); } void createUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) override @@ -2609,21 +2615,21 @@ VK_IMPORT_DEVICE const FrameBufferVK& frameBuffer = m_frameBuffers[m_fbh.idx]; BX_UNUSED(frameBuffer); -// for (uint8_t ii = 0, num = frameBuffer.m_num; ii < num; ++ii) -// { -// TextureVK& texture = m_textures[frameBuffer.m_texture[ii].idx]; -// texture.setState(m_commandList, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); -// } -// -// if (isValid(frameBuffer.m_depth) ) -// { -// TextureVK& texture = m_textures[frameBuffer.m_depth.idx]; -// const bool writeOnly = 0 != (texture.m_flags&BGFX_TEXTURE_RT_WRITE_ONLY); -// if (!writeOnly) -// { -// texture.setState(m_commandList, D3D12_RESOURCE_STATE_DEPTH_READ); -// } -// } + for (uint8_t ii = 0, num = frameBuffer.m_num; ii < num; ++ii) + { + TextureVK& texture = m_textures[frameBuffer.m_texture[ii].idx]; + texture.setImageMemoryBarrier(m_commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + } + + if (isValid(frameBuffer.m_depth) ) + { + TextureVK& texture = m_textures[frameBuffer.m_depth.idx]; + const bool writeOnly = 0 != (texture.m_flags&BGFX_TEXTURE_RT_WRITE_ONLY); + if (!writeOnly) + { + texture.setImageMemoryBarrier(m_commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + } + } } if (!isValid(_fbh) ) @@ -2669,15 +2675,13 @@ VK_IMPORT_DEVICE for (uint8_t ii = 0, num = frameBuffer.m_num; ii < num; ++ii) { TextureVK& texture = m_textures[frameBuffer.m_texture[ii].idx]; - BX_UNUSED(texture); -// texture.setState(m_commandList, D3D12_RESOURCE_STATE_RENDER_TARGET); + texture.setImageMemoryBarrier(m_commandBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); } if (isValid(frameBuffer.m_depth) ) { TextureVK& texture = m_textures[frameBuffer.m_depth.idx]; - BX_UNUSED(texture); -// texture.setState(m_commandList, D3D12_RESOURCE_STATE_DEPTH_WRITE); + texture.setImageMemoryBarrier(m_commandBuffer, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); } // m_commandList->OMSetRenderTargets(frameBuffer.m_num @@ -2691,8 +2695,8 @@ VK_IMPORT_DEVICE // m_rtMsaa = _msaa; } - void setBlendState(VkPipelineColorBlendStateCreateInfo& _desc, uint64_t _state, uint32_t _rgba = 0) - { + void setBlendState(VkPipelineColorBlendStateCreateInfo& _desc, uint64_t _state, uint32_t _rgba = 0) + { VkPipelineColorBlendAttachmentState* bas = const_cast(_desc.pAttachments); uint8_t writeMask = 0; @@ -2874,6 +2878,198 @@ VK_IMPORT_DEVICE return num; } + uint32_t getRenderPassHashkey(uint8_t _num, const Attachment* attachments) + { + if (_num == 0) + return 0; + bx::HashMurmur2A hash; + hash.begin(0); + for (uint8_t ii = 0; ii < _num; ++ii) + { + hash.add(attachments[ii].access); + hash.add(attachments[ii].layer); + hash.add(attachments[ii].mip); + hash.add(attachments[ii].resolve); + + TextureVK& texture = m_textures[attachments[ii].handle.idx]; + hash.add(texture.m_textureFormat); + } + return hash.end(); + } + + VkRenderPass getRenderPass(uint8_t _num, const Attachment* _attachments) + { + VkRenderPass renderPass = VK_NULL_HANDLE; + uint32_t hashKey = getRenderPassHashkey(_num, _attachments); + renderPass = (VkRenderPass)m_renderPassCache.find(hashKey); + if (renderPass != VK_NULL_HANDLE) + return renderPass; + + // cache missed + VkAttachmentDescription ad[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; + VkAttachmentReference colorAr[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; + VkAttachmentReference resolveAr; + VkAttachmentReference depthAr; + uint32_t numColorAr = 0; + + resolveAr.attachment = VK_ATTACHMENT_UNUSED; + resolveAr.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + depthAr.attachment = VK_ATTACHMENT_UNUSED; + depthAr.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + for (uint8_t ii = 0; ii < _num; ++ii) + { + TextureVK& texture = m_textures[_attachments[ii].handle.idx]; + ad[ii].flags = 0; + ad[ii].format = texture.m_vkTextureFormat; + ad[ii].samples = VK_SAMPLE_COUNT_1_BIT; + ad[ii].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + ad[ii].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + ad[ii].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + ad[ii].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + ad[ii].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + if (texture.m_vkTextureAspect & VK_IMAGE_ASPECT_COLOR_BIT) + { + ad[ii].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorAr[numColorAr].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorAr[numColorAr].attachment = ii; + numColorAr++; + } + else if (texture.m_vkTextureAspect & VK_IMAGE_ASPECT_DEPTH_BIT) + { + ad[ii].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depthAr.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depthAr.attachment = ii; + } + } + + VkSubpassDescription sd[1]; + sd[0].flags = 0; + sd[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + sd[0].inputAttachmentCount = 0; + sd[0].pInputAttachments = NULL; + sd[0].colorAttachmentCount = numColorAr; + sd[0].pColorAttachments = colorAr; + sd[0].pResolveAttachments = &resolveAr; + sd[0].pDepthStencilAttachment = &depthAr; + sd[0].preserveAttachmentCount = 0; + sd[0].pPreserveAttachments = NULL; + + VkRenderPassCreateInfo rpi; + rpi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + rpi.pNext = NULL; + rpi.flags = 0; + rpi.attachmentCount = _num; + rpi.pAttachments = ad; + rpi.subpassCount = BX_COUNTOF(sd); + rpi.pSubpasses = sd; + rpi.dependencyCount = 0; + rpi.pDependencies = NULL; + + VK_CHECK( vkCreateRenderPass(m_device, &rpi, m_allocatorCb, &renderPass) ); + + m_renderPassCache.add(hashKey, renderPass); + return renderPass; + } + + VkSampler getSampler(uint32_t _samplerFlags, uint32_t _mipLevels) + { + bx::HashMurmur2A hash; + hash.add(_samplerFlags); + hash.add(_mipLevels); + uint32_t hashKey = hash.end(); + + VkSampler sampler = m_samplerCache.find(hashKey); + if (sampler != VK_NULL_HANDLE) + return sampler; + + // set default sampler + VkSamplerCreateInfo samplerInfo; + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.pNext = NULL; + samplerInfo.flags = 0; + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.mipLodBias = 0.0f; + samplerInfo.anisotropyEnable = VK_FALSE; + samplerInfo.maxAnisotropy = 0; // TODO + samplerInfo.compareEnable = VK_FALSE; + samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; + samplerInfo.minLod = 0.0f; + samplerInfo.maxLod = (float)_mipLevels; + samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + samplerInfo.unnormalizedCoordinates = VK_FALSE; + + if (0 == (_samplerFlags & BGFX_SAMPLER_INTERNAL_DEFAULT)) + { + switch (_samplerFlags & BGFX_SAMPLER_MAG_MASK) + { + case BGFX_SAMPLER_MAG_POINT: samplerInfo.magFilter = VK_FILTER_NEAREST; break; + case BGFX_SAMPLER_MAG_ANISOTROPIC: samplerInfo.anisotropyEnable = VK_TRUE; break; + } + + switch (_samplerFlags & BGFX_SAMPLER_MIN_MASK) + { + case BGFX_SAMPLER_MIN_POINT: samplerInfo.minFilter = VK_FILTER_NEAREST; break; + case BGFX_SAMPLER_MIN_ANISOTROPIC: samplerInfo.anisotropyEnable = VK_TRUE; break; + } + + switch (_samplerFlags & BGFX_SAMPLER_U_MASK) + { + case BGFX_SAMPLER_U_MIRROR: samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; break; + case BGFX_SAMPLER_U_CLAMP: samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; break; + case BGFX_SAMPLER_U_BORDER: samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; break; + } + + switch (_samplerFlags & BGFX_SAMPLER_V_MASK) + { + case BGFX_SAMPLER_V_MIRROR: samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; break; + case BGFX_SAMPLER_V_CLAMP: samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; break; + case BGFX_SAMPLER_V_BORDER: samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; break; + } + + switch (_samplerFlags & BGFX_SAMPLER_W_MASK) + { + case BGFX_SAMPLER_W_MIRROR: samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; break; + case BGFX_SAMPLER_W_CLAMP: samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; break; + case BGFX_SAMPLER_W_BORDER: samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; break; + } + + if (0 != (_samplerFlags & BGFX_SAMPLER_COMPARE_MASK)) + { + samplerInfo.compareEnable = VK_TRUE; + switch (_samplerFlags & BGFX_SAMPLER_COMPARE_MASK) + { + case BGFX_SAMPLER_COMPARE_LESS: samplerInfo.compareOp = VK_COMPARE_OP_LESS; break; + case BGFX_SAMPLER_COMPARE_LEQUAL: samplerInfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL; break; + case BGFX_SAMPLER_COMPARE_EQUAL: samplerInfo.compareOp = VK_COMPARE_OP_EQUAL; break; + case BGFX_SAMPLER_COMPARE_GEQUAL: samplerInfo.compareOp = VK_COMPARE_OP_GREATER_OR_EQUAL; break; + case BGFX_SAMPLER_COMPARE_GREATER: samplerInfo.compareOp = VK_COMPARE_OP_GREATER; break; + case BGFX_SAMPLER_COMPARE_NOTEQUAL: samplerInfo.compareOp = VK_COMPARE_OP_NOT_EQUAL; break; + case BGFX_SAMPLER_COMPARE_NEVER: samplerInfo.compareOp = VK_COMPARE_OP_NEVER; break; + case BGFX_SAMPLER_COMPARE_ALWAYS: samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; break; + } + } + + uint32_t borderColor = ((_samplerFlags & BGFX_SAMPLER_BORDER_COLOR_MASK) >> BGFX_SAMPLER_BORDER_COLOR_SHIFT); + if (borderColor > 0) + { + // TODO: set borderColor properly + samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_WHITE; + } + } + + VK_CHECK(vkCreateSampler(m_device, &samplerInfo, m_allocatorCb, &sampler)); + + m_samplerCache.add(hashKey, sampler); + return sampler; + } + VkPipeline getPipeline(ProgramHandle _program) { BX_UNUSED(_program); @@ -3028,7 +3224,7 @@ VK_IMPORT_DEVICE graphicsPipeline.pDynamicState = &dynamicState; // graphicsPipeline.layout = m_pipelineLayout; graphicsPipeline.layout = program.m_pipelineLayout; - graphicsPipeline.renderPass = m_renderPass; + graphicsPipeline.renderPass = isValid(m_fbh) ? m_frameBuffers[m_fbh.idx].m_renderPass : m_renderPass; graphicsPipeline.subpass = 0; graphicsPipeline.basePipelineHandle = VK_NULL_HANDLE; graphicsPipeline.basePipelineIndex = 0; @@ -3189,12 +3385,12 @@ VK_IMPORT_DEVICE rect[0].layerCount = 1; uint32_t numMrt = 1; -// FrameBufferHandle fbh = m_fbh; -// if (isValid(fbh) ) -// { -// const FrameBufferVK& fb = m_frameBuffers[fbh.idx]; -// numMrt = bx::max(1, fb.m_num); -// } + FrameBufferHandle fbh = m_fbh; + if (isValid(fbh) ) + { + const FrameBufferVK& fb = m_frameBuffers[fbh.idx]; + numMrt = bx::max((uint8_t)1, fb.m_num); + } VkClearAttachment attachments[BGFX_CONFIG_MAX_FRAME_BUFFERS]; uint32_t mrt = 0; @@ -3246,12 +3442,15 @@ VK_IMPORT_DEVICE ++mrt; } - vkCmdClearAttachments(m_commandBuffer - , mrt - , attachments - , BX_COUNTOF(rect) - , rect - ); + if (mrt > 0) + { + vkCmdClearAttachments(m_commandBuffer + , mrt + , attachments + , BX_COUNTOF(rect) + , rect + ); + } } uint64_t kick(VkSemaphore _wait = VK_NULL_HANDLE, VkSemaphore _signal = VK_NULL_HANDLE) @@ -3403,6 +3602,8 @@ VK_IMPORT_DEVICE StateCacheT m_pipelineStateCache; StateCacheT m_descriptorSetLayoutCache; + StateCacheT m_renderPassCache; + StateCacheT m_samplerCache; Resolution m_resolution; uint32_t m_maxAnisotropy; @@ -3743,10 +3944,10 @@ VK_DESTROY VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand(); // copy buffer to buffer { - VkBufferCopy region = {}; + VkBufferCopy region; region.srcOffset = 0; region.dstOffset = 0; - region.size = _size; + region.size = _size; vkCmdCopyBuffer(commandBuffer, stagingBuffer, m_buffer, 1, ®ion); } @@ -3816,10 +4017,10 @@ VK_DESTROY VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand(); // copy buffer to buffer { - VkBufferCopy region = {}; + VkBufferCopy region; region.srcOffset = 0; region.dstOffset = _offset; - region.size = _size; + region.size = _size; vkCmdCopyBuffer(commandBuffer, stagingBuffer, m_buffer, 1, ®ion); } @@ -3903,7 +4104,12 @@ VK_DESTROY uint8_t fragmentBit = fragment ? BGFX_UNIFORM_FRAGMENTBIT : 0; - bx::memSet(m_sampler, 0, sizeof(SamplerInfo) * BX_COUNTOF(m_sampler)); + for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++ii) + { + m_sampler[ii].uniformHandle = {kInvalidHandle}; + m_sampler[ii].imageBinding = 0; + m_sampler[ii].samplerBinding = 0; + } if (0 < count) { for (uint32_t ii = 0; ii < count; ++ii) @@ -3962,7 +4168,6 @@ VK_DESTROY m_sampler[num].uniformHandle = info->m_handle; m_sampler[num].imageBinding = regIndex; // regIndex is used for image binding index m_sampler[num].samplerBinding = regCount; // regCount is used for sampler binding index - m_numSamplers++; kind = "sampler"; } @@ -4206,11 +4411,13 @@ VK_DESTROY m_textureFormat = uint8_t(getViableTextureFormat(imageContainer)); const bool convert = m_textureFormat != m_requestedFormat; const uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat)); - VkImageAspectFlags aspectFlag = bimg::isDepth((bimg::TextureFormat::Enum)m_textureFormat) + m_vkTextureAspect = bimg::isDepth((bimg::TextureFormat::Enum)m_textureFormat) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT ; - VkFormat textureFormat = bimg::isDepth((bimg::TextureFormat::Enum)m_textureFormat) + if (m_textureFormat == TextureFormat::D0S8 || m_textureFormat == TextureFormat::D24S8) + m_vkTextureAspect |= VK_IMAGE_ASPECT_STENCIL_BIT; + m_vkTextureFormat = bimg::isDepth((bimg::TextureFormat::Enum)m_textureFormat) ? s_textureFormat[m_textureFormat].m_fmtDsv : s_textureFormat[m_textureFormat].m_fmt ; @@ -4229,6 +4436,7 @@ VK_DESTROY } m_numMips = ti.numMips; + m_numSides = ti.numLayers * (imageContainer.m_cubeMap ? 6 : 1); const uint16_t numSides = ti.numLayers * (imageContainer.m_cubeMap ? 6 : 1); const uint32_t numSrd = numSides * ti.numMips; @@ -4267,7 +4475,7 @@ VK_DESTROY ImageInfo* imageInfos = (ImageInfo*)BX_ALLOC(g_allocator, sizeof(ImageInfo) * numSrd); bx::memSet(imageInfos, 0, sizeof(ImageInfo) * numSrd); - uint32_t alignment = 256; + uint32_t alignment = 1; // tightly aligned buffer for (uint8_t side = 0; side < numSides; ++side) { for (uint8_t lod = 0; lod < ti.numMips; ++lod) @@ -4360,15 +4568,17 @@ VK_DESTROY VkBufferImageCopy* bufferCopyInfo = (VkBufferImageCopy*)BX_ALLOC(g_allocator, sizeof(VkBufferImageCopy) * numSrd); for (uint32_t ii = 0; ii < numSrd; ++ii) { - bufferCopyInfo[ii].bufferOffset = totalMemSize; - bufferCopyInfo[ii].bufferImageHeight = 0; - bufferCopyInfo[ii].bufferRowLength = 0; - bufferCopyInfo[ii].imageOffset = { 0, 0, 0 }; - bufferCopyInfo[ii].imageExtent = { imageInfos[ii].width, imageInfos[ii].height, imageInfos[ii].depth }; - bufferCopyInfo[ii].imageSubresource.aspectMask = aspectFlag; - bufferCopyInfo[ii].imageSubresource.mipLevel = imageInfos[ii].mipLevel; + uint32_t idealWidth = m_width >> imageInfos[ii].mipLevel; + uint32_t idealHeight = m_height >> imageInfos[ii].mipLevel; + bufferCopyInfo[ii].bufferOffset = totalMemSize; + bufferCopyInfo[ii].bufferRowLength = 0; // assume that image data are tightly aligned + bufferCopyInfo[ii].bufferImageHeight = 0; // assume that image data are tightly aligned + bufferCopyInfo[ii].imageSubresource.aspectMask = m_vkTextureAspect; + bufferCopyInfo[ii].imageSubresource.mipLevel = imageInfos[ii].mipLevel; bufferCopyInfo[ii].imageSubresource.baseArrayLayer = imageInfos[ii].layer; - bufferCopyInfo[ii].imageSubresource.layerCount = 1; + bufferCopyInfo[ii].imageSubresource.layerCount = 1; + bufferCopyInfo[ii].imageOffset = { 0, 0, 0 }; + bufferCopyInfo[ii].imageExtent = { idealWidth, idealHeight, imageInfos[ii].depth }; totalMemSize += imageInfos[ii].size; } @@ -4432,11 +4642,19 @@ VK_DESTROY ici.queueFamilyIndexCount = 0; ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; ici.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - ici.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + ici.usage = 0 + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | (_flags & BGFX_TEXTURE_RT_MASK ? + (bimg::isDepth((bimg::TextureFormat::Enum)m_textureFormat) ? + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + : 0) + ; ici.format = bimg::isDepth((bimg::TextureFormat::Enum)m_textureFormat) ? s_textureFormat[m_textureFormat].m_fmtDsv : s_textureFormat[m_textureFormat].m_fmt; ici.samples = VK_SAMPLE_COUNT_1_BIT; ici.mipLevels = m_numMips; - ici.arrayLayers = (m_type == VK_IMAGE_VIEW_TYPE_CUBE ? 6 : m_numLayers); + ici.arrayLayers = m_numSides; ici.extent.width = m_width; ici.extent.height = m_height; ici.extent.depth = m_depth; @@ -4461,25 +4679,14 @@ VK_DESTROY if (stagingBuffer) { - /*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.x = 0; - region.imageOffset.y = 0; - region.imageOffset.z = 0; - region.imageExtent.width = m_width; - region.imageExtent.height = m_height; - region.imageExtent.depth = 1; - - copyBufferToTexture(stagingBuffer, 1, ®ion);*/ copyBufferToTexture(stagingBuffer, numSrd, bufferCopyInfo); } + else + { + VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand(); + setImageMemoryBarrier(commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + s_renderVK->submitCommandAndWait(commandBuffer); + } vkFreeMemory(device, stagingDeviceMem, &s_allocationCb); vkDestroy(stagingBuffer); @@ -4493,42 +4700,24 @@ VK_DESTROY // image view creation { - VkImageViewCreateInfo viewInfo = {}; - viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.image = m_textureImage; - viewInfo.viewType = m_type; - viewInfo.format = textureFormat; - viewInfo.subresourceRange.aspectMask = aspectFlag; - viewInfo.subresourceRange.baseMipLevel = 0; - viewInfo.subresourceRange.levelCount = 1; //m_numMips; + VkImageViewCreateInfo viewInfo; + viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewInfo.pNext = NULL; + viewInfo.flags = 0; + viewInfo.image = m_textureImage; + viewInfo.viewType = m_type; + viewInfo.format = m_vkTextureFormat; + viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.subresourceRange.aspectMask = m_vkTextureAspect; + viewInfo.subresourceRange.baseMipLevel = 0; + viewInfo.subresourceRange.levelCount = m_numMips; //m_numMips; viewInfo.subresourceRange.baseArrayLayer = 0; - viewInfo.subresourceRange.layerCount = 1; //(m_type == VK_IMAGE_VIEW_TYPE_CUBE ? 6 : m_numLayers); - + viewInfo.subresourceRange.layerCount = m_numSides; //(m_type == VK_IMAGE_VIEW_TYPE_CUBE ? 6 : m_numLayers); VK_CHECK(vkCreateImageView(device, &viewInfo, &s_allocationCb, &m_textureImageView)); } - - // sampler creation - { - VkSamplerCreateInfo samplerInfo = {}; - samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.anisotropyEnable = VK_FALSE; // TODO - samplerInfo.maxAnisotropy = 0; - samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; - samplerInfo.unnormalizedCoordinates = VK_FALSE; - samplerInfo.compareEnable = VK_FALSE; - samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - samplerInfo.mipLodBias = 0.0f; - samplerInfo.minLod = 0.0f; - samplerInfo.maxLod = 0.0f; - - VK_CHECK(vkCreateSampler(device, &samplerInfo, &s_allocationCb, &m_textureSampler)); - } } return m_directAccessPtr; @@ -4541,7 +4730,6 @@ VK_DESTROY VkDevice device = s_renderVK->m_device; vkFreeMemory(device, m_textureDeviceMem, &s_allocationCb); - vkDestroy(m_textureSampler); vkDestroy(m_textureImageView); vkDestroy(m_textureImage); } @@ -4549,7 +4737,7 @@ VK_DESTROY void TextureVK::update(VkCommandPool _commandPool, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) { - BX_UNUSED(_commandPool, _side, _mip, _pitch); + BX_UNUSED(_commandPool); VkDevice device = s_renderVK->m_device; VkBuffer stagingBuffer = VK_NULL_HANDLE; @@ -4560,7 +4748,7 @@ VK_DESTROY bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bci.pNext = NULL; bci.flags = 0; - bci.size = _rect.m_width * _rect.m_height * _depth * 4; + bci.size = (_pitch == UINT16_MAX ? _mem->size :_rect.m_height * _pitch * _depth); bci.queueFamilyIndexCount = 0; bci.pQueueFamilyIndices = NULL; bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -4596,25 +4784,21 @@ VK_DESTROY void* directAccessPtr = NULL; VK_CHECK(vkBindBufferMemory(device, stagingBuffer, stagingDeviceMem, 0)); - VK_CHECK(vkMapMemory(device, stagingDeviceMem, 0, ma.allocationSize, 0, (void**)& directAccessPtr)); - bx::memCopy(directAccessPtr, _mem->data, _mem->size); + VK_CHECK(vkMapMemory(device, stagingDeviceMem, 0, ma.allocationSize, 0, (void**)&directAccessPtr)); + bx::memCopy(directAccessPtr, _mem->data, bci.size); vkUnmapMemory(device, stagingDeviceMem); - VkBufferImageCopy region = {}; - region.bufferOffset = 0; - region.bufferRowLength = 0; + const uint32_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat) ); + VkBufferImageCopy region; + region.bufferOffset = 0; + region.bufferRowLength = (_pitch == UINT16_MAX ? 0 : _pitch * 8 / bpp); 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.x = _rect.m_x; - region.imageOffset.y = _rect.m_y; - region.imageOffset.z = _z; - region.imageExtent.width = _rect.m_width; - region.imageExtent.height = _rect.m_height; - region.imageExtent.depth = _depth; + region.imageSubresource.aspectMask = m_vkTextureAspect; + region.imageSubresource.mipLevel = _mip; + region.imageSubresource.baseArrayLayer = _side; + region.imageSubresource.layerCount = 1; + region.imageOffset = { _rect.m_x, _rect.m_y, _z }; + region.imageExtent = { _rect.m_width, _rect.m_height, _depth }; copyBufferToTexture(stagingBuffer, 1, ®ion); @@ -4626,19 +4810,76 @@ VK_DESTROY { VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand(); // image Layout transition into destination optimal - setImageMemoryBarrier(commandBuffer, m_textureImage, m_currentImageLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, m_numMips, m_numLayers); + setImageMemoryBarrier(commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); // copy buffer to image vkCmdCopyBufferToImage(commandBuffer, stagingBuffer, m_textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, bufferImageCopyCount, bufferImageCopy); - setImageMemoryBarrier(commandBuffer, m_textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, m_numMips, m_numLayers); + setImageMemoryBarrier(commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); s_renderVK->submitCommandAndWait(commandBuffer); - m_currentImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } + void TextureVK::setImageMemoryBarrier(VkCommandBuffer commandBuffer, VkImageLayout newImageLayout) + { + if (m_currentImageLayout == newImageLayout) + return; + bgfx::vk::setImageMemoryBarrier(commandBuffer + , m_textureImage + , m_vkTextureAspect + , m_currentImageLayout + , newImageLayout + , m_numMips + , m_numSides + ); + m_currentImageLayout = newImageLayout; + } + + void FrameBufferVK::create(uint8_t _num, const Attachment* _attachment) + { + // create frame buffer object + m_numAttachment = _num; + bx::memCopy(m_attachment, _attachment, sizeof(Attachment) * _num); + + VkDevice device = s_renderVK->m_device; + VkAllocationCallbacks* allocatorCb = s_renderVK->m_allocatorCb; + VkRenderPass renderPass = s_renderVK->getRenderPass(_num, _attachment); + + TextureVK& firstTexture = s_renderVK->m_textures[m_attachment[0].handle.idx]; + ::VkImageView textureImageViews[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; + + m_num = 0; + for (uint8_t ii = 0; ii < m_numAttachment; ++ii) + { + TextureVK& texture = s_renderVK->m_textures[m_attachment[ii].handle.idx]; + textureImageViews[ii] = texture.m_textureImageView; + if (texture.m_vkTextureAspect & VK_IMAGE_ASPECT_COLOR_BIT) + { + m_texture[m_num] = m_attachment[ii].handle; + m_num++; + } + else if (texture.m_vkTextureAspect & VK_IMAGE_ASPECT_DEPTH_BIT) + { + m_depth = m_attachment[ii].handle; + } + } + + VkFramebufferCreateInfo fci; + fci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fci.pNext = NULL; + fci.flags = 0; + fci.renderPass = renderPass; + fci.attachmentCount = m_numAttachment; + fci.pAttachments = textureImageViews; + fci.width = firstTexture.m_width >> m_attachment[0].mip; + fci.height = firstTexture.m_height >> m_attachment[0].mip; + fci.layers = firstTexture.m_numSides; + VK_CHECK( vkCreateFramebuffer(device, &fci, allocatorCb, &m_framebuffer) ); + m_renderPass = renderPass; + } void FrameBufferVK::destroy() { + vkDestroy(m_framebuffer); } void RendererContextVK::submitBlit(BlitState& _bs, uint16_t _view) @@ -4750,6 +4991,7 @@ VK_DESTROY setImageMemoryBarrier(m_commandBuffer , m_backBufferColorImage[m_backBufferColorIdx] + , VK_IMAGE_ASPECT_COLOR_BIT , VK_IMAGE_LAYOUT_PRESENT_SRC_KHR , VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL , 1, 1); @@ -4817,6 +5059,7 @@ BX_UNUSED(currentSamplerStateIdx); currentProgram = BGFX_INVALID_HANDLE; hasPredefined = false; + VK_CHECK(vkBeginCommandBuffer(m_commandBuffer, &cbbi) ); fbh = _render->m_view[view].m_fbh; setFrameBuffer(fbh); @@ -4826,11 +5069,12 @@ BX_UNUSED(currentSamplerStateIdx); viewHasScissor = !scissorRect.isZero(); viewScissorRect = viewHasScissor ? scissorRect : rect; + rpbi.framebuffer = isValid(m_fbh) ? m_frameBuffers[m_fbh.idx].m_framebuffer : m_backBufferColor[m_backBufferColorIdx]; + rpbi.renderPass = isValid(m_fbh) ? m_frameBuffers[m_fbh.idx].m_renderPass : m_renderPass; rpbi.renderArea.offset.x = rect.m_x; rpbi.renderArea.offset.y = rect.m_y; rpbi.renderArea.extent.width = rect.m_width; rpbi.renderArea.extent.height = rect.m_height; - VK_CHECK(vkBeginCommandBuffer(m_commandBuffer, &cbbi) ); if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) ) { @@ -5337,12 +5581,20 @@ BX_UNUSED(currentSamplerStateIdx); for (uint32_t stage = 0; stage < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++stage) { const Binding& bind = renderBind.m_bind[stage]; - if (kInvalidHandle != bind.m_idx) + if (kInvalidHandle != bind.m_idx && + isValid(program.m_fsh->m_sampler[stage].uniformHandle)) { TextureVK& texture = m_textures[bind.m_idx]; - imageInfo[stage].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageInfo[stage].imageView = texture.m_textureImageView; - imageInfo[stage].sampler = texture.m_textureSampler; + VkSampler sampler = getSampler( + (0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags) + ? bind.m_samplerFlags + : (uint32_t)texture.m_flags + ) & (BGFX_SAMPLER_BITS_MASK | BGFX_SAMPLER_BORDER_COLOR_MASK) + , (uint32_t)texture.m_numMips); + + imageInfo[stage].imageLayout = texture.m_currentImageLayout; + imageInfo[stage].imageView = texture.m_textureImageView; + imageInfo[stage].sampler = sampler; wds[wdsCount].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; wds[wdsCount].pNext = NULL; @@ -5789,6 +6041,7 @@ BX_UNUSED(presentMin, presentMax); setImageMemoryBarrier(m_commandBuffer , m_backBufferColorImage[m_backBufferColorIdx] + , VK_IMAGE_ASPECT_COLOR_BIT , VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL , VK_IMAGE_LAYOUT_PRESENT_SRC_KHR , 1, 1); diff --git a/src/renderer_vk.h b/src/renderer_vk.h index 2febc3a3f..a6ddf1bb6 100644 --- a/src/renderer_vk.h +++ b/src/renderer_vk.h @@ -390,7 +390,6 @@ VK_DESTROY , m_hash(0) , m_numUniforms(0) , m_numPredefined(0) - , m_numSamplers(0) , m_numBindings(0) { } @@ -419,7 +418,6 @@ VK_DESTROY uint32_t imageBinding; }; SamplerInfo m_sampler[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS]; - uint16_t m_numSamplers; uint16_t m_numBindings; VkDescriptorSetLayoutBinding m_bindings[32]; }; @@ -450,10 +448,10 @@ VK_DESTROY struct TextureVK { TextureVK() - : m_textureImage(VK_NULL_HANDLE) + : m_vkTextureFormat(VK_FORMAT_UNDEFINED) + , m_textureImage(VK_NULL_HANDLE) , m_textureDeviceMem(VK_NULL_HANDLE) , m_textureImageView(VK_NULL_HANDLE) - , m_textureSampler(VK_NULL_HANDLE) , m_currentImageLayout(VK_IMAGE_LAYOUT_UNDEFINED) { } @@ -463,6 +461,7 @@ VK_DESTROY void update(VkCommandPool commandPool, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); void copyBufferToTexture(VkBuffer stagingBuffer, uint32_t bufferImageCopyCount, VkBufferImageCopy* bufferImageCopy); + void setImageMemoryBarrier(VkCommandBuffer commandBuffer, VkImageLayout newImageLayout); void* m_directAccessPtr; uint64_t m_flags; @@ -470,16 +469,17 @@ VK_DESTROY uint32_t m_height; uint32_t m_depth; uint32_t m_numLayers; - uint16_t m_samplerIdx; + uint32_t m_numSides; VkImageViewType m_type; uint8_t m_requestedFormat; uint8_t m_textureFormat; uint8_t m_numMips; + VkFormat m_vkTextureFormat; + VkImageAspectFlags m_vkTextureAspect; VkImage m_textureImage; VkDeviceMemory m_textureDeviceMem; VkImageView m_textureImageView; - VkSampler m_textureSampler; VkImageLayout m_currentImageLayout; }; @@ -492,9 +492,10 @@ VK_DESTROY , m_denseIdx(kInvalidHandle) , m_num(0) , m_numTh(0) + , m_framebuffer(VK_NULL_HANDLE) { } - + void create(uint8_t _num, const Attachment* _attachment); void destroy(); TextureHandle m_texture[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; @@ -505,7 +506,10 @@ VK_DESTROY uint16_t m_denseIdx; uint8_t m_num; uint8_t m_numTh; + uint8_t m_numAttachment; Attachment m_attachment[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; + VkFramebuffer m_framebuffer; + VkRenderPass m_renderPass; }; } /* namespace bgfx */ } // namespace vk