Permalink
Browse files

Merge pull request #10041 from hrydgard/vulkan-cleanups

Additional Vulkan fixes and cleanups
  • Loading branch information...
hrydgard committed Nov 1, 2017
2 parents 980e173 + 6b90454 commit 6d20aea340460f0d9a451c77f4363b233490d75c
@@ -153,20 +153,6 @@ VulkanContext::~VulkanContext() {
VulkanFree();
}
void TransitionToPresent(VkCommandBuffer cmd, VkImage image) {
TransitionImageLayout2(cmd, image, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT);
}
void TransitionFromPresent(VkCommandBuffer cmd, VkImage image) {
TransitionImageLayout2(cmd, image, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
}
void VulkanContext::BeginFrame() {
FrameData *frame = &frame_[curFrame_];
// Process pending deletes.
@@ -306,6 +306,8 @@ class VulkanContext {
return swapchainFormat_;
}
// 1 for no frame overlap and thus minimal latency but worst performance.
// 2 is an OK compromise, while 3 performs best but risks slightly higher latency.
enum {
MAX_INFLIGHT_FRAMES = 3,
};
@@ -393,9 +395,6 @@ void TransitionImageLayout2(VkCommandBuffer cmd, VkImage image, VkImageAspectFla
VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask);
void TransitionFromPresent(VkCommandBuffer cmd, VkImage image);
void TransitionToPresent(VkCommandBuffer cmd, VkImage image);
// GLSL compiler
void init_glslang();
void finalize_glslang();
@@ -358,14 +358,6 @@ void VulkanTexture::EndCreate(VkCommandBuffer cmd) {
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
}
void VulkanTexture::TransitionForUpload(VkCommandBuffer cmd) {
TransitionImageLayout2(cmd, image,
VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT);
}
void VulkanTexture::Destroy() {
if (view != VK_NULL_HANDLE) {
vulkan_->Delete().QueueDeleteImageView(view);
@@ -35,8 +35,6 @@ class VulkanTexture {
void UploadMip(VkCommandBuffer cmd, int mip, int mipWidth, int mipHeight, VkBuffer buffer, uint32_t offset, size_t rowLength); // rowLength is in pixels
void EndCreate(VkCommandBuffer cmd);
void TransitionForUpload(VkCommandBuffer cmd);
int GetNumMips() const { return numMips_; }
void Destroy();
View
@@ -236,7 +236,10 @@
<ClCompile Include="FileSystems\VirtualDiscFileSystem.cpp" />
<ClCompile Include="Font\PGF.cpp" />
<ClCompile Include="HDRemaster.cpp" />
<ClCompile Include="HLE\HLE.cpp" />
<ClCompile Include="HLE\HLE.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">MaxSpeed</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Default</BasicRuntimeChecks>
</ClCompile>
<ClCompile Include="HLE\HLEHelperThread.cpp" />
<ClCompile Include="HLE\HLETables.cpp" />
<ClCompile Include="HLE\proAdhoc.cpp" />
@@ -514,9 +514,6 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceIma
}
}
// If GLES3 is available, we can preallocate the storage, which makes texture loading more efficient.
DXGI_FORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat());
int scaleFactor = standardScaleFactor_;
// Rachet down scale factor in low-memory mode.
@@ -573,6 +570,8 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceIma
maxLevel = 0;
}
DXGI_FORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat());
if (IsFakeMipmapChange()) {
// NOTE: Since the level is not part of the cache key, we assume it never changes.
u8 level = std::max(0, gstate.getTexLevelOffset16() / 16);
@@ -35,15 +35,24 @@ void main() {
}
)";
static VkFormat GetClutDestFormat(GEPaletteFormat format) {
static const VkComponentMapping VULKAN_4444_SWIZZLE = { VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B };
static const VkComponentMapping VULKAN_1555_SWIZZLE = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A };
static const VkComponentMapping VULKAN_565_SWIZZLE = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
static const VkComponentMapping VULKAN_8888_SWIZZLE = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
static VkFormat GetClutDestFormat(GEPaletteFormat format, VkComponentMapping *componentMapping) {
switch (format) {
case GE_CMODE_16BIT_ABGR4444:
return VK_FORMAT_R4G4B4A4_UNORM_PACK16;
*componentMapping = VULKAN_4444_SWIZZLE;
return VK_FORMAT_B4G4R4A4_UNORM_PACK16;
case GE_CMODE_16BIT_ABGR5551:
*componentMapping = VULKAN_1555_SWIZZLE;
return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
case GE_CMODE_16BIT_BGR5650:
return VK_FORMAT_R5G6B5_UNORM_PACK16;
*componentMapping = VULKAN_565_SWIZZLE;
return VK_FORMAT_B5G6R5_UNORM_PACK16;
case GE_CMODE_32BIT_ABGR8888:
*componentMapping = VULKAN_8888_SWIZZLE;
return VK_FORMAT_R8G8B8A8_UNORM;
}
return VK_FORMAT_UNDEFINED;
@@ -104,15 +113,16 @@ VulkanTexture *DepalShaderCacheVulkan::GetClutTexture(GEPaletteFormat clutFormat
return oldtex->second->texture;
}
VkFormat destFormat = GetClutDestFormat(clutFormat);
VkComponentMapping componentMapping;
VkFormat destFormat = GetClutDestFormat(clutFormat, &componentMapping);
int texturePixels = clutFormat == GE_CMODE_32BIT_ABGR8888 ? 256 : 512;
VkBuffer pushBuffer;
uint32_t pushOffset = push_->PushAligned(rawClut, 1024, 4, &pushBuffer);
VulkanTexture *vktex = new VulkanTexture(vulkan_, alloc_);
if (!vktex->CreateDirect(cmd, texturePixels, 1, 1, destFormat,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, nullptr)) {
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, &componentMapping)) {
Crash();
}
vktex->UploadMip(cmd, 0, texturePixels, 1, pushBuffer, pushOffset, texturePixels);
@@ -57,7 +57,7 @@ enum {
};
#define VERTEXCACHE_DECIMATION_INTERVAL 17
#define DESCRIPTORSET_DECIMATION_INTERVAL 13
#define DESCRIPTORSET_DECIMATION_INTERVAL 1 // Temporarily cut to 1. Handle reuse breaks this when textures get deleted.
enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MAX = 4 };
@@ -79,7 +79,6 @@ enum {
DrawEngineVulkan::DrawEngineVulkan(VulkanContext *vulkan, Draw::DrawContext *draw)
: vulkan_(vulkan),
draw_(draw),
curFrame_(0),
stats_{},
vai_(1024) {
decOptions_.expandAllWeightsToFloat = false;
@@ -279,7 +278,8 @@ void DrawEngineVulkan::DeviceRestore(VulkanContext *vulkan) {
void DrawEngineVulkan::BeginFrame() {
lastPipeline_ = nullptr;
FrameData *frame = &frame_[curFrame_];
int curFrame = vulkan_->GetCurFrame();
FrameData *frame = &frame_[curFrame];
// First reset all buffers, then begin. This is so that Reset can free memory and Begin can allocate it,
// if growing the buffer is needed. Doing it this way will reduce fragmentation if more than one buffer
@@ -295,6 +295,7 @@ void DrawEngineVulkan::BeginFrame() {
// TODO : Find a better place to do this.
if (!nullTexture_) {
ILOG("INIT : Creating null texture");
VkCommandBuffer cmdInit = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::INIT_COMMANDBUFFER);
nullTexture_ = new VulkanTexture(vulkan_);
int w = 8;
@@ -357,16 +358,13 @@ void DrawEngineVulkan::BeginFrame() {
}
void DrawEngineVulkan::EndFrame() {
FrameData *frame = &frame_[curFrame_];
FrameData *frame = &frame_[vulkan_->GetCurFrame()];
stats_.pushUBOSpaceUsed = (int)frame->pushUBO->GetOffset();
stats_.pushVertexSpaceUsed = (int)frame->pushVertex->GetOffset();
stats_.pushIndexSpaceUsed = (int)frame->pushIndex->GetOffset();
frame->pushUBO->End();
frame->pushVertex->End();
frame->pushIndex->End();
curFrame_++;
if (curFrame_ >= vulkan_->GetInflightFrames())
curFrame_ = 0;
vertexCache_->End();
}
@@ -519,7 +517,7 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView
assert(light != VK_NULL_HANDLE);
assert(bone != VK_NULL_HANDLE);
FrameData *frame = &frame_[curFrame_];
FrameData *frame = &frame_[vulkan_->GetCurFrame()];
if (!gstate_c.bezier && !gstate_c.spline) { // Has no cache when HW tessellation.
VkDescriptorSet d = frame->descSets.Get(key);
if (d != VK_NULL_HANDLE)
@@ -667,7 +665,7 @@ void DrawEngineVulkan::DoFlush() {
// Since we have a new cmdbuf, dirty our dynamic state so it gets re-set.
// gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE|DIRTY_DEPTHSTENCIL_STATE|DIRTY_BLEND_STATE);
FrameData *frame = &frame_[curFrame_];
FrameData *frame = &frame_[vulkan_->GetCurFrame()];
bool textureNeedsApply = false;
if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) {
@@ -1087,6 +1085,7 @@ void DrawEngineVulkan::UpdateUBOs(FrameData *frame) {
void DrawEngineVulkan::TessellationDataTransferVulkan::PrepareBuffers(float *&pos, float *&tex, float *&col, int size, bool hasColor, bool hasTexCoords) {
int rowPitch;
ILOG("INIT : Prep tess");
VkCommandBuffer cmd = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::INIT_COMMANDBUFFER);
// Position
@@ -168,7 +168,7 @@ class DrawEngineVulkan : public DrawEngineCommon {
}
VulkanPushBuffer *GetPushBufferForTextureData() {
return frame_[curFrame_].pushUBO;
return frame_[vulkan_->GetCurFrame()].pushUBO;
}
const DrawEngineVulkanStats &GetStats() const {
@@ -233,7 +233,6 @@ class DrawEngineVulkan : public DrawEngineCommon {
};
GEPrimitiveType lastPrim_ = GE_PRIM_INVALID;
int curFrame_;
FrameData frame_[VulkanContext::MAX_INFLIGHT_FRAMES];
// Other
@@ -206,25 +206,27 @@ void FramebufferManagerVulkan::Init() {
}
void FramebufferManagerVulkan::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) {
if (drawPixelsTex_ && (drawPixelsTexFormat_ != srcPixelFormat || drawPixelsTex_->GetWidth() != width || drawPixelsTex_->GetHeight() != height)) {
if (drawPixelsTex_) {
delete drawPixelsTex_;
drawPixelsTex_ = nullptr;
}
VkCommandBuffer initCmd = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::INIT_COMMANDBUFFER);
if (!drawPixelsTex_) {
drawPixelsTex_ = new VulkanTexture(vulkan_);
drawPixelsTex_->CreateDirect(initCmd, width, height, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
// Initialize backbuffer texture for DrawPixels
drawPixelsTexFormat_ = srcPixelFormat;
} else {
// TODO: We may want to double-buffer these, when we have more frames hanging about.
drawPixelsTex_->TransitionForUpload(initCmd);
drawPixelsTex_ = new VulkanTexture(vulkan_);
if (!drawPixelsTex_->CreateDirect(initCmd, width, height, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)) {
// out of memory?
delete drawPixelsTex_;
drawPixelsTex_ = nullptr;
overrideImageView_ = VK_NULL_HANDLE;
return;
}
// Initialize backbuffer texture for DrawPixels
drawPixelsTexFormat_ = srcPixelFormat;
// TODO: We can just change the texture format and flip some bits around instead of this.
// Could share code with the texture cache perhaps.
// Could also convert directly into the pushbuffer easily.
const uint8_t *data = srcPixels;
if (srcPixelFormat != GE_FORMAT_8888 || srcStride != width) {
u32 neededSize = width * height * 4;
View
@@ -218,16 +218,16 @@ void GPU_Vulkan::BeginHostFrame() {
textureCacheVulkan_->StartFrame();
FrameData &frame = frameData_[curFrame_];
int curFrame = vulkan_->GetCurFrame();
FrameData &frame = frameData_[curFrame];
frame.push_->Reset();
frame.push_->Begin(vulkan_);
framebufferManagerVulkan_->BeginFrameVulkan();
framebufferManagerVulkan_->SetPushBuffer(frameData_[curFrame_].push_);
depalShaderCache_.SetPushBuffer(frameData_[curFrame_].push_);
textureCacheVulkan_->SetPushBuffer(frameData_[curFrame_].push_);
framebufferManagerVulkan_->SetPushBuffer(frameData_[curFrame].push_);
depalShaderCache_.SetPushBuffer(frameData_[curFrame].push_);
textureCacheVulkan_->SetPushBuffer(frameData_[curFrame].push_);
vulkan2D_.BeginFrame();
@@ -244,16 +244,12 @@ void GPU_Vulkan::BeginHostFrame() {
}
void GPU_Vulkan::EndHostFrame() {
FrameData &frame = frameData_[curFrame_];
int curFrame = vulkan_->GetCurFrame();
FrameData &frame = frameData_[curFrame];
frame.push_->End();
vulkan2D_.EndFrame();
curFrame_++;
if (curFrame_ >= vulkan_->GetInflightFrames()) {
curFrame_ = 0;
}
drawEngine_.EndFrame();
framebufferManagerVulkan_->EndFrame();
textureCacheVulkan_->EndFrame();
View
@@ -134,5 +134,4 @@ class GPU_Vulkan : public GPUCommon {
};
FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES]{};
int curFrame_ = 0;
};
@@ -550,6 +550,11 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, bool replaceIm
int h = gstate.getTextureHeight(0);
ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h);
if (replaced.GetSize(0, w, h)) {
if (replaceImages) {
// Since we're replacing the texture, we can't replace the image inside.
ReleaseTexture(entry, true);
replaceImages = false;
}
// We're replacing, so we won't scale.
scaleFactor = 1;
entry->status |= TexCacheEntry::STATUS_IS_SCALED;
@@ -586,7 +591,9 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, bool replaceIm
if (replaced.Valid()) {
actualFmt = ToVulkanFormat(replaced.Format(0));
}
if (!entry->vkTex) {
{
delete entry->vkTex;
entry->vkTex = new CachedTextureVulkan();
entry->vkTex->texture_ = new VulkanTexture(vulkan_, allocator_);
VulkanTexture *image = entry->vkTex->texture_;
@@ -636,8 +643,6 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, bool replaceIm
delete entry->vkTex;
entry->vkTex = nullptr;
}
} else {
entry->vkTex->texture_->TransitionForUpload(cmdInit);
}
lastBoundTexture = entry->vkTex;
View
@@ -20,7 +20,7 @@
#include "Common/Vulkan/VulkanContext.h"
#include "GPU/Vulkan/VulkanUtil.h"
Vulkan2D::Vulkan2D(VulkanContext *vulkan) : vulkan_(vulkan), curFrame_(0) {
Vulkan2D::Vulkan2D(VulkanContext *vulkan) : vulkan_(vulkan) {
InitDeviceObjects();
}
@@ -121,15 +121,13 @@ void Vulkan2D::DeviceRestore(VulkanContext *vulkan) {
}
void Vulkan2D::BeginFrame() {
FrameData &frame = frameData_[curFrame_];
int curFrame = vulkan_->GetCurFrame();
FrameData &frame = frameData_[curFrame];
frame.descSets.clear();
vkResetDescriptorPool(vulkan_->GetDevice(), frame.descPool, 0);
}
void Vulkan2D::EndFrame() {
curFrame_++;
if (curFrame_ >= vulkan_->GetInflightFrames())
curFrame_ = 0;
}
VkDescriptorSet Vulkan2D::GetDescriptorSet(VkImageView tex1, VkSampler sampler1, VkImageView tex2, VkSampler sampler2) {
@@ -139,7 +137,8 @@ VkDescriptorSet Vulkan2D::GetDescriptorSet(VkImageView tex1, VkSampler sampler1,
key.sampler[0] = sampler1;
key.sampler[1] = sampler2;
FrameData *frame = &frameData_[curFrame_];
int curFrame = vulkan_->GetCurFrame();
FrameData *frame = &frameData_[curFrame];
auto iter = frame->descSets.find(key);
if (iter != frame->descSets.end()) {
return iter->second;
View
@@ -104,7 +104,6 @@ class Vulkan2D {
};
FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES];
int curFrame_ = 0;
std::map<PipelineKey, VkPipeline> pipelines_;
};
Oops, something went wrong.

0 comments on commit 6d20aea

Please sign in to comment.