2019-10-05 09:50:14 +00:00
|
|
|
/*
|
|
|
|
* Created on: Oct 3, 2019
|
|
|
|
|
|
|
|
Copyright 2019 flyinghead
|
|
|
|
|
|
|
|
This file is part of Flycast.
|
|
|
|
|
|
|
|
Flycast is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Flycast is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <memory>
|
|
|
|
#include "vulkan.h"
|
|
|
|
#include "buffer.h"
|
|
|
|
#include "rend/TexCache.h"
|
2019-10-09 19:16:12 +00:00
|
|
|
#include "hw/pvr/Renderer_if.h"
|
|
|
|
|
2019-10-13 16:42:28 +00:00
|
|
|
void setImageLayout(vk::CommandBuffer const& commandBuffer, vk::Image image, vk::Format format, u32 mipmapLevels, vk::ImageLayout oldImageLayout, vk::ImageLayout newImageLayout);
|
2019-10-05 09:50:14 +00:00
|
|
|
|
|
|
|
struct Texture : BaseTextureCacheData
|
|
|
|
{
|
2019-10-12 11:47:25 +00:00
|
|
|
~Texture() override
|
|
|
|
{
|
|
|
|
imageView.reset();
|
|
|
|
image.reset();
|
|
|
|
if (allocator)
|
|
|
|
allocator->Free(memoryOffset, memoryType, sharedDeviceMemory);
|
|
|
|
}
|
2019-10-05 09:50:14 +00:00
|
|
|
void UploadToGPU(int width, int height, u8 *data) override;
|
|
|
|
u64 GetIntId() { return (u64)reinterpret_cast<uintptr_t>(this); }
|
|
|
|
std::string GetId() override { char s[20]; sprintf(s, "%p", this); return s; }
|
|
|
|
bool IsNew() const { return !image.get(); }
|
2019-10-06 10:24:07 +00:00
|
|
|
vk::ImageView GetImageView() const { return *imageView; }
|
2019-10-07 15:45:11 +00:00
|
|
|
void SetCommandBuffer(vk::CommandBuffer commandBuffer) { this->commandBuffer = commandBuffer; }
|
2019-11-10 09:16:18 +00:00
|
|
|
virtual bool Force32BitTexture(TextureType type) const override { return !VulkanContext::Instance()->IsFormatSupported(type); }
|
2019-10-05 09:50:14 +00:00
|
|
|
|
2019-11-10 09:16:18 +00:00
|
|
|
void SetAllocator(Allocator *allocator) { this->allocator = allocator; }
|
2019-10-21 14:39:16 +00:00
|
|
|
void SetPhysicalDevice(vk::PhysicalDevice physicalDevice) { this->physicalDevice = physicalDevice; }
|
|
|
|
void SetDevice(vk::Device device) { this->device = device; }
|
|
|
|
|
2019-10-05 09:50:14 +00:00
|
|
|
private:
|
|
|
|
void Init(u32 width, u32 height, vk::Format format);
|
2019-10-07 15:45:11 +00:00
|
|
|
void SetImage(u32 size, void *data, bool isNew);
|
2019-10-05 09:50:14 +00:00
|
|
|
void CreateImage(vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::ImageLayout initialLayout,
|
|
|
|
vk::MemoryPropertyFlags memoryProperties, vk::ImageAspectFlags aspectMask);
|
2019-10-13 16:42:28 +00:00
|
|
|
void GenerateMipmaps();
|
2019-10-05 09:50:14 +00:00
|
|
|
|
2019-10-21 14:39:16 +00:00
|
|
|
vk::Format format = vk::Format::eUndefined;
|
2019-10-13 16:42:28 +00:00
|
|
|
vk::Extent2D extent;
|
|
|
|
u32 mipmapLevels = 1;
|
|
|
|
bool needsStaging = false;
|
2019-10-05 09:50:14 +00:00
|
|
|
std::unique_ptr<BufferData> stagingBufferData;
|
2019-10-07 15:45:11 +00:00
|
|
|
vk::CommandBuffer commandBuffer;
|
2019-10-05 09:50:14 +00:00
|
|
|
|
|
|
|
vk::UniqueDeviceMemory deviceMemory;
|
|
|
|
vk::UniqueImageView imageView;
|
2019-10-05 14:09:28 +00:00
|
|
|
vk::UniqueImage image;
|
|
|
|
|
2019-10-05 09:50:14 +00:00
|
|
|
vk::PhysicalDevice physicalDevice;
|
|
|
|
vk::Device device;
|
2019-11-10 09:16:18 +00:00
|
|
|
Allocator *allocator = nullptr;
|
2019-10-12 11:47:25 +00:00
|
|
|
vk::DeviceMemory sharedDeviceMemory;
|
|
|
|
u32 memoryType = 0;
|
|
|
|
vk::DeviceSize memoryOffset = 0;
|
2019-10-09 19:16:12 +00:00
|
|
|
|
|
|
|
friend class TextureDrawer;
|
2019-11-10 09:16:18 +00:00
|
|
|
friend class OITTextureDrawer;
|
2019-10-05 09:50:14 +00:00
|
|
|
};
|
2019-10-06 10:24:07 +00:00
|
|
|
|
|
|
|
class SamplerManager
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
vk::Sampler GetSampler(TSP tsp)
|
|
|
|
{
|
|
|
|
u32 samplerHash = tsp.full & TSP_Mask; // FilterMode, ClampU, ClampV, FlipU, FlipV
|
|
|
|
const auto& it = samplers.find(samplerHash);
|
|
|
|
vk::Sampler sampler;
|
|
|
|
if (it != samplers.end())
|
|
|
|
return it->second.get();
|
|
|
|
vk::Filter filter = tsp.FilterMode == 0 ? vk::Filter::eNearest : vk::Filter::eLinear;
|
|
|
|
vk::SamplerAddressMode uRepeat = tsp.ClampU ? vk::SamplerAddressMode::eClampToEdge
|
|
|
|
: tsp.FlipU ? vk::SamplerAddressMode::eMirroredRepeat : vk::SamplerAddressMode::eRepeat;
|
|
|
|
vk::SamplerAddressMode vRepeat = tsp.ClampV ? vk::SamplerAddressMode::eClampToEdge
|
|
|
|
: tsp.FlipV ? vk::SamplerAddressMode::eMirroredRepeat : vk::SamplerAddressMode::eRepeat;
|
|
|
|
|
|
|
|
return samplers.emplace(
|
2019-10-25 17:20:15 +00:00
|
|
|
std::make_pair(samplerHash, VulkanContext::Instance()->GetDevice().createSamplerUnique(
|
2019-10-06 10:24:07 +00:00
|
|
|
vk::SamplerCreateInfo(vk::SamplerCreateFlags(), filter, filter,
|
2019-11-15 10:17:01 +00:00
|
|
|
vk::SamplerMipmapMode::eNearest, uRepeat, vRepeat, vk::SamplerAddressMode::eClampToEdge, 0.0f,
|
|
|
|
VulkanContext::Instance()->SupportsSamplerAnisotropy(), 16.0f, false, vk::CompareOp::eNever,
|
|
|
|
0.0f, 256.0f, vk::BorderColor::eFloatOpaqueBlack)))).first->second.get();
|
2019-10-06 10:24:07 +00:00
|
|
|
}
|
|
|
|
static const u32 TSP_Mask = 0x7e000;
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::map<u32, vk::UniqueSampler> samplers;
|
|
|
|
};
|
2019-10-09 19:16:12 +00:00
|
|
|
|
|
|
|
class FramebufferAttachment
|
|
|
|
{
|
|
|
|
public:
|
2019-11-10 09:16:18 +00:00
|
|
|
FramebufferAttachment(vk::PhysicalDevice physicalDevice, vk::Device device, Allocator *allocator = nullptr)
|
|
|
|
: physicalDevice(physicalDevice), device(device), format(vk::Format::eUndefined), allocator(allocator)
|
2019-10-09 19:16:12 +00:00
|
|
|
{}
|
2019-11-10 09:16:18 +00:00
|
|
|
~FramebufferAttachment() {
|
|
|
|
if (allocator != nullptr && sharedDeviceMemory)
|
|
|
|
allocator->Free(memoryOffset, memoryType, sharedDeviceMemory);
|
|
|
|
}
|
|
|
|
void Init(u32 width, u32 height, vk::Format format, vk::ImageUsageFlags = vk::ImageUsageFlags());
|
2019-10-09 19:16:12 +00:00
|
|
|
void Reset() { image.reset(); imageView.reset(); deviceMemory.reset(); }
|
|
|
|
|
2019-11-10 09:16:18 +00:00
|
|
|
vk::ImageView GetImageView() const { return *imageView; }
|
|
|
|
vk::Image GetImage() const { return *image; }
|
2019-10-09 19:16:12 +00:00
|
|
|
const BufferData* GetBufferData() const { return stagingBufferData.get(); }
|
2019-11-10 09:16:18 +00:00
|
|
|
vk::ImageView GetStencilView() const { return *stencilView; }
|
2019-10-09 19:16:12 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
vk::Format format;
|
|
|
|
vk::Extent2D extent;
|
|
|
|
|
|
|
|
std::unique_ptr<BufferData> stagingBufferData;
|
2019-11-10 09:16:18 +00:00
|
|
|
vk::DeviceMemory sharedDeviceMemory;
|
|
|
|
vk::DeviceSize memoryOffset = 0;
|
|
|
|
u32 memoryType = 0;
|
2019-10-09 19:16:12 +00:00
|
|
|
vk::UniqueDeviceMemory deviceMemory;
|
|
|
|
vk::UniqueImageView imageView;
|
2019-11-10 09:16:18 +00:00
|
|
|
vk::UniqueImageView stencilView;
|
2019-10-09 19:16:12 +00:00
|
|
|
vk::UniqueImage image;
|
|
|
|
|
|
|
|
vk::PhysicalDevice physicalDevice;
|
|
|
|
vk::Device device;
|
2019-11-10 09:16:18 +00:00
|
|
|
Allocator *allocator;
|
2019-10-09 19:16:12 +00:00
|
|
|
};
|
2019-10-21 14:39:16 +00:00
|
|
|
|
|
|
|
class TextureCache : public BaseTextureCache<Texture>
|
|
|
|
{
|
|
|
|
};
|