diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index 14fd1b32a0..078230f0ba 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -104,7 +104,7 @@ struct UB_VS_FS_Base { }; static const char *ub_baseStr = -R"( mat4 proj_mtx; +R"( mat4 proj_mtx; mat4 view_mtx; mat4 world_mtx; mat4 tex_mtx; @@ -139,15 +139,15 @@ struct UB_VS_Lights { }; static const char *ub_vs_lightsStr = -R"(vec4 globalAmbient; +R"( vec4 globalAmbient; vec3 matdiffuse; - vec4 matspecular; - vec3 matemissive; - vec3 pos[4]; - vec3 dir[4]; - vec3 att[4]; + vec4 matspecular; + vec3 matemissive; + vec3 pos[4]; + vec3 dir[4]; + vec3 att[4]; float angle[4]; - float spotCoef[4]; + float spotCoef[4]; vec3 ambient[4]; vec3 diffuse[4]; vec3 specular[4]; @@ -158,7 +158,7 @@ struct UB_VS_Bones { }; static const char *ub_vs_bonesStr = -R"(mat4 m[8]; +R"( mat4 m[8]; )"; class VulkanContext; diff --git a/GPU/Vulkan/StateMappingVulkan.cpp b/GPU/Vulkan/StateMappingVulkan.cpp index 6fb68e0eec..c2ea8a2e21 100644 --- a/GPU/Vulkan/StateMappingVulkan.cpp +++ b/GPU/Vulkan/StateMappingVulkan.cpp @@ -202,6 +202,7 @@ void ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManager, ShaderManagerV // Set cull bool wantCull = !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); key.cullMode = wantCull ? (gstate.getCullMode() ? VK_CULL_MODE_FRONT_BIT : VK_CULL_MODE_BACK_BIT) : VK_CULL_MODE_NONE; + key.cullMode = VK_CULL_MODE_NONE; // Depth Test if (gstate.isDepthTestEnabled()) { @@ -213,6 +214,8 @@ void ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManager, ShaderManagerV } } else { key.depthTestEnable = false; + key.depthWriteEnable = false; + key.depthCompareOp = VK_COMPARE_OP_ALWAYS; } // PSP color/alpha mask is per bit but we can only support per byte. diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 7ec887c1ce..0349ebc481 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -1446,9 +1446,10 @@ void TextureCacheVulkan::SetTexture() { } } else { entry->vkTex = new CachedTextureVulkan(); - entry->vkTex->texture_ = new VulkanTexture(); + entry->vkTex->texture_ = new VulkanTexture(vulkan_); VulkanTexture *image = entry->vkTex->texture_; - image->Create(vulkan_, w, h, dstFmt); + VkResult res = image->Create(w, h, dstFmt); + assert(res == VK_SUCCESS); } lastBoundTexture = entry->vkTex; @@ -1786,11 +1787,11 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, int level, bool // Upload the texture data. TODO: Decode directly into this buffer. int rowPitch; - uint8_t *writePtr = entry.vkTex->texture_->Lock(vulkan_, level, &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); } - entry.vkTex->texture_->Unlock(vulkan_); + entry.vkTex->texture_->Unlock(); /* if (!lowMemoryMode_) { diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp index ea35594545..0adf5d5ddd 100644 --- a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp @@ -138,11 +138,11 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer) { // are present and what parts aren't, but we will not be ultra detailed about it. WRITE(p, "\n"); - WRITE(p, "layout (std140, set = 0, binding = 2) uniform baseVars {\n%s\n} base;\n", ub_baseStr); + WRITE(p, "layout (std140, set = 0, binding = 2) uniform baseVars {\n%s} base;\n", ub_baseStr); if (enableLighting || doShadeMapping) - WRITE(p, "layout (std140, set = 0, binding = 3) uniform lightVars {\n%s\n} light;\n", ub_vs_lightsStr); + WRITE(p, "layout (std140, set = 0, binding = 3) uniform lightVars {\n%s} light;\n", ub_vs_lightsStr); if (enableBones) - WRITE(p, "layout (std140, set = 0, binding = 4) uniform boneVars {\n%s\n} bone;\n", ub_vs_bonesStr); + WRITE(p, "layout (std140, set = 0, binding = 4) uniform boneVars {\n%s} bone;\n", ub_vs_bonesStr); const char *shading = doFlatShading ? "flat " : ""; diff --git a/ext/native/thin3d/VulkanContext.cpp b/ext/native/thin3d/VulkanContext.cpp index e29c1f4bd3..75bcdc3663 100644 --- a/ext/native/thin3d/VulkanContext.cpp +++ b/ext/native/thin3d/VulkanContext.cpp @@ -1131,13 +1131,13 @@ void VulkanContext::InitCommandPool() { assert(res == VK_SUCCESS); } -VkResult VulkanTexture::Create(VulkanContext *vulkan, int w, int h, VkFormat format) { +VkResult VulkanTexture::Create(int w, int h, VkFormat format) { tex_width = w; tex_height = h; format_ = format; VkFormatProperties formatProps; - vkGetPhysicalDeviceFormatProperties(vulkan->GetPhysicalDevice(), format, &formatProps); + vkGetPhysicalDeviceFormatProperties(vulkan_->GetPhysicalDevice(), format, &formatProps); // See if we can use a linear tiled image for a texture, if not, we will need a staging image for the texture data. // Linear tiling is usually only supported for 2D non-array textures. @@ -1148,14 +1148,14 @@ VkResult VulkanTexture::Create(VulkanContext *vulkan, int w, int h, VkFormat for return VK_SUCCESS; } -void VulkanTexture::CreateMappableImage(VulkanContext *vulkan) { +void VulkanTexture::CreateMappableImage() { // If we already have a mappableImage, forget it. if (mappableImage) { - vulkan->QueueDelete(mappableImage); + vulkan_->QueueDelete(mappableImage); mappableImage = nullptr; } if (mappableMemory) { - vulkan->QueueDelete(mappableMemory); + vulkan_->QueueDelete(mappableMemory); mappableMemory = nullptr; } @@ -1187,27 +1187,27 @@ void VulkanTexture::CreateMappableImage(VulkanContext *vulkan) { // Create a mappable image. It will be the texture if linear images are ok to be textures // or it will be the staging image if they are not. - VkResult res = vkCreateImage(vulkan->GetDevice(), &image_create_info, NULL, &mappableImage); + VkResult res = vkCreateImage(vulkan_->GetDevice(), &image_create_info, NULL, &mappableImage); assert(res == VK_SUCCESS); - vkGetImageMemoryRequirements(vulkan->GetDevice(), mappableImage, &mem_reqs); + vkGetImageMemoryRequirements(vulkan_->GetDevice(), mappableImage, &mem_reqs); assert(res == VK_SUCCESS); mem_alloc.allocationSize = mem_reqs.size; // Find the memory type that is host mappable. - pass = vulkan->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &mem_alloc.memoryTypeIndex); + pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &mem_alloc.memoryTypeIndex); assert(pass); - res = vkAllocateMemory(vulkan->GetDevice(), &mem_alloc, NULL, &(mappableMemory)); + res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &(mappableMemory)); assert(res == VK_SUCCESS); - res = vkBindImageMemory(vulkan->GetDevice(), mappableImage, mappableMemory, 0); + res = vkBindImageMemory(vulkan_->GetDevice(), mappableImage, mappableMemory, 0); assert(res == VK_SUCCESS); } -uint8_t *VulkanTexture::Lock(VulkanContext *vulkan, int level, int *rowPitch) { - CreateMappableImage(vulkan); +uint8_t *VulkanTexture::Lock(int level, int *rowPitch) { + CreateMappableImage(); VkImageSubresource subres = {}; subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -1218,28 +1218,32 @@ uint8_t *VulkanTexture::Lock(VulkanContext *vulkan, int level, int *rowPitch) { void *data; // Get the subresource layout so we know what the row pitch is - vkGetImageSubresourceLayout(vulkan->GetDevice(), mappableImage, &subres, &layout); - VkResult res = vkMapMemory(vulkan->GetDevice(), mappableMemory, layout.offset, layout.size, 0, &data); + vkGetImageSubresourceLayout(vulkan_->GetDevice(), mappableImage, &subres, &layout); + VkResult res = vkMapMemory(vulkan_->GetDevice(), mappableMemory, layout.offset, layout.size, 0, &data); assert(res == VK_SUCCESS); *rowPitch = (int)layout.rowPitch; return (uint8_t *)data; } -void VulkanTexture::Unlock(VulkanContext *vulkan) { - vkUnmapMemory(vulkan->GetDevice(), mappableMemory); +void VulkanTexture::Unlock() { + vkUnmapMemory(vulkan_->GetDevice(), mappableMemory); - VkCommandBuffer cmd = vulkan->GetInitCommandBuffer(); + VkCommandBuffer cmd = vulkan_->GetInitCommandBuffer(); // if we already have an image, queue it for destruction and forget it. if (image) { - vulkan->QueueDelete(image); + vulkan_->QueueDelete(image); image = nullptr; } if (view) { - vulkan->QueueDelete(view); + vulkan_->QueueDelete(view); view = nullptr; } + if (mem) { + vulkan_->QueueDelete(mem); + mem = nullptr; + } if (!needStaging) { /* If we can use the linear tiled image as a texture, just do it */ image = mappableImage; @@ -1267,10 +1271,10 @@ void VulkanTexture::Unlock(VulkanContext *vulkan) { image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VkResult res = vkCreateImage(vulkan->GetDevice(), &image_create_info, NULL, &image); + VkResult res = vkCreateImage(vulkan_->GetDevice(), &image_create_info, NULL, &image); assert(res == VK_SUCCESS); - vkGetImageMemoryRequirements(vulkan->GetDevice(), image, &mem_reqs); + vkGetImageMemoryRequirements(vulkan_->GetDevice(), image, &mem_reqs); VkMemoryAllocateInfo mem_alloc = {}; mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; @@ -1279,13 +1283,13 @@ void VulkanTexture::Unlock(VulkanContext *vulkan) { mem_alloc.allocationSize = mem_reqs.size; // Find memory type - don't specify any mapping requirements - bool pass = vulkan->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mem_alloc.memoryTypeIndex); + bool pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mem_alloc.memoryTypeIndex); assert(pass); - res = vkAllocateMemory(vulkan->GetDevice(), &mem_alloc, NULL, &mem); + res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mem); assert(res == VK_SUCCESS); - res = vkBindImageMemory(vulkan->GetDevice(), image, mem, 0); + res = vkBindImageMemory(vulkan_->GetDevice(), image, mem, 0); assert(res == VK_SUCCESS); // Since we're going to blit from the mappable image, set its layout to SOURCE_OPTIMAL @@ -1334,8 +1338,8 @@ void VulkanTexture::Unlock(VulkanContext *vulkan) { VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageLayout); - vulkan->QueueDelete(mappableMemory); - vulkan->QueueDelete(mappableImage); + vulkan_->QueueDelete(mappableMemory); + vulkan_->QueueDelete(mappableImage); mappableImage = nullptr; mappableMemory = nullptr; } @@ -1358,18 +1362,30 @@ void VulkanTexture::Unlock(VulkanContext *vulkan) { /* create image view */ view_info.image = image; - VkResult res = vkCreateImageView(vulkan->GetDevice(), &view_info, NULL, &view); + VkResult res = vkCreateImageView(vulkan_->GetDevice(), &view_info, NULL, &view); assert(res == VK_SUCCESS); } -void VulkanTexture::Destroy(VulkanContext *vulkan) { - vulkan->QueueDelete(view); - vulkan->QueueDelete(image); - vulkan->QueueDelete(mem); +void VulkanTexture::Destroy() { + if (view) { + vulkan_->QueueDelete(view); + } + if (image) { + vulkan_->QueueDelete(image); + if (mappableImage == image) { + mappableImage = nullptr; + } + } + if (mem) { + vulkan_->QueueDelete(mem); + if (mappableMemory == mem) { + mappableMemory = nullptr; + } + } - view = NULL; - image = NULL; - mem = NULL; + view = nullptr; + image = nullptr; + mem = nullptr; } VkFence VulkanContext::CreateFence(bool presignalled) { diff --git a/ext/native/thin3d/VulkanContext.h b/ext/native/thin3d/VulkanContext.h index 4115e8435e..7568368d64 100644 --- a/ext/native/thin3d/VulkanContext.h +++ b/ext/native/thin3d/VulkanContext.h @@ -342,25 +342,30 @@ private: // Only supports simple 2D textures for now. Mipmap support will be added later. class VulkanTexture { public: - VulkanTexture() - : image(nullptr), imageLayout(VK_IMAGE_LAYOUT_UNDEFINED), mem(nullptr), view(nullptr), tex_width(0), tex_height(0), format_(VK_FORMAT_UNDEFINED), + VulkanTexture(VulkanContext *vulkan) + : vulkan_(vulkan), image(nullptr), imageLayout(VK_IMAGE_LAYOUT_UNDEFINED), mem(nullptr), view(nullptr), tex_width(0), tex_height(0), format_(VK_FORMAT_UNDEFINED), mappableImage(nullptr), mappableMemory(nullptr), needStaging(false) { } + ~VulkanTexture() { + Destroy(); + } // Always call Create, Lock, Unlock. Unlock performs the upload if necessary. // Can later Lock and Unlock again. This cannot change the format. Create cannot - // be called a second time without recreating the texture object. + // be called a second time without recreating the texture object until Destroy has + // been called. - VkResult Create(VulkanContext *vulkan, int w, int h, VkFormat format); - uint8_t *Lock(VulkanContext *vulkan, int level, int *rowPitch); - void Unlock(VulkanContext *vulkan); + VkResult Create(int w, int h, VkFormat format); + uint8_t *Lock(int level, int *rowPitch); + void Unlock(); - void Destroy(VulkanContext *vulkan); + void Destroy(); VkImageView GetImageView() const { return view; } private: - void CreateMappableImage(VulkanContext *vulkan); + void CreateMappableImage(); + VulkanContext *vulkan_; VkImage image; VkImageLayout imageLayout; VkDeviceMemory mem; diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index b04c10e348..5fc81cb708 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -548,7 +548,7 @@ public: width_ = width; height_ = height; depth_ = depth; - vkTex_ = new VulkanTexture(); + vkTex_ = new VulkanTexture(vulkan_); // We don't actually do anything here. return true; } @@ -563,7 +563,7 @@ private: void Destroy() { ILOG("texture destroyed: %p", this); if (vkTex_) { - vkTex_->Destroy(vulkan_); + vkTex_->Destroy(); delete vkTex_; } } @@ -955,13 +955,13 @@ void Thin3DVKTexture::SetImageData(int x, int y, int z, int width, int height, i int bpp; VkFormat vulkanFormat = FormatToVulkan(format_, &bpp); int bytesPerPixel = bpp / 8; - vkTex_->Create(vulkan_, width, height, vulkanFormat); + vkTex_->Create(width, height, vulkanFormat); int rowPitch; - uint8_t *dstData = vkTex_->Lock(vulkan_, 0, &rowPitch); + uint8_t *dstData = vkTex_->Lock(0, &rowPitch); for (int y = 0; y < height; y++) { memcpy(dstData + rowPitch * y, data + stride * y, width * bytesPerPixel); } - vkTex_->Unlock(vulkan_); + vkTex_->Unlock(); } void Thin3DVKTexture::Finalize(int zim_flags) {