From d958c4fec5196b38c493f694a527f2476822e53e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 26 Feb 2019 15:29:08 +0100 Subject: [PATCH] - upload and bind some textures --- .../vulkan/renderer/vk_renderstate.cpp | 10 ++ .../vulkan/system/vk_framebuffer.cpp | 10 ++ src/rendering/vulkan/system/vk_framebuffer.h | 5 + .../vulkan/textures/vk_hwtexture.cpp | 156 +++++++++++++++++- src/rendering/vulkan/textures/vk_hwtexture.h | 35 ++++ 5 files changed, 208 insertions(+), 8 deletions(-) diff --git a/src/rendering/vulkan/renderer/vk_renderstate.cpp b/src/rendering/vulkan/renderer/vk_renderstate.cpp index b3a6418236..3701fe3511 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.cpp +++ b/src/rendering/vulkan/renderer/vk_renderstate.cpp @@ -3,6 +3,7 @@ #include "vulkan/system/vk_framebuffer.h" #include "vulkan/system/vk_builders.h" #include "vulkan/renderer/vk_renderpass.h" +#include "vulkan/textures/vk_hwtexture.h" #include "templates.h" #include "doomstat.h" #include "r_data/colormaps.h" @@ -165,6 +166,15 @@ void VkRenderState::Apply(int dt) mCommandBuffer->bindIndexBuffer(static_cast(mIndexBuffer)->mBuffer->buffer, 0, VK_INDEX_TYPE_UINT32); BindDescriptorSets(); + + if (mMaterial.mChanged) + { + auto base = static_cast(mMaterial.mMaterial->GetLayer(0, mMaterial.mTranslation)); + if (base) + mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->PipelineLayout.get(), 1, base->GetDescriptorSet(mMaterial)); + + mMaterial.mChanged = false; + } } void VkRenderState::Bind(int bindingpoint, uint32_t offset) diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index 9b5e5345ca..2d30161be1 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -43,6 +43,7 @@ #include "vulkan/renderer/vk_renderpass.h" #include "vulkan/shaders/vk_shader.h" #include "vulkan/textures/vk_samplers.h" +#include "vulkan/textures/vk_hwtexture.h" #include "vulkan/system/vk_builders.h" #include "vulkan/system/vk_swapchain.h" #include "doomerrors.h" @@ -62,6 +63,8 @@ VulkanFrameBuffer::VulkanFrameBuffer(void *hMonitor, bool fullscreen, VulkanDevi VulkanFrameBuffer::~VulkanFrameBuffer() { + for (auto tex : AllTextures) + tex->Reset(); } void VulkanFrameBuffer::InitializeState() @@ -232,6 +235,13 @@ void VulkanFrameBuffer::CleanForRestart() { } +IHardwareTexture *VulkanFrameBuffer::CreateHardwareTexture() +{ + auto texture = new VkHardwareTexture(); + AllTextures.Push(texture); + return texture; +} + FModelRenderer *VulkanFrameBuffer::CreateModelRenderer(int mli) { I_FatalError("VulkanFrameBuffer::CreateModelRenderer not implemented\n"); diff --git a/src/rendering/vulkan/system/vk_framebuffer.h b/src/rendering/vulkan/system/vk_framebuffer.h index 401b8f8578..4e2d9d05e2 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.h +++ b/src/rendering/vulkan/system/vk_framebuffer.h @@ -9,6 +9,7 @@ class VkShaderManager; class VkRenderPassManager; class VkRenderState; class VKDataBuffer; +class VkHardwareTexture; class VulkanFrameBuffer : public SystemBaseFrameBuffer { @@ -21,6 +22,7 @@ public: VulkanCommandBuffer *GetUploadCommands(); VulkanCommandBuffer *GetDrawCommands(); VkShaderManager *GetShaderManager() { return mShaderManager.get(); } + VkSamplerManager *GetSamplerManager() { return mSamplerManager.get(); } VkRenderPassManager *GetRenderPassManager() { return mRenderPassManager.get(); } VkRenderState *GetRenderState() { return mRenderState.get(); } @@ -44,6 +46,7 @@ public: void BeginFrame() override; void BlurScene(float amount) override; + IHardwareTexture *CreateHardwareTexture() override; FModelRenderer *CreateModelRenderer(int mli) override; IShaderProgram *CreateShaderProgram() override; IVertexBuffer *CreateVertexBuffer() override; @@ -75,6 +78,8 @@ private: int lastSwapWidth = 0; int lastSwapHeight = 0; + + TArray AllTextures; }; inline VulkanFrameBuffer *GetVulkanFrameBuffer() { return static_cast(screen); } diff --git a/src/rendering/vulkan/textures/vk_hwtexture.cpp b/src/rendering/vulkan/textures/vk_hwtexture.cpp index db0eb020f1..8c498beceb 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/rendering/vulkan/textures/vk_hwtexture.cpp @@ -28,10 +28,155 @@ #include "c_cvars.h" #include "r_data/colormaps.h" #include "hwrenderer/textures/hw_material.h" - #include "hwrenderer/utility/hw_cvars.h" +#include "vulkan/system/vk_objects.h" +#include "vulkan/system/vk_builders.h" +#include "vulkan/system/vk_framebuffer.h" +#include "vulkan/textures/vk_samplers.h" +#include "vulkan/renderer/vk_renderpass.h" #include "vk_hwtexture.h" +VkHardwareTexture::VkHardwareTexture() +{ +} + +VkHardwareTexture::~VkHardwareTexture() +{ +} + +void VkHardwareTexture::Reset() +{ + mDescriptorSet.reset(); + mImage.reset(); + mImageView.reset(); + mStagingBuffer.reset(); +} + +VulkanDescriptorSet *VkHardwareTexture::GetDescriptorSet(const FMaterialState &state) +{ + if (!mImage) + { + static const uint32_t testpixels[4 * 4] = + { + 0xff0000ff, 0xff0000ff, 0xffff00ff, 0xffff00ff, + 0xff0000ff, 0xff0000ff, 0xffff00ff, 0xffff00ff, + 0xff0000ff, 0x00ffffff, 0x0000ffff, 0x0000ffff, + 0xff0000ff, 0x00ffffff, 0x0000ffff, 0x0000ffff, + }; + CreateTexture(4, 4, 4, VK_FORMAT_R8G8B8A8_UNORM, testpixels); + } + + if (!mDescriptorSet) + { + auto fb = GetVulkanFrameBuffer(); + mDescriptorSet = fb->GetRenderPassManager()->DescriptorPool->allocate(fb->GetRenderPassManager()->TextureSetLayout.get()); + + WriteDescriptors update; + update.addCombinedImageSampler(mDescriptorSet.get(), 0, mImageView.get(), fb->GetSamplerManager()->Get(0), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + update.updateSets(fb->device); + } + + return mDescriptorSet.get(); +} + +void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels) +{ + auto fb = GetVulkanFrameBuffer(); + + int totalSize = w * h * pixelsize; + + BufferBuilder bufbuilder; + bufbuilder.setSize(totalSize); + bufbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); + mStagingBuffer = bufbuilder.create(fb->device); + + uint8_t *data = (uint8_t*)mStagingBuffer->Map(0, totalSize); + memcpy(data, pixels, totalSize); + mStagingBuffer->Unmap(); + + ImageBuilder imgbuilder; + imgbuilder.setFormat(format); + imgbuilder.setSize(w, h, GetMipLevels(w, h)); + imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + mImage = imgbuilder.create(fb->device); + + ImageViewBuilder viewbuilder; + viewbuilder.setImage(mImage.get(), format); + mImageView = viewbuilder.create(fb->device); + + auto cmdbuffer = fb->GetUploadCommands(); + + PipelineBarrier imageTransition0; + imageTransition0.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT); + imageTransition0.execute(cmdbuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.depth = 1; + region.imageExtent.width = w; + region.imageExtent.height = h; + cmdbuffer->copyBufferToImage(mStagingBuffer->buffer, mImage->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + GenerateMipmaps(mImage.get(), cmdbuffer); +} + +void VkHardwareTexture::GenerateMipmaps(VulkanImage *image, VulkanCommandBuffer *cmdbuffer) +{ + int mipWidth = image->width; + int mipHeight = image->height; + int i; + for (i = 1; mipWidth > 1 || mipHeight > 1; i++) + { + PipelineBarrier barrier0; + barrier0.addImage(image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); + barrier0.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + + int nextWidth = std::max(mipWidth >> 1, 1); + int nextHeight = std::max(mipHeight >> 1, 1); + + VkImageBlit blit = {}; + blit.srcOffsets[0] = { 0, 0, 0 }; + blit.srcOffsets[1] = { mipWidth, mipHeight, 1 }; + blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.srcSubresource.mipLevel = i - 1; + blit.srcSubresource.baseArrayLayer = 0; + blit.srcSubresource.layerCount = 1; + blit.dstOffsets[0] = { 0, 0, 0 }; + blit.dstOffsets[1] = { nextWidth, nextHeight, 1 }; + blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.dstSubresource.mipLevel = i; + blit.dstSubresource.baseArrayLayer = 0; + blit.dstSubresource.layerCount = 1; + cmdbuffer->blitImage(image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR); + + PipelineBarrier barrier1; + barrier1.addImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); + barrier1.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + mipWidth = nextWidth; + mipHeight = nextHeight; + } + + PipelineBarrier barrier2; + barrier2.addImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); + barrier2.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); +} + +int VkHardwareTexture::GetMipLevels(int w, int h) +{ + int levels = 1; + while (w > 1 || h > 1) + { + w = std::max(w >> 1, 1); + h = std::max(h >> 1, 1); + levels++; + } + return levels; +} + +#if 0 + //=========================================================================== // // Creates the low level texture object @@ -40,7 +185,6 @@ VkResult VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, bool mipmap, int translation) { -#if 0 int rh,rw; bool deletebuffer=false; auto tTex = GetTexID(translation); @@ -72,9 +216,6 @@ VkResult VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, tTex->vkTexture = nullptr; } return res; -#else - return VK_ERROR_INITIALIZATION_FAILED; -#endif } //=========================================================================== @@ -204,7 +345,6 @@ VkHardwareTexture::TranslatedTexture *VkHardwareTexture::GetTexID(int translatio VkTexture *VkHardwareTexture::GetVkTexture(FTexture *tex, int translation, bool needmipmap, int flags) { -#if 0 int usebright = false; if (translation <= 0) @@ -227,6 +367,6 @@ VkTexture *VkHardwareTexture::GetVkTexture(FTexture *tex, int translation, bool delete[] buffer; } return pTex->vkTexture; -#endif - return nullptr; } + +#endif diff --git a/src/rendering/vulkan/textures/vk_hwtexture.h b/src/rendering/vulkan/textures/vk_hwtexture.h index d30b89132c..3a7b8a977f 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.h +++ b/src/rendering/vulkan/textures/vk_hwtexture.h @@ -11,6 +11,40 @@ #include "hwrenderer/textures/hw_ihwtexture.h" #include "volk/volk.h" +struct FMaterialState; +class VulkanDescriptorSet; +class VulkanImage; +class VulkanImageView; +class VulkanBuffer; + +class VkHardwareTexture : public IHardwareTexture +{ +public: + VkHardwareTexture(); + ~VkHardwareTexture(); + + void Reset(); + + VulkanDescriptorSet *GetDescriptorSet(const FMaterialState &state); + + // Software renderer stuff + void AllocateBuffer(int w, int h, int texelsize) override { } + uint8_t *MapBuffer() override { return nullptr; } + unsigned int CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, const char *name) override { return 0; } + +private: + void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels); + void GenerateMipmaps(VulkanImage *image, VulkanCommandBuffer *cmdbuffer); + static int GetMipLevels(int w, int h); + + std::unique_ptr mDescriptorSet; + std::unique_ptr mImage; + std::unique_ptr mImageView; + std::unique_ptr mStagingBuffer; +}; + +#if 0 + class FCanvasTexture; class AActor; class VkTexture; @@ -71,3 +105,4 @@ public: VkTexture *GetVkTexture(FTexture *tex, int translation, bool needmipmap, int flags); }; +#endif