diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index 6286e939c..4a5a30ed4 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -269,13 +269,14 @@ sector_t *VulkanFrameBuffer::RenderView(player_t *player) screen->mLights->Clear(); screen->mViewpoints->Clear(); -#if 0 // NoInterpolateView should have no bearing on camera textures, but needs to be preserved for the main view below. bool saved_niv = NoInterpolateView; NoInterpolateView = false; // Shader start time does not need to be handled per level. Just use the one from the camera to render from. +#if 0 GetRenderState()->CheckTimer(player->camera->Level->ShaderStartTime); +#endif // prepare all camera textures that have been used in the last frame. // This must be done for all levels, not just the primary one! for (auto Level : AllLevels()) @@ -286,7 +287,6 @@ sector_t *VulkanFrameBuffer::RenderView(player_t *player) }); } NoInterpolateView = saved_niv; -#endif // now render the main view float fovratio; @@ -389,6 +389,45 @@ sector_t *VulkanFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor * return mainvp.sector; } +void VulkanFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV) +{ + // This doesn't need to clear the fake flat cache. It can be shared between camera textures and the main view of a scene. + FMaterial *mat = FMaterial::ValidateTexture(tex, false); + auto BaseLayer = static_cast(mat->GetLayer(0, 0)); + + int width = mat->TextureWidth(); + int height = mat->TextureHeight(); + VulkanImage *image = BaseLayer->GetImage(tex, 0, 0); + VulkanImageView *view = BaseLayer->GetImageView(tex, 0, 0); + + mRenderState->EndRenderPass(); + auto cmdbuffer = GetDrawCommands(); + + PipelineBarrier barrier0; + barrier0.addImage(image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); + barrier0.execute(cmdbuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + + mRenderState->SetRenderTarget(view, image->width, image->height, VK_SAMPLE_COUNT_1_BIT); + + IntRect bounds; + bounds.left = bounds.top = 0; + bounds.width = MIN(mat->GetWidth(), image->width); + bounds.height = MIN(mat->GetHeight(), image->height); + + FRenderViewpoint texvp; + RenderViewpoint(texvp, Viewpoint, &bounds, FOV, (float)width / height, (float)width / height, false, false); + + mRenderState->EndRenderPass(); + + PipelineBarrier barrier1; + barrier1.addImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); + barrier1.execute(cmdbuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + mRenderState->SetRenderTarget(GetBuffers()->SceneColorView.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), GetBuffers()->GetSceneSamples()); + + tex->SetUpdated(true); +} + void VulkanFrameBuffer::DrawScene(HWDrawInfo *di, int drawmode) { // To do: this is virtually identical to FGLRenderer::DrawScene and should be merged. diff --git a/src/rendering/vulkan/system/vk_framebuffer.h b/src/rendering/vulkan/system/vk_framebuffer.h index a8525aa4c..5fb474166 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.h +++ b/src/rendering/vulkan/system/vk_framebuffer.h @@ -80,6 +80,7 @@ public: private: sector_t *RenderViewpoint(FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); + void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV); void DrawScene(HWDrawInfo *di, int drawmode); void PrintStartupLog(); void CreateFanToTrisIndexBuffer(); @@ -98,8 +99,6 @@ private: VkRenderBuffers *mActiveRenderBuffers = nullptr; - int camtexcount = 0; - int lastSwapWidth = 0; int lastSwapHeight = 0; }; diff --git a/src/rendering/vulkan/textures/vk_hwtexture.cpp b/src/rendering/vulkan/textures/vk_hwtexture.cpp index 653e9fadf..8ecdcbdc6 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/rendering/vulkan/textures/vk_hwtexture.cpp @@ -76,6 +76,8 @@ VulkanDescriptorSet *VkHardwareTexture::GetDescriptorSet(const FMaterialState &s // Textures that are already scaled in the texture lump will not get replaced by hires textures. int flags = state.mMaterial->isExpanded() ? CTF_Expand : (gl_texture_usehires && !tex->isScaled() && clampmode <= CLAMP_XY) ? CTF_CheckHires : 0; + if (tex->isHardwareCanvas()) static_cast(tex)->NeedUpdate(); + DescriptorKey key; key.clampmode = clampmode; key.translation = translation; @@ -92,12 +94,12 @@ VulkanDescriptorSet *VkHardwareTexture::GetDescriptorSet(const FMaterialState &s int numLayers = mat->GetLayers(); WriteDescriptors update; - update.addCombinedImageSampler(descriptorSet.get(), 0, GetImageView(tex, clampmode, translation, flags), sampler, mImageLayout); + update.addCombinedImageSampler(descriptorSet.get(), 0, GetImageView(tex, translation, flags), sampler, mImageLayout); for (int i = 1; i < numLayers; i++) { FTexture *layer; auto systex = static_cast(mat->GetLayer(i, 0, &layer)); - update.addCombinedImageSampler(descriptorSet.get(), i, systex->GetImageView(layer, clampmode, 0, mat->isExpanded() ? CTF_Expand : 0), sampler, systex->mImageLayout); + update.addCombinedImageSampler(descriptorSet.get(), i, systex->GetImageView(layer, 0, mat->isExpanded() ? CTF_Expand : 0), sampler, systex->mImageLayout); } update.updateSets(fb->device); } @@ -105,40 +107,67 @@ VulkanDescriptorSet *VkHardwareTexture::GetDescriptorSet(const FMaterialState &s return descriptorSet.get(); } -VulkanImageView *VkHardwareTexture::GetImageView(FTexture *tex, int clampmode, int translation, int flags) +VulkanImage *VkHardwareTexture::GetImage(FTexture *tex, int translation, int flags) { if (!mImage) { - if (!tex->isHardwareCanvas()) + CreateImage(tex, translation, flags); + } + return mImage.get(); +} + +VulkanImageView *VkHardwareTexture::GetImageView(FTexture *tex, int translation, int flags) +{ + if (!mImageView) + { + CreateImage(tex, translation, flags); + } + return mImageView.get(); +} + +void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) +{ + if (!tex->isHardwareCanvas()) + { + if (translation <= 0) { - if (translation <= 0) - { - translation = -translation; - } - else - { - auto remap = TranslationToTable(translation); - translation = remap == nullptr ? 0 : remap->GetUniqueIndex(); - } - - bool needmipmap = (clampmode <= CLAMP_XY); - - FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData); - CreateTexture(texbuffer.mWidth, texbuffer.mHeight, 4, VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer); + translation = -translation; } else { - static const uint32_t testpixels[4 * 4] = - { - 0xff0000ff, 0xff0000ff, 0xffff00ff, 0xffff00ff, - 0xff0000ff, 0xff0000ff, 0xffff00ff, 0xffff00ff, - 0xff00ff00, 0xff00ff00, 0x0000ffff, 0xff00ffff, - 0xff00ff00, 0xff00ff00, 0x0000ffff, 0xff00ffff, - }; - CreateTexture(4, 4, 4, VK_FORMAT_R8G8B8A8_UNORM, testpixels); + auto remap = TranslationToTable(translation); + translation = remap == nullptr ? 0 : remap->GetUniqueIndex(); } + + FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData); + CreateTexture(texbuffer.mWidth, texbuffer.mHeight, 4, VK_FORMAT_B8G8R8A8_UNORM, texbuffer.mBuffer); + } + else + { + auto fb = GetVulkanFrameBuffer(); + + VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; + int w = tex->GetWidth(); + int h = tex->GetHeight(); + + ImageBuilder imgbuilder; + imgbuilder.setFormat(format); + imgbuilder.setSize(w, h); + imgbuilder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + mImage = imgbuilder.create(fb->device); + mImage->SetDebugName("VkHardwareTexture.mImage"); + + ImageViewBuilder viewbuilder; + viewbuilder.setImage(mImage.get(), format); + mImageView = viewbuilder.create(fb->device); + mImageView->SetDebugName("VkHardwareTexture.mImageView"); + + auto cmdbuffer = fb->GetUploadCommands(); + + PipelineBarrier imageTransition; + imageTransition.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT); + imageTransition.execute(cmdbuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); } - return mImageView.get(); } void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels) diff --git a/src/rendering/vulkan/textures/vk_hwtexture.h b/src/rendering/vulkan/textures/vk_hwtexture.h index 2f8a7927a..6c4777e6d 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.h +++ b/src/rendering/vulkan/textures/vk_hwtexture.h @@ -39,8 +39,11 @@ public: VkHardwareTexture *Prev = nullptr; VkHardwareTexture *Next = nullptr; + VulkanImage *GetImage(FTexture *tex, int translation, int flags); + VulkanImageView *GetImageView(FTexture *tex, int translation, int flags); + private: - VulkanImageView *GetImageView(FTexture *tex, int clampmode, int translation, int flags); + void CreateImage(FTexture *tex, int translation, int flags); void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels); void GenerateMipmaps(VulkanImage *image, VulkanCommandBuffer *cmdbuffer);