diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index 2b15f90f2e..3d91d00aab 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -1436,6 +1436,7 @@ void VulkanTexture::CreateDirect(int w, int h, int numMips, VkFormat format) { tex_width = w; tex_height = h; numMips_ = numMips; + format_ = format; VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; image_create_info.imageType = VK_IMAGE_TYPE_2D; @@ -1497,10 +1498,10 @@ void VulkanTexture::CreateDirect(int w, int h, int numMips, VkFormat format) { assert(res == VK_SUCCESS); } -void VulkanTexture::UploadMip(int mip, VkBuffer buffer, size_t offset, size_t stride) { +void VulkanTexture::UploadMip(int mip, VkBuffer buffer, size_t offset, size_t rowLength) { VkBufferImageCopy copy_region = {}; copy_region.bufferOffset = offset; - copy_region.bufferRowLength = (uint32_t)stride; + copy_region.bufferRowLength = (uint32_t)rowLength; copy_region.bufferImageHeight = tex_height; copy_region.imageExtent.width = tex_width; copy_region.imageExtent.height = tex_height; diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index ba905279c4..c60e305e8b 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -366,7 +366,7 @@ public: // Fast uploads from buffer. Mipmaps supported. void CreateDirect(int w, int h, int numMips, VkFormat format); - void UploadMip(int mip, VkBuffer buffer, size_t offset, size_t stride); + void UploadMip(int mip, VkBuffer buffer, size_t offset, size_t rowLength); // rowLength is in pixels void EndCreate(); void Destroy(); @@ -416,12 +416,10 @@ public: VulkanPushBuffer(VulkanContext *vulkan, size_t size) : offset_(0), size_(size), writePtr_(nullptr), deviceMemory_(0) { VkDevice device = vulkan->GetDevice(); - VkBufferCreateInfo b = {}; - b.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - b.pNext = nullptr; + VkBufferCreateInfo b = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; b.size = size; b.flags = 0; - b.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + b.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; b.sharingMode = VK_SHARING_MODE_EXCLUSIVE; b.queueFamilyIndexCount = 0; b.pQueueFamilyIndices = nullptr; diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 665c0b0f96..dd015a8d8d 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -467,7 +467,7 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) { // TODO: The descriptor set seems to be unbinding the texture when not specified. Cache it or the imageView instead? // TODO: Add this back when fixed: gstate_c.textureChanged != TEXCHANGE_UNCHANGED && if (!gstate.isModeClear() && gstate.isTextureMapEnabled()) { - textureCache_->SetTexture(); + textureCache_->SetTexture(frame->pushData); gstate_c.textureChanged = TEXCHANGE_UNCHANGED; if (gstate_c.needShaderTexClamp) { // We will rarely need to set this, so let's do it every time on use rather than in runloop. diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 2768c7d12b..c9a710a102 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -1069,7 +1069,7 @@ bool TextureCacheVulkan::SetOffsetTexture(u32 offset) { return false; } -void TextureCacheVulkan::SetTexture() { +void TextureCacheVulkan::SetTexture(VulkanPushBuffer *uploadBuffer) { #ifdef DEBUG_TEXTURES if (SetDebugTexture()) { // A different texture was bound, let's rebind next time. @@ -1453,14 +1453,21 @@ void TextureCacheVulkan::SetTexture() { entry->vkTex = new CachedTextureVulkan(); entry->vkTex->texture_ = new VulkanTexture(vulkan_); VulkanTexture *image = entry->vkTex->texture_; - VkResult res = image->Create(w, h, dstFmt); - assert(res == VK_SUCCESS); + image->CreateDirect(w, h, 1, dstFmt); } lastBoundTexture = entry->vkTex; // In Vulkan, fortunately, we have full control over mipmapping. // For now, we only load the base texture. More to come. - LoadTextureLevel(*entry, 0, replaceImages, scaleFactor, dstFmt); + + // Upload the texture data. + int bpp = dstFmt == VULKAN_8888_FORMAT ? 4 : 2; + int stride = (w * bpp + 15) & ~15; + int size = stride * h; + size_t bufferOffset; + void *data = uploadBuffer->Push(size, &bufferOffset); + LoadTextureLevel(*entry, (uint8_t *)data, stride, 0, replaceImages, scaleFactor, dstFmt); + entry->vkTex->texture_->UploadMip(0, uploadBuffer->GetVkBuffer(), bufferOffset, stride / bpp); // Mipmapping only enable when texture scaling disable /* @@ -1740,7 +1747,7 @@ TextureCacheVulkan::TexCacheEntry::Status TextureCacheVulkan::CheckAlpha(const u return (TexCacheEntry::Status)res; } -void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, int level, bool replaceImages, int scaleFactor, VkFormat dstFmt) { +void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePtr, int rowPitch, int level, bool replaceImages, int scaleFactor, VkFormat dstFmt) { CachedTextureVulkan *tex = entry.vkTex; int w = gstate.getTextureWidth(level); int h = gstate.getTextureHeight(level); @@ -1751,7 +1758,6 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, int level, bool PROFILE_THIS_SCOPE("decodetex"); u32 texByteAlign = 1; - GETextureFormat tfmt = (GETextureFormat)entry.format; GEPaletteFormat clutformat = gstate.getClutPaletteFormat(); int bufw; @@ -1784,16 +1790,11 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, int level, bool } PROFILE_THIS_SCOPE("loadtex"); - - // Upload the texture data. TODO: Decode directly into this buffer. - int rowPitch; - uint8_t *writePtr = entry.vkTex->texture_->Lock(level, &rowPitch); for (int y = 0; y < h; y++) { memcpy(writePtr + rowPitch * y, (const uint8_t *)pixelData + decPitch * y, rowBytes); // uncomment to make all textures white for debugging //memset(writePtr + rowPitch * y, 0xff, rowBytes); } - entry.vkTex->texture_->Unlock(); /* if (!lowMemoryMode_) { diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 17eaabf863..0d732f480d 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -85,7 +85,7 @@ public: TextureCacheVulkan(VulkanContext *vulkan); ~TextureCacheVulkan(); - void SetTexture(); + void SetTexture(VulkanPushBuffer *uploadBuffer); virtual bool SetOffsetTexture(u32 offset) override; void Clear(bool delete_them); @@ -126,7 +126,7 @@ private: void DeleteTexture(TexCache::iterator it); void *ReadIndexedTex(int level, const u8 *texptr, int bytesPerIndex, VkFormat dstFmt, int bufw); void UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheKey &key); - void LoadTextureLevel(TexCacheEntry &entry, int level, bool replaceImages, int scaleFactor, VkFormat dstFmt); + void LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePtr, int rowPitch, int level, bool replaceImages, int scaleFactor, VkFormat dstFmt); VkFormat GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; void *DecodeTextureLevel(GETextureFormat format, GEPaletteFormat clutformat, int level, u32 &texByteAlign, VkFormat dstFmt, int scaleFactor, int *bufw = 0); TexCacheEntry::Status CheckAlpha(const u32 *pixelData, VkFormat dstFmt, int stride, int w, int h);