vulkan: adjust code styling

This commit is contained in:
niki
2022-09-10 17:40:46 +02:00
parent 57207606c0
commit a93d153792
22 changed files with 1268 additions and 977 deletions
-4
View File
@@ -70,10 +70,6 @@ struct Rect
{ {
return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h; return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
} }
bool operator != (const Rect& rhs) const {
return !(*this == rhs);
}
}; };
inline int nextP2(int x) inline int nextP2(int x)
+1 -2
View File
@@ -673,8 +673,7 @@ int luax_catchexcept(lua_State *L, const T& func)
catch (const std::exception &e) catch (const std::exception &e)
{ {
should_error = true; should_error = true;
const char* msg = e.what(); lua_pushstring(L, e.what());
lua_pushstring(L, msg);
} }
if (should_error) if (should_error)
+9 -11
View File
@@ -49,7 +49,7 @@ static const char global_syntax[] = R"(
#define mediump #define mediump
#define highp #define highp
#endif #endif
#if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH) || defined(USE_VULKAN) #if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH)
#define LOVE_HIGHP_OR_MEDIUMP highp #define LOVE_HIGHP_OR_MEDIUMP highp
#else #else
#define LOVE_HIGHP_OR_MEDIUMP mediump #define LOVE_HIGHP_OR_MEDIUMP mediump
@@ -248,8 +248,8 @@ LOVE_IO_LOCATION(0) attribute vec4 VertexPosition;
LOVE_IO_LOCATION(1) attribute vec4 VertexTexCoord; LOVE_IO_LOCATION(1) attribute vec4 VertexTexCoord;
LOVE_IO_LOCATION(2) attribute vec4 VertexColor; LOVE_IO_LOCATION(2) attribute vec4 VertexColor;
LOVE_IO_LOCATION(0) varying vec4 VaryingTexCoord; varying vec4 VaryingTexCoord;
LOVE_IO_LOCATION(1) varying vec4 VaryingColor; varying vec4 VaryingColor;
vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition); vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition);
@@ -316,8 +316,8 @@ static const char pixel_main[] = R"(
#endif #endif
uniform sampler2D MainTex; uniform sampler2D MainTex;
LOVE_IO_LOCATION(0) varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord; varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord;
LOVE_IO_LOCATION(1) varying mediump vec4 VaryingColor; varying mediump vec4 VaryingColor;
vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord); vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord);
@@ -351,8 +351,8 @@ static const char pixel_main_custom[] = R"(
#define LOVE_MULTI_CANVASES 1 #define LOVE_MULTI_CANVASES 1
#endif #endif
LOVE_IO_LOCATION(0) varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord; varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord;
LOVE_IO_LOCATION(1) varying mediump vec4 VaryingColor; varying mediump vec4 VaryingColor;
void effect(); void effect();
@@ -574,8 +574,7 @@ std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage,
ss << ((!gles && (lang == Shader::LANGUAGE_GLSL1 || glsl1on3)) ? "#line 0\n" : "#line 1\n"); ss << ((!gles && (lang == Shader::LANGUAGE_GLSL1 || glsl1on3)) ? "#line 0\n" : "#line 1\n");
ss << code; ss << code;
auto result = ss.str(); return ss.str();
return result;
} }
Shader::Shader(StrongRef<ShaderStage> _stages[]) Shader::Shader(StrongRef<ShaderStage> _stages[])
@@ -877,8 +876,7 @@ bool Shader::validateInternal(StrongRef<ShaderStage> stages[], std::string &err,
{ {
LocalUniform u = {}; LocalUniform u = {};
auto &values = u.initializerValues; auto &values = u.initializerValues;
// const glslang::TConstUnionArray *constarray = info.getConstArray(); was this function deprecated in a later version? const glslang::TConstUnionArray *constarray = info.getConstArray();
const glslang::TConstUnionArray* constarray = nullptr;
// Store initializer values for local uniforms. Some love graphics // Store initializer values for local uniforms. Some love graphics
// backends strip these out of the shader so we need to be able to // backends strip these out of the shader so we need to be able to
+1 -4
View File
@@ -18,8 +18,6 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
#include <iostream>
#include "ShaderStage.h" #include "ShaderStage.h"
#include "common/Exception.h" #include "common/Exception.h"
#include "Graphics.h" #include "Graphics.h"
@@ -178,8 +176,7 @@ ShaderStage::ShaderStage(Graphics *gfx, ShaderStageType stage, const std::string
std::string err = "Error validating " + std::string(stagename) + " shader:\n\n" std::string err = "Error validating " + std::string(stagename) + " shader:\n\n"
+ std::string(glslangShader->getInfoLog()) + "\n" + std::string(glslangShader->getInfoLog()) + "\n"
+ std::string(glslangShader->getInfoDebugLog()) + "\n\nShader Code:\n" + std::string(glslangShader->getInfoDebugLog());
+ glsl;
delete glslangShader; delete glslangShader;
throw love::Exception("%s", err.c_str()); throw love::Exception("%s", err.c_str());
+2 -2
View File
@@ -46,8 +46,8 @@ public:
bool loadVolatile() override; bool loadVolatile() override;
void unloadVolatile() override; void unloadVolatile() override;
void copyFromBuffer(love::graphics::Buffer* source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect& rect) override; void copyFromBuffer(love::graphics::Buffer *source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect &rect) override;
void copyToBuffer(love::graphics::Buffer* dest, int slice, int mipmap, const Rect& rect, size_t destoffset, int destwidth, size_t size) override; void copyToBuffer(love::graphics::Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth, size_t size) override;
void setSamplerState(const SamplerState &s) override; void setSamplerState(const SamplerState &s) override;
+47 -26
View File
@@ -1,12 +1,17 @@
#include "Buffer.h" #include "Buffer.h"
#include "Graphics.h" #include "Graphics.h"
namespace love { namespace love
namespace graphics { {
namespace vulkan { namespace graphics
{
namespace vulkan
{
static VkBufferUsageFlags getUsageBit(BufferUsage mode) { static VkBufferUsageFlags getUsageBit(BufferUsage mode)
switch (mode) { {
switch (mode)
{
case BUFFERUSAGE_VERTEX: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; case BUFFERUSAGE_VERTEX: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
case BUFFERUSAGE_INDEX: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT; case BUFFERUSAGE_INDEX: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
case BUFFERUSAGE_UNIFORM: return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; case BUFFERUSAGE_UNIFORM: return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
@@ -15,35 +20,37 @@ static VkBufferUsageFlags getUsageBit(BufferUsage mode) {
} }
} }
static VkBufferUsageFlags getVulkanUsageFlags(BufferUsageFlags flags) { static VkBufferUsageFlags getVulkanUsageFlags(BufferUsageFlags flags)
{
VkBufferUsageFlags vkFlags = 0; VkBufferUsageFlags vkFlags = 0;
for (int i = 0; i < BUFFERUSAGE_MAX_ENUM; i++) { for (int i = 0; i < BUFFERUSAGE_MAX_ENUM; i++)
{
BufferUsageFlags flag = static_cast<BufferUsageFlags>(1u << i); BufferUsageFlags flag = static_cast<BufferUsageFlags>(1u << i);
if (flags & flag) { if (flags & flag)
vkFlags |= getUsageBit((BufferUsage)i); vkFlags |= getUsageBit((BufferUsage)i);
}
} }
return vkFlags; return vkFlags;
} }
Buffer::Buffer(love::graphics::Graphics* gfx, const Settings& settings, const std::vector<DataDeclaration>& format, const void* data, size_t size, size_t arraylength) Buffer::Buffer(love::graphics::Graphics *gfx, const Settings &settings, const std::vector<DataDeclaration> &format, const void *data, size_t size, size_t arraylength)
: love::graphics::Buffer(gfx, settings, format, size, arraylength), usageFlags(settings.usageFlags), gfx(gfx) { : love::graphics::Buffer(gfx, settings, format, size, arraylength)
, usageFlags(settings.usageFlags)
, vgfx(dynamic_cast<Graphics*>(gfx))
{
loadVolatile(); loadVolatile();
} }
bool Buffer::loadVolatile() { bool Buffer::loadVolatile()
Graphics* vgfx = (Graphics*)gfx; {
allocator = vgfx->getVmaAllocator(); allocator = vgfx->getVmaAllocator();
VkBufferCreateInfo bufferInfo{}; VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = getSize(); bufferInfo.size = getSize();
if (dataUsage == BUFFERDATAUSAGE_READBACK) { if (dataUsage == BUFFERDATAUSAGE_READBACK)
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
} else
else {
bufferInfo.usage = getVulkanUsageFlags(usageFlags); bufferInfo.usage = getVulkanUsageFlags(usageFlags);
}
VmaAllocationCreateInfo allocCreateInfo = {}; VmaAllocationCreateInfo allocCreateInfo = {};
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
@@ -54,11 +61,11 @@ bool Buffer::loadVolatile() {
return true; return true;
} }
void Buffer::unloadVolatile() { void Buffer::unloadVolatile()
{
if (buffer == VK_NULL_HANDLE) if (buffer == VK_NULL_HANDLE)
return; return;
Graphics* vgfx = (Graphics*)gfx;
auto device = vgfx->getDevice(); auto device = vgfx->getDevice();
vgfx->queueCleanUp( vgfx->queueCleanUp(
@@ -70,29 +77,43 @@ void Buffer::unloadVolatile() {
buffer = VK_NULL_HANDLE; buffer = VK_NULL_HANDLE;
} }
Buffer::~Buffer() { Buffer::~Buffer()
{
unloadVolatile(); unloadVolatile();
} }
void* Buffer::map(MapType map, size_t offset, size_t size) { ptrdiff_t Buffer::getHandle() const
{
return (ptrdiff_t) buffer;
}
ptrdiff_t Buffer::getTexelBufferHandle() const
{
throw love::Exception("unimplemented Buffer::getTexelBufferHandle");
return (ptrdiff_t) nullptr; // todo ?
}
void* Buffer::map(MapType map, size_t offset, size_t size)
{
char* data = (char*)allocInfo.pMappedData; char* data = (char*)allocInfo.pMappedData;
return (void*) (data + offset); return (void*) (data + offset);
} }
bool Buffer::fill(size_t offset, size_t size, const void *data) { bool Buffer::fill(size_t offset, size_t size, const void *data)
{
void* dst = (void*)((char*)allocInfo.pMappedData + offset); void* dst = (void*)((char*)allocInfo.pMappedData + offset);
memcpy(dst, data, size); memcpy(dst, data, size);
return true; return true;
} }
void Buffer::unmap(size_t usedoffset, size_t usedsize) { void Buffer::unmap(size_t usedoffset, size_t usedsize)
{
(void)usedoffset; (void)usedoffset;
(void)usedsize; (void)usedsize;
} }
void Buffer::copyTo(love::graphics::Buffer* dest, size_t sourceoffset, size_t destoffset, size_t size) { void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size)
Graphics* vgfx = (Graphics*)gfx; {
auto commandBuffer = vgfx->getReadbackCommandBuffer(); auto commandBuffer = vgfx->getReadbackCommandBuffer();
VkBufferCopy bufferCopy{}; VkBufferCopy bufferCopy{};
+22 -20
View File
@@ -1,5 +1,4 @@
#ifndef LOVE_GRAPHICS_VULKAN_BUFFER_H #pragma once
#define LOVE_GRAPHICS_VULKAN_BUFFER_H
#include "graphics/Buffer.h" #include "graphics/Buffer.h"
#include "graphics/Volatile.h" #include "graphics/Volatile.h"
@@ -7,40 +6,43 @@
#include "VulkanWrapper.h" #include "VulkanWrapper.h"
namespace love { namespace love
namespace graphics { {
namespace vulkan { namespace graphics
class Buffer : public love::graphics::Buffer, public Volatile { {
namespace vulkan
{
class Graphics;
class Buffer
: public love::graphics::Buffer
, public Volatile
{
public: public:
Buffer(love::graphics::Graphics* gfx, const Settings& settings, const std::vector<DataDeclaration>& format, const void* data, size_t size, size_t arraylength); Buffer(love::graphics::Graphics *gfx, const Settings& settings, const std::vector<DataDeclaration> &format, const void *data, size_t size, size_t arraylength);
virtual ~Buffer(); virtual ~Buffer();
virtual bool loadVolatile() override; virtual bool loadVolatile() override;
virtual void unloadVolatile() override; virtual void unloadVolatile() override;
void* map(MapType map, size_t offset, size_t size) override; void *map(MapType map, size_t offset, size_t size) override;
void unmap(size_t usedoffset, size_t usedsize) override; void unmap(size_t usedoffset, size_t usedsize) override;
bool fill(size_t offset, size_t size, const void* data) override; bool fill(size_t offset, size_t size, const void *data) override;
void copyTo(love::graphics::Buffer* dest, size_t sourceoffset, size_t destoffset, size_t size) override; void copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) override;
ptrdiff_t getHandle() const override { ptrdiff_t getHandle() const override;
return (ptrdiff_t) buffer; // todo ? ptrdiff_t getTexelBufferHandle() const override;
}
ptrdiff_t getTexelBufferHandle() const override {
throw love::Exception("unimplemented Buffer::getTexelBufferHandle");
return (ptrdiff_t) nullptr; // todo ?
}
private: private:
// todo use a staging buffer for improved performance // todo use a staging buffer for improved performance
VkBuffer buffer = VK_NULL_HANDLE; VkBuffer buffer = VK_NULL_HANDLE;
love::graphics::Graphics* gfx; Graphics *vgfx = nullptr;
VmaAllocator allocator; VmaAllocator allocator;
VmaAllocation allocation; VmaAllocation allocation;
VmaAllocationInfo allocInfo; VmaAllocationInfo allocInfo;
BufferUsageFlags usageFlags; BufferUsageFlags usageFlags;
}; };
} // vulkan } // vulkan
} // graphics } // graphics
} // love } // love
#endif
File diff suppressed because it is too large Load Diff
+95 -66
View File
@@ -1,5 +1,4 @@
#ifndef LOVE_GRAPHICS_VULKAN_GRAPHICS_H #pragma once
#define LOVE_GRAPHICS_VULKAN_GRAPHICS_H
// löve // löve
#include "common/config.h" #include "common/config.h"
@@ -20,27 +19,36 @@
#include <functional> #include <functional>
namespace love { namespace love
namespace graphics { {
namespace vulkan { namespace graphics
struct RenderPassConfiguration { {
namespace vulkan
{
struct RenderPassConfiguration
{
std::vector<VkFormat> colorFormats; std::vector<VkFormat> colorFormats;
struct StaticRenderPassConfiguration { struct StaticRenderPassConfiguration
{
VkImageLayout initialColorImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageLayout initialColorImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT; VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
VkFormat depthFormat = VK_FORMAT_UNDEFINED; VkFormat depthFormat = VK_FORMAT_UNDEFINED;
bool resolve = false; bool resolve = false;
} staticData; } staticData;
bool operator==(const RenderPassConfiguration& conf) const { bool operator==(const RenderPassConfiguration &conf) const
{
return colorFormats == conf.colorFormats && return colorFormats == conf.colorFormats &&
(memcmp(&staticData, &conf.staticData, sizeof(StaticRenderPassConfiguration)) == 0); (memcmp(&staticData, &conf.staticData, sizeof(StaticRenderPassConfiguration)) == 0);
} }
}; };
struct RenderPassConfigurationHasher { struct RenderPassConfigurationHasher
size_t operator()(const RenderPassConfiguration &configuration) const { {
size_t operator()(const RenderPassConfiguration &configuration) const
{
size_t hashes[] = { size_t hashes[] = {
XXH32(configuration.colorFormats.data(), configuration.colorFormats.size() * sizeof(VkFormat), 0), XXH32(configuration.colorFormats.data(), configuration.colorFormats.size() * sizeof(VkFormat), 0),
XXH32(&configuration.staticData, sizeof(configuration.staticData), 0), XXH32(&configuration.staticData, sizeof(configuration.staticData), 0),
@@ -49,10 +57,12 @@ struct RenderPassConfigurationHasher {
} }
}; };
struct FramebufferConfiguration { struct FramebufferConfiguration
{
std::vector<VkImageView> colorViews; std::vector<VkImageView> colorViews;
struct StaticFramebufferConfiguration { struct StaticFramebufferConfiguration
{
VkImageView depthView = VK_NULL_HANDLE; VkImageView depthView = VK_NULL_HANDLE;
VkImageView resolveView = VK_NULL_HANDLE; VkImageView resolveView = VK_NULL_HANDLE;
@@ -62,14 +72,17 @@ struct FramebufferConfiguration {
VkRenderPass renderPass = VK_NULL_HANDLE; VkRenderPass renderPass = VK_NULL_HANDLE;
} staticData; } staticData;
bool operator==(const FramebufferConfiguration& conf) const { bool operator==(const FramebufferConfiguration &conf) const
{
return colorViews == conf.colorViews && return colorViews == conf.colorViews &&
(memcmp(&staticData, &conf.staticData, sizeof(StaticFramebufferConfiguration)) == 0); (memcmp(&staticData, &conf.staticData, sizeof(StaticFramebufferConfiguration)) == 0);
} }
}; };
struct FramebufferConfigurationHasher { struct FramebufferConfigurationHasher
size_t operator()(const FramebufferConfiguration& configuration) const { {
size_t operator()(const FramebufferConfiguration &configuration) const
{
size_t hashes[] = { size_t hashes[] = {
XXH32(configuration.colorViews.data(), configuration.colorViews.size() * sizeof(VkImageView), 0), XXH32(configuration.colorViews.data(), configuration.colorViews.size() * sizeof(VkImageView), 0),
XXH32(&configuration.staticData, sizeof(configuration.staticData), 0), XXH32(&configuration.staticData, sizeof(configuration.staticData), 0),
@@ -79,16 +92,19 @@ struct FramebufferConfigurationHasher {
} }
}; };
struct OptionalInstanceExtensions { struct OptionalInstanceExtensions
{
bool physicalDeviceProperties2 = false; bool physicalDeviceProperties2 = false;
}; };
struct OptionalDeviceFeatures { struct OptionalDeviceFeatures
{
bool extendedDynamicState = false; bool extendedDynamicState = false;
bool pushDescriptor = false; bool pushDescriptor = false;
}; };
struct OptionalDeviceExtensionFunctions { struct OptionalDeviceExtensionFunctions
{
// extended dynamic state // extended dynamic state
PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT = nullptr; PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT = nullptr;
PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT = nullptr; PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT = nullptr;
@@ -106,7 +122,8 @@ struct OptionalDeviceExtensionFunctions {
PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR = nullptr; PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR = nullptr;
}; };
struct GraphicsPipelineConfiguration { struct GraphicsPipelineConfiguration
{
VkRenderPass renderPass; VkRenderPass renderPass;
VertexAttributes vertexAttributes; VertexAttributes vertexAttributes;
Shader* shader = nullptr; Shader* shader = nullptr;
@@ -117,7 +134,8 @@ struct GraphicsPipelineConfiguration {
uint32_t numColorAttachments; uint32_t numColorAttachments;
PrimitiveType primitiveType; PrimitiveType primitiveType;
struct DynamicState { struct DynamicState
{
CullMode cullmode = CULL_NONE; CullMode cullmode = CULL_NONE;
Winding winding = WINDING_MAX_ENUM; Winding winding = WINDING_MAX_ENUM;
StencilAction stencilAction = STENCIL_MAX_ENUM; StencilAction stencilAction = STENCIL_MAX_ENUM;
@@ -125,34 +143,42 @@ struct GraphicsPipelineConfiguration {
DepthState depthState{}; DepthState depthState{};
} dynamicState; } dynamicState;
GraphicsPipelineConfiguration() { GraphicsPipelineConfiguration()
{
memset(this, 0, sizeof(GraphicsPipelineConfiguration)); memset(this, 0, sizeof(GraphicsPipelineConfiguration));
} }
bool operator==(const GraphicsPipelineConfiguration& other) const { bool operator==(const GraphicsPipelineConfiguration &other) const
{
return memcmp(this, &other, sizeof(GraphicsPipelineConfiguration)) == 0; return memcmp(this, &other, sizeof(GraphicsPipelineConfiguration)) == 0;
} }
}; };
struct GraphicsPipelineConfigurationHasher { struct GraphicsPipelineConfigurationHasher
size_t operator() (const GraphicsPipelineConfiguration &configuration) const { {
size_t operator() (const GraphicsPipelineConfiguration &configuration) const
{
return XXH32(&configuration, sizeof(GraphicsPipelineConfiguration), 0); return XXH32(&configuration, sizeof(GraphicsPipelineConfiguration), 0);
} }
}; };
struct SamplerStateHasher { struct SamplerStateHasher
size_t operator()(const SamplerState &samplerState) const { {
size_t operator()(const SamplerState &samplerState) const
{
return XXH32(&samplerState, sizeof(SamplerState), 0); return XXH32(&samplerState, sizeof(SamplerState), 0);
} }
}; };
struct BatchedDrawBuffers { struct BatchedDrawBuffers
{
StreamBuffer* vertexBuffer1; StreamBuffer* vertexBuffer1;
StreamBuffer* vertexBuffer2; StreamBuffer* vertexBuffer2;
StreamBuffer* indexBuffer; StreamBuffer* indexBuffer;
StreamBuffer* constantColorBuffer; StreamBuffer* constantColorBuffer;
~BatchedDrawBuffers() { ~BatchedDrawBuffers()
{
delete vertexBuffer1; delete vertexBuffer1;
delete vertexBuffer2; delete vertexBuffer2;
delete indexBuffer; delete indexBuffer;
@@ -160,22 +186,26 @@ struct BatchedDrawBuffers {
} }
}; };
struct QueueFamilyIndices { struct QueueFamilyIndices
{
std::optional<uint32_t> graphicsFamily; std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily; std::optional<uint32_t> presentFamily;
bool isComplete() const { bool isComplete() const
{
return graphicsFamily.has_value() && presentFamily.has_value(); return graphicsFamily.has_value() && presentFamily.has_value();
} }
}; };
struct SwapChainSupportDetails { struct SwapChainSupportDetails
{
VkSurfaceCapabilitiesKHR capabilities{}; VkSurfaceCapabilitiesKHR capabilities{};
std::vector<VkSurfaceFormatKHR> formats; std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes; std::vector<VkPresentModeKHR> presentModes;
}; };
class Graphics final : public love::graphics::Graphics { class Graphics final : public love::graphics::Graphics
{
public: public:
#ifdef LOVE_ANDROID #ifdef LOVE_ANDROID
Graphics() { Graphics() {
@@ -196,27 +226,27 @@ public:
const VmaAllocator getVmaAllocator() const; const VmaAllocator getVmaAllocator() const;
// implementation for virtual functions // implementation for virtual functions
love::graphics::Texture* newTexture(const love::graphics::Texture::Settings& settings, const love::graphics::Texture::Slices* data) override; love::graphics::Texture *newTexture(const love::graphics::Texture::Settings &settings, const love::graphics::Texture::Slices *data) override;
love::graphics::Buffer* newBuffer(const love::graphics::Buffer::Settings& settings, const std::vector<love::graphics::Buffer::DataDeclaration>& format, const void* data, size_t size, size_t arraylength) override; love::graphics::Buffer *newBuffer(const love::graphics::Buffer::Settings &settings, const std::vector<love::graphics::Buffer::DataDeclaration>& format, const void *data, size_t size, size_t arraylength) override;
void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override; void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override;
void clear(const std::vector<OptionalColorD>& colors, OptionalInt stencil, OptionalDouble depth) override; void clear(const std::vector<OptionalColorD> &colors, OptionalInt stencil, OptionalDouble depth) override;
Matrix4 computeDeviceProjection(const Matrix4& projection, bool rendertotexture) const override; Matrix4 computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const override;
void discard(const std::vector<bool>& colorbuffers, bool depthstencil) override { } void discard(const std::vector<bool> &colorbuffers, bool depthstencil) override { }
void present(void* screenshotCallbackdata) override; void present(void *screenshotCallbackdata) override;
void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override; void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;
bool setMode(void* context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) override; bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) override;
void unSetMode() override; void unSetMode() override;
void setActive(bool active) override; void setActive(bool active) override;
int getRequestedBackbufferMSAA() const override; int getRequestedBackbufferMSAA() const override;
int getBackbufferMSAA() const override; int getBackbufferMSAA() const override;
void setColor(Colorf c) override; void setColor(Colorf c) override;
void setScissor(const Rect& rect) override; void setScissor(const Rect &rect) override;
void setScissor() override; void setScissor() override;
void setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) override; void setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) override;
void setDepthMode(CompareMode compare, bool write) override; void setDepthMode(CompareMode compare, bool write) override;
void setFrontFaceWinding(Winding winding) override; void setFrontFaceWinding(Winding winding) override;
void setColorMask(ColorChannelMask mask) override; void setColorMask(ColorChannelMask mask) override;
void setBlendState(const BlendState& blend) override; void setBlendState(const BlendState &blend) override;
void setPointSize(float size) override; void setPointSize(float size) override;
void setWireframe(bool enable) override; void setWireframe(bool enable) override;
PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override; PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override;
@@ -224,12 +254,12 @@ public:
Renderer getRenderer() const override; Renderer getRenderer() const override;
bool usesGLSLES() const override; bool usesGLSLES() const override;
RendererInfo getRendererInfo() const override; RendererInfo getRendererInfo() const override;
void draw(const DrawCommand& cmd) override; void draw(const DrawCommand &cmd) override;
void draw(const DrawIndexedCommand& cmd) override; void draw(const DrawIndexedCommand &cmd) override;
void drawQuads(int start, int count, const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture) override; void drawQuads(int start, int count, const VertexAttributes &attributes, const BufferBindings &buffers, graphics::Texture *texture) override;
graphics::GraphicsReadback* newReadbackInternal(ReadbackMethod method, love::graphics::Buffer* buffer, size_t offset, size_t size, data::ByteData* dest, size_t destoffset) override; graphics::GraphicsReadback *newReadbackInternal(ReadbackMethod method, love::graphics::Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset) override;
graphics::GraphicsReadback* newReadbackInternal(ReadbackMethod method, love::graphics::Texture* texture, int slice, int mipmap, const Rect& rect, image::ImageData* dest, int destx, int desty) override; graphics::GraphicsReadback *newReadbackInternal(ReadbackMethod method, love::graphics::Texture *texture, int slice, int mipmap, const Rect &rect, image::ImageData *dest, int destx, int desty) override;
VkCommandBuffer getDataTransferCommandBuffer(); VkCommandBuffer getDataTransferCommandBuffer();
VkCommandBuffer getReadbackCommandBuffer(); VkCommandBuffer getReadbackCommandBuffer();
@@ -243,7 +273,7 @@ public:
uint32_t getNumImagesInFlight() const; uint32_t getNumImagesInFlight() const;
const VkDeviceSize getMinUniformBufferOffsetAlignment() const; const VkDeviceSize getMinUniformBufferOffsetAlignment() const;
graphics::Texture* getDefaultTexture() const; graphics::Texture *getDefaultTexture() const;
VkSampler getCachedSampler(const SamplerState&); VkSampler getCachedSampler(const SamplerState&);
void setComputeShader(Shader*); void setComputeShader(Shader*);
@@ -252,13 +282,13 @@ public:
const OptionalDeviceExtensionFunctions &getExtensionFunctions() const; const OptionalDeviceExtensionFunctions &getExtensionFunctions() const;
protected: protected:
graphics::ShaderStage* newShaderStageInternal(ShaderStageType stage, const std::string& cachekey, const std::string& source, bool gles) override; graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
graphics::Shader* newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) override; graphics::Shader *newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) override;
graphics::StreamBuffer* newStreamBuffer(BufferUsage type, size_t size) override; graphics::StreamBuffer *newStreamBuffer(BufferUsage type, size_t size) override;
bool dispatch(int x, int y, int z) override; bool dispatch(int x, int y, int z) override;
void initCapabilities() override; void initCapabilities() override;
void getAPIStats(int& shaderswitches) const override; void getAPIStats(int &shaderswitches) const override;
void setRenderTargetsInternal(const RenderTargets& rts, int pixelw, int pixelh, bool hasSRGBtexture) override; void setRenderTargetsInternal(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture) override;
private: private:
void createVulkanInstance(); void createVulkanInstance();
@@ -272,21 +302,21 @@ private:
void createSurface(); void createSurface();
bool checkDeviceExtensionSupport(VkPhysicalDevice device); bool checkDeviceExtensionSupport(VkPhysicalDevice device);
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device); SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats); VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats);
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes); VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes);
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities);
VkCompositeAlphaFlagBitsKHR chooseCompositeAlpha(const VkSurfaceCapabilitiesKHR& capabilities); VkCompositeAlphaFlagBitsKHR chooseCompositeAlpha(const VkSurfaceCapabilitiesKHR &capabilities);
void createSwapChain(); void createSwapChain();
void createImageViews(); void createImageViews();
void createDefaultRenderPass(); void createDefaultRenderPass();
void createDefaultFramebuffers(); void createDefaultFramebuffers();
VkFramebuffer createFramebuffer(FramebufferConfiguration); VkFramebuffer createFramebuffer(FramebufferConfiguration&);
VkFramebuffer getFramebuffer(FramebufferConfiguration); VkFramebuffer getFramebuffer(FramebufferConfiguration&);
void createDefaultShaders(); void createDefaultShaders();
VkRenderPass createRenderPass(RenderPassConfiguration); VkRenderPass createRenderPass(RenderPassConfiguration&);
VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration); VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration&);
void createColorResources(); void createColorResources();
VkFormat findSupportedFormat(const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features); VkFormat findSupportedFormat(const std::vector<VkFormat> &candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
VkFormat findDepthFormat(); VkFormat findDepthFormat();
void createDepthResources(); void createDepthResources();
void createCommandPool(); void createCommandPool();
@@ -300,7 +330,7 @@ private:
void beginFrame(); void beginFrame();
void startRecordingGraphicsCommands(bool newFrame); void startRecordingGraphicsCommands(bool newFrame);
void endRecordingGraphicsCommands(bool present); void endRecordingGraphicsCommands(bool present);
void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration); void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration&);
graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData(); graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData();
void updatedBatchedDrawBuffers(); void updatedBatchedDrawBuffers();
bool usesConstantVertexColor(const VertexAttributes&); bool usesConstantVertexColor(const VertexAttributes&);
@@ -308,8 +338,8 @@ private:
VertexAttributes vertexAttributes, VertexAttributes vertexAttributes,
std::vector<VkVertexInputBindingDescription> &bindingDescriptions, std::vector<VkVertexInputBindingDescription> &bindingDescriptions,
std::vector<VkVertexInputAttributeDescription> &attributeDescriptions); std::vector<VkVertexInputAttributeDescription> &attributeDescriptions);
void prepareDraw(const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture, PrimitiveType, CullMode); void prepareDraw(const VertexAttributes &attributes, const BufferBindings &buffers, graphics::Texture *texture, PrimitiveType, CullMode);
void startRenderPass(const RenderTargets& rts, int pixelw, int pixelh, bool hasSRGBtexture); void startRenderPass(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture);
void startDefaultRenderPass(); void startDefaultRenderPass();
void endRenderPass(); void endRenderPass();
VkSampler createSampler(const SamplerState&); VkSampler createSampler(const SamplerState&);
@@ -378,8 +408,7 @@ private:
float currentViewportHeight = 0; float currentViewportHeight = 0;
VkSampleCountFlagBits currentMsaaSamples = VK_SAMPLE_COUNT_1_BIT; VkSampleCountFlagBits currentMsaaSamples = VK_SAMPLE_COUNT_1_BIT;
}; };
} // vulkan } // vulkan
} // graphics } // graphics
} // love } // love
#endif
@@ -4,21 +4,26 @@
#include "Graphics.h" #include "Graphics.h"
#include "data/ByteData.h" #include "data/ByteData.h"
namespace love { namespace love
namespace graphics { {
namespace vulkan { namespace graphics
{
GraphicsReadback::GraphicsReadback(love::graphics::Graphics* gfx, ReadbackMethod method, love::graphics::Buffer* buffer, size_t offset, size_t size, data::ByteData* dest, size_t destoffset) namespace vulkan
: graphics::GraphicsReadback(gfx, method, buffer, offset, size, dest, destoffset) { {
vgfx = dynamic_cast<Graphics*>(gfx);
GraphicsReadback::GraphicsReadback(love::graphics::Graphics *gfx, ReadbackMethod method, love::graphics::Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset)
: graphics::GraphicsReadback(gfx, method, buffer, offset, size, dest, destoffset)
, vgfx(dynamic_cast<Graphics*>(gfx))
{
// Immediate readback of readback-type buffers doesn't need a staging buffer. // Immediate readback of readback-type buffers doesn't need a staging buffer.
if (method != READBACK_IMMEDIATE || buffer->getDataUsage() != BUFFERDATAUSAGE_READBACK) { if (method != READBACK_IMMEDIATE || buffer->getDataUsage() != BUFFERDATAUSAGE_READBACK)
{
stagingBuffer = gfx->getTemporaryBuffer(size, DATAFORMAT_FLOAT, 0, BUFFERDATAUSAGE_READBACK); stagingBuffer = gfx->getTemporaryBuffer(size, DATAFORMAT_FLOAT, 0, BUFFERDATAUSAGE_READBACK);
gfx->copyBuffer(buffer, stagingBuffer, offset, 0, size); gfx->copyBuffer(buffer, stagingBuffer, offset, 0, size);
} }
if (method == READBACK_IMMEDIATE) { if (method == READBACK_IMMEDIATE)
{
vgfx->submitGpuCommands(false); vgfx->submitGpuCommands(false);
if (stagingBuffer.get()) { if (stagingBuffer.get()) {
status = readbackBuffer(stagingBuffer, 0, size); status = readbackBuffer(stagingBuffer, 0, size);
@@ -36,10 +41,10 @@ GraphicsReadback::GraphicsReadback(love::graphics::Graphics* gfx, ReadbackMethod
}); });
} }
GraphicsReadback::GraphicsReadback(love::graphics::Graphics* gfx, ReadbackMethod method, love::graphics::Texture* texture, int slice, int mipmap, const Rect& rect, image::ImageData* dest, int destx, int desty) GraphicsReadback::GraphicsReadback(love::graphics::Graphics *gfx, ReadbackMethod method, love::graphics::Texture *texture, int slice, int mipmap, const Rect &rect, image::ImageData *dest, int destx, int desty)
: graphics::GraphicsReadback(gfx, method, texture, slice, mipmap, rect, dest, destx, desty) { : graphics::GraphicsReadback(gfx, method, texture, slice, mipmap, rect, dest, destx, desty)
vgfx = dynamic_cast<Graphics*>(gfx); , vgfx(dynamic_cast<Graphics*>(gfx))
{
size_t size = getPixelFormatSliceSize(textureFormat, rect.w, rect.h); size_t size = getPixelFormatSliceSize(textureFormat, rect.w, rect.h);
stagingBuffer = vgfx->getTemporaryBuffer(size, DATAFORMAT_FLOAT, 0, BUFFERDATAUSAGE_READBACK); stagingBuffer = vgfx->getTemporaryBuffer(size, DATAFORMAT_FLOAT, 0, BUFFERDATAUSAGE_READBACK);
@@ -57,15 +62,18 @@ GraphicsReadback::GraphicsReadback(love::graphics::Graphics* gfx, ReadbackMethod
vgfx->submitGpuCommands(false); vgfx->submitGpuCommands(false);
} }
GraphicsReadback::~GraphicsReadback() { GraphicsReadback::~GraphicsReadback()
{
} }
void GraphicsReadback::wait() { void GraphicsReadback::wait()
{
if (status == STATUS_WAITING) if (status == STATUS_WAITING)
vgfx->submitGpuCommands(false); vgfx->submitGpuCommands(false);
} }
void GraphicsReadback::update() { void GraphicsReadback::update()
{
} }
} // vulkan } // vulkan
+12 -11
View File
@@ -1,18 +1,21 @@
#ifndef LOVE_GRAPHICS_VULKAN_GRAPHICS_READBACK_H #pragma once
#define LOVE_GRAPHICS_VULKAN_GRAPHICS_READBACK_H
#include "graphics/GraphicsReadback.h" #include "graphics/GraphicsReadback.h"
namespace love { namespace love
namespace graphics { {
namespace vulkan { namespace graphics
{
namespace vulkan
{
class Graphics; class Graphics;
class GraphicsReadback : public graphics::GraphicsReadback { class GraphicsReadback : public graphics::GraphicsReadback
{
public: public:
GraphicsReadback(love::graphics::Graphics* gfx, ReadbackMethod method, love::graphics::Buffer* buffer, size_t offset, size_t size, data::ByteData* dest, size_t destoffset); GraphicsReadback(love::graphics::Graphics *gfx, ReadbackMethod method, love::graphics::Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset);
GraphicsReadback(love::graphics::Graphics* gfx, ReadbackMethod method, love::graphics::Texture* texture, int slice, int mipmap, const Rect& rect, image::ImageData* dest, int destx, int desty); GraphicsReadback(love::graphics::Graphics *gfx, ReadbackMethod method, love::graphics::Texture *texture, int slice, int mipmap, const Rect &rect, image::ImageData *dest, int destx, int desty);
virtual ~GraphicsReadback(); virtual ~GraphicsReadback();
void wait() override; void wait() override;
@@ -20,12 +23,10 @@ public:
private: private:
Graphics* vgfx; Graphics *vgfx = nullptr;
StrongRef<love::graphics::Buffer> stagingBuffer; StrongRef<love::graphics::Buffer> stagingBuffer;
}; };
} // vulkan } // vulkan
} // graphics } // graphics
} // love } // love
#endif
+192 -160
View File
@@ -7,9 +7,13 @@
#include <vector> #include <vector>
namespace love { namespace love
namespace graphics { {
namespace vulkan { namespace graphics
{
namespace vulkan
{
static const TBuiltInResource defaultTBuiltInResource = { static const TBuiltInResource defaultTBuiltInResource = {
/* .MaxLights = */ 32, /* .MaxLights = */ 32,
/* .MaxClipPlanes = */ 6, /* .MaxClipPlanes = */ 6,
@@ -120,8 +124,10 @@ static const TBuiltInResource defaultTBuiltInResource = {
static const uint32_t STREAMBUFFER_DEFAULT_SIZE = 16; static const uint32_t STREAMBUFFER_DEFAULT_SIZE = 16;
static const uint32_t DESCRIPTOR_POOL_SIZE = 1; static const uint32_t DESCRIPTOR_POOL_SIZE = 1;
static VkShaderStageFlagBits getStageBit(ShaderStageType type) { static VkShaderStageFlagBits getStageBit(ShaderStageType type)
switch (type) { {
switch (type)
{
case SHADERSTAGE_VERTEX: case SHADERSTAGE_VERTEX:
return VK_SHADER_STAGE_VERTEX_BIT; return VK_SHADER_STAGE_VERTEX_BIT;
case SHADERSTAGE_PIXEL: case SHADERSTAGE_PIXEL:
@@ -133,8 +139,10 @@ static VkShaderStageFlagBits getStageBit(ShaderStageType type) {
} }
} }
static EShLanguage getGlslShaderType(ShaderStageType stage) { static EShLanguage getGlslShaderType(ShaderStageType stage)
switch (stage) { {
switch (stage)
{
case SHADERSTAGE_VERTEX: case SHADERSTAGE_VERTEX:
return EShLangVertex; return EShLangVertex;
case SHADERSTAGE_PIXEL: case SHADERSTAGE_PIXEL:
@@ -147,30 +155,30 @@ static EShLanguage getGlslShaderType(ShaderStageType stage) {
} }
Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[]) Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[])
: graphics::Shader(stages) { : graphics::Shader(stages)
gfx = Module::getInstance<Graphics>(Module::ModuleType::M_GRAPHICS); {
auto vgfx = (Graphics*)gfx; auto gfx = Module::getInstance<Graphics>(Module::ModuleType::M_GRAPHICS);
vgfx = dynamic_cast<Graphics*>(gfx);
auto &optionalDeviceFeaures = vgfx->getOptionalDeviceFeatures(); auto &optionalDeviceFeaures = vgfx->getOptionalDeviceFeatures();
if (optionalDeviceFeaures.pushDescriptor) { if (optionalDeviceFeaures.pushDescriptor)
pfn_vkCmdPushDescriptorSetKHR = vgfx->getExtensionFunctions().vkCmdPushDescriptorSetKHR; pfn_vkCmdPushDescriptorSetKHR = vgfx->getExtensionFunctions().vkCmdPushDescriptorSetKHR;
}
loadVolatile(); loadVolatile();
} }
bool Shader::loadVolatile() { bool Shader::loadVolatile()
{
computePipeline = VK_NULL_HANDLE; computePipeline = VK_NULL_HANDLE;
for (int i = 0; i < BUILTIN_MAX_ENUM; i++) { for (int i = 0; i < BUILTIN_MAX_ENUM; i++)
builtinUniformInfo[i] = nullptr; builtinUniformInfo[i] = nullptr;
}
compileShaders(); compileShaders();
calculateUniformBufferSizeAligned(); calculateUniformBufferSizeAligned();
createDescriptorSetLayout(); createDescriptorSetLayout();
createPipelineLayout(); createPipelineLayout();
createStreamBuffers(); createStreamBuffers();
descriptorSetsVector.resize(((Graphics*)gfx)->getNumImagesInFlight()); descriptorSetsVector.resize(vgfx->getNumImagesInFlight());
currentFrame = 0; currentFrame = 0;
currentUsedUniformStreamBuffersCount = 0; currentUsedUniformStreamBuffersCount = 0;
currentUsedDescriptorSetsCount = 0; currentUsedDescriptorSetsCount = 0;
@@ -178,19 +186,17 @@ bool Shader::loadVolatile() {
return true; return true;
} }
void Shader::unloadVolatile() { void Shader::unloadVolatile()
if (shaderModules.empty()) { {
if (shaderModules.empty())
return; return;
}
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS); auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
gfx->queueCleanUp([shaderModules = std::move(shaderModules), device = device, descriptorSetLayout = descriptorSetLayout, pipelineLayout = pipelineLayout, descriptorPools = descriptorPools, computePipeline = computePipeline](){ gfx->queueCleanUp([shaderModules = std::move(shaderModules), device = device, descriptorSetLayout = descriptorSetLayout, pipelineLayout = pipelineLayout, descriptorPools = descriptorPools, computePipeline = computePipeline](){
for (const auto pool : descriptorPools) { for (const auto pool : descriptorPools)
vkDestroyDescriptorPool(device, pool, nullptr); vkDestroyDescriptorPool(device, pool, nullptr);
} for (const auto shaderModule : shaderModules)
for (const auto shaderModule : shaderModules) {
vkDestroyShaderModule(device, shaderModule, nullptr); vkDestroyShaderModule(device, shaderModule, nullptr);
}
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
if (computePipeline != VK_NULL_HANDLE) if (computePipeline != VK_NULL_HANDLE)
@@ -211,19 +217,23 @@ void Shader::unloadVolatile() {
descriptorSetsVector.clear(); descriptorSetsVector.clear();
} }
const std::vector<VkPipelineShaderStageCreateInfo>& Shader::getShaderStages() const { const std::vector<VkPipelineShaderStageCreateInfo>& Shader::getShaderStages() const
{
return shaderStages; return shaderStages;
} }
const VkPipelineLayout Shader::getGraphicsPipelineLayout() const { const VkPipelineLayout Shader::getGraphicsPipelineLayout() const
{
return pipelineLayout; return pipelineLayout;
} }
VkPipeline Shader::getComputePipeline() const { VkPipeline Shader::getComputePipeline() const
{
return computePipeline; return computePipeline;
} }
static VkDescriptorImageInfo* createDescriptorImageInfo(graphics::Texture* texture, bool sampler) { static VkDescriptorImageInfo* createDescriptorImageInfo(graphics::Texture* texture, bool sampler)
{
auto vkTexture = (Texture*)texture; auto vkTexture = (Texture*)texture;
auto imageInfo = new VkDescriptorImageInfo(); auto imageInfo = new VkDescriptorImageInfo();
@@ -236,48 +246,52 @@ static VkDescriptorImageInfo* createDescriptorImageInfo(graphics::Texture* textu
return imageInfo; return imageInfo;
} }
void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frameIndex, VkPipelineBindPoint bindPoint) { void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frameIndex, VkPipelineBindPoint bindPoint)
{
// detect whether a new frame has begun // detect whether a new frame has begun
if (currentFrame != frameIndex) { if (currentFrame != frameIndex)
{
currentFrame = frameIndex; currentFrame = frameIndex;
currentUsedUniformStreamBuffersCount = 0; currentUsedUniformStreamBuffersCount = 0;
currentUsedDescriptorSetsCount = 0; currentUsedDescriptorSetsCount = 0;
// we needed more memory last frame, let's collapse all buffers into a single one. // we needed more memory last frame, let's collapse all buffers into a single one.
if (streamBuffers.at(currentFrame).size() > 1) { if (streamBuffers.at(currentFrame).size() > 1)
{
size_t newSize = 0; size_t newSize = 0;
for (auto streamBuffer : streamBuffers.at(currentFrame)) { for (auto streamBuffer : streamBuffers.at(currentFrame))
{
newSize += streamBuffer->getSize(); newSize += streamBuffer->getSize();
delete streamBuffer; delete streamBuffer;
} }
streamBuffers.at(currentFrame).clear(); streamBuffers.at(currentFrame).clear();
streamBuffers.at(currentFrame).push_back(new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, newSize)); streamBuffers.at(currentFrame).push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, newSize));
} }
// no collapse necessary, can just call nextFrame to reset the current (only) streambuffer // no collapse necessary, can just call nextFrame to reset the current (only) streambuffer
else { else
streamBuffers.at(currentFrame).at(0)->nextFrame(); streamBuffers.at(currentFrame).at(0)->nextFrame();
}
} }
// still the same frame // still the same frame
else { else
{
auto usedStreamBufferMemory = currentUsedUniformStreamBuffersCount * uniformBufferSizeAligned; auto usedStreamBufferMemory = currentUsedUniformStreamBuffersCount * uniformBufferSizeAligned;
if (usedStreamBufferMemory >= streamBuffers.at(currentFrame).back()->getSize()) { if (usedStreamBufferMemory >= streamBuffers.at(currentFrame).back()->getSize())
{
// we ran out of memory in the current frame, need to allocate more. // we ran out of memory in the current frame, need to allocate more.
streamBuffers.at(currentFrame).push_back(new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned)); streamBuffers.at(currentFrame).push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned));
currentUsedUniformStreamBuffersCount = 0; currentUsedUniformStreamBuffersCount = 0;
} }
} }
VkDescriptorSet currentDescriptorSet; VkDescriptorSet currentDescriptorSet;
if (pfn_vkCmdPushDescriptorSetKHR) { if (pfn_vkCmdPushDescriptorSetKHR)
currentDescriptorSet = 0; currentDescriptorSet = 0;
} else
else { {
if (currentUsedDescriptorSetsCount >= static_cast<uint32_t>(descriptorSetsVector.at(currentFrame).size())) { if (currentUsedDescriptorSetsCount >= static_cast<uint32_t>(descriptorSetsVector.at(currentFrame).size()))
descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet()); descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet());
}
currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount); currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount);
} }
@@ -350,14 +364,7 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frame
} }
} }
if (currentDescriptorSet) { if (pfn_vkCmdPushDescriptorSetKHR)
vkUpdateDescriptorSets(device, static_cast<uint32_t>(descriptorWrite.size()), descriptorWrite.data(), 0, nullptr);
vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, &currentDescriptorSet, 0, nullptr);
currentUsedDescriptorSetsCount++;
}
else {
pfn_vkCmdPushDescriptorSetKHR( pfn_vkCmdPushDescriptorSetKHR(
commandBuffer, commandBuffer,
bindPoint, bindPoint,
@@ -365,49 +372,63 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t frame
0, 0,
static_cast<uint32_t>(descriptorWrite.size()), static_cast<uint32_t>(descriptorWrite.size()),
descriptorWrite.data()); descriptorWrite.data());
else
{
vkUpdateDescriptorSets(device, static_cast<uint32_t>(descriptorWrite.size()), descriptorWrite.data(), 0, nullptr);
vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, &currentDescriptorSet, 0, nullptr);
currentUsedDescriptorSetsCount++;
} }
for (const auto imageInfo : imageInfos) { for (const auto imageInfo : imageInfos)
delete imageInfo; delete imageInfo;
} if (bufferInfo)
if (bufferInfo) {
delete bufferInfo; delete bufferInfo;
}
currentUsedUniformStreamBuffersCount++; currentUsedUniformStreamBuffersCount++;
} }
Shader::~Shader() { Shader::~Shader()
{
unloadVolatile(); unloadVolatile();
} }
void Shader::attach() { void Shader::attach()
if (!isCompute) { {
if (Shader::current != this) { if (!isCompute)
{
if (Shader::current != this)
{
Graphics::flushBatchedDrawsGlobal(); Graphics::flushBatchedDrawsGlobal();
Shader::current = this; Shader::current = this;
Vulkan::shaderSwitch(); Vulkan::shaderSwitch();
} }
} }
else else
((Graphics*)gfx)->setComputeShader(this); vgfx->setComputeShader(this);
} }
int Shader::getVertexAttributeIndex(const std::string& name) { int Shader::getVertexAttributeIndex(const std::string& name)
{
auto it = attributes.find(name); auto it = attributes.find(name);
return it == attributes.end() ? -1 : it->second; return it == attributes.end() ? -1 : it->second;
} }
const Shader::UniformInfo* Shader::getUniformInfo(const std::string& name) const { const Shader::UniformInfo* Shader::getUniformInfo(const std::string& name) const
{
return &uniformInfos.at(name); return &uniformInfos.at(name);
} }
const Shader::UniformInfo* Shader::getUniformInfo(BuiltinUniform builtin) const { const Shader::UniformInfo* Shader::getUniformInfo(BuiltinUniform builtin) const
{
return builtinUniformInfo[builtin]; return builtinUniformInfo[builtin];
} }
void Shader::sendTextures(const UniformInfo* info, graphics::Texture** textures, int count) { void Shader::sendTextures(const UniformInfo* info, graphics::Texture** textures, int count)
for (unsigned i = 0; i < count; i++) { {
for (unsigned i = 0; i < count; i++)
{
auto oldTexture = info->textures[i]; auto oldTexture = info->textures[i];
info->textures[i] = textures[i]; info->textures[i] = textures[i];
info->textures[i]->retain(); info->textures[i]->retain();
@@ -416,8 +437,8 @@ void Shader::sendTextures(const UniformInfo* info, graphics::Texture** textures,
} }
} }
void Shader::calculateUniformBufferSizeAligned() { void Shader::calculateUniformBufferSizeAligned()
auto vgfx = (Graphics*)gfx; {
auto minAlignment = vgfx->getMinUniformBufferOffsetAlignment(); auto minAlignment = vgfx->getMinUniformBufferOffsetAlignment();
size_t size = localUniformStagingData.size(); size_t size = localUniformStagingData.size();
auto factor = static_cast<VkDeviceSize>(std::ceil( auto factor = static_cast<VkDeviceSize>(std::ceil(
@@ -426,19 +447,22 @@ void Shader::calculateUniformBufferSizeAligned() {
uniformBufferSizeAligned = factor * minAlignment; uniformBufferSizeAligned = factor * minAlignment;
} }
void Shader::buildLocalUniforms(spirv_cross::Compiler& comp, const spirv_cross::SPIRType& type, size_t baseoff, const std::string& basename) { void Shader::buildLocalUniforms(spirv_cross::Compiler& comp, const spirv_cross::SPIRType &type, size_t baseoff, const std::string &basename)
{
using namespace spirv_cross; using namespace spirv_cross;
const auto& membertypes = type.member_types; const auto& membertypes = type.member_types;
for (size_t uindex = 0; uindex < membertypes.size(); uindex++) { for (size_t uindex = 0; uindex < membertypes.size(); uindex++)
{
const auto& memberType = comp.get_type(membertypes[uindex]); const auto& memberType = comp.get_type(membertypes[uindex]);
size_t memberSize = comp.get_declared_struct_member_size(type, uindex); size_t memberSize = comp.get_declared_struct_member_size(type, uindex);
size_t offset = baseoff + comp.type_struct_member_offset(type, uindex); size_t offset = baseoff + comp.type_struct_member_offset(type, uindex);
std::string name = basename + comp.get_member_name(type.self, uindex); std::string name = basename + comp.get_member_name(type.self, uindex);
switch (memberType.basetype) { switch (memberType.basetype)
{
case SPIRType::Struct: case SPIRType::Struct:
name += "."; name += ".";
buildLocalUniforms(comp, memberType, offset, name); buildLocalUniforms(comp, memberType, offset, name);
@@ -458,49 +482,49 @@ void Shader::buildLocalUniforms(spirv_cross::Compiler& comp, const spirv_cross::
u.components = 1; u.components = 1;
u.data = localUniformStagingData.data() + offset; u.data = localUniformStagingData.data() + offset;
if (memberType.columns == 1) { if (memberType.columns == 1)
if (memberType.basetype == SPIRType::Int) { {
if (memberType.basetype == SPIRType::Int)
u.baseType = UNIFORM_INT; u.baseType = UNIFORM_INT;
} else if (memberType.basetype == SPIRType::UInt)
else if (memberType.basetype == SPIRType::UInt) {
u.baseType = UNIFORM_UINT; u.baseType = UNIFORM_UINT;
} else
else {
u.baseType = UNIFORM_FLOAT; u.baseType = UNIFORM_FLOAT;
}
u.components = memberType.vecsize; u.components = memberType.vecsize;
} }
else { else
{
u.baseType = UNIFORM_MATRIX; u.baseType = UNIFORM_MATRIX;
u.matrix.rows = memberType.vecsize; u.matrix.rows = memberType.vecsize;
u.matrix.columns = memberType.columns; u.matrix.columns = memberType.columns;
} }
const auto& reflectionIt = validationReflection.localUniforms.find(u.name); const auto& reflectionIt = validationReflection.localUniforms.find(u.name);
if (reflectionIt != validationReflection.localUniforms.end()) { if (reflectionIt != validationReflection.localUniforms.end())
{
const auto& localUniform = reflectionIt->second; const auto& localUniform = reflectionIt->second;
const auto& values = localUniform.initializerValues; const auto& values = localUniform.initializerValues;
if (!values.empty()) { if (!values.empty())
memcpy( memcpy(
u.data, u.data,
values.data(), values.data(),
std::min(u.dataSize, values.size() * sizeof(LocalUniformValue))); std::min(u.dataSize, values.size() * sizeof(LocalUniformValue)));
}
} }
uniformInfos[u.name] = u; uniformInfos[u.name] = u;
BuiltinUniform builtin = BUILTIN_MAX_ENUM; BuiltinUniform builtin = BUILTIN_MAX_ENUM;
if (getConstant(u.name.c_str(), builtin)) { if (getConstant(u.name.c_str(), builtin))
if (builtin == BUILTIN_UNIFORMS_PER_DRAW) { {
if (builtin == BUILTIN_UNIFORMS_PER_DRAW)
builtinUniformDataOffset = offset; builtinUniformDataOffset = offset;
}
builtinUniformInfo[builtin] = &uniformInfos[u.name]; builtinUniformInfo[builtin] = &uniformInfos[u.name];
} }
} }
} }
void Shader::compileShaders() { void Shader::compileShaders()
{
using namespace glslang; using namespace glslang;
using namespace spirv_cross; using namespace spirv_cross;
@@ -508,11 +532,10 @@ void Shader::compileShaders() {
auto program = new TProgram(); auto program = new TProgram();
gfx = Module::getInstance<Graphics>(Module::ModuleType::M_GRAPHICS);
auto vgfx = (Graphics*)gfx;
device = vgfx->getDevice(); device = vgfx->getDevice();
for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++) { for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++)
{
if (!stages[i]) if (!stages[i])
continue; continue;
@@ -543,7 +566,8 @@ void Shader::compileShaders() {
bool forceDefault = false; bool forceDefault = false;
bool forwardCompat = true; bool forwardCompat = true;
if (!tshader->parse(&defaultTBuiltInResource, defaultVersion, defaultProfile, forceDefault, forwardCompat, EShMsgSuppressWarnings)) { if (!tshader->parse(&defaultTBuiltInResource, defaultVersion, defaultProfile, forceDefault, forwardCompat, EShMsgSuppressWarnings))
{
const char* msg1 = tshader->getInfoLog(); const char* msg1 = tshader->getInfoLog();
const char* msg2 = tshader->getInfoDebugLog(); const char* msg2 = tshader->getInfoDebugLog();
@@ -554,17 +578,16 @@ void Shader::compileShaders() {
glslangShaders.push_back(tshader); glslangShaders.push_back(tshader);
} }
if (!program->link(EShMsgDefault)) { if (!program->link(EShMsgDefault))
throw love::Exception("link failed! %s\n", program->getInfoLog()); throw love::Exception("link failed! %s\n", program->getInfoLog());
}
if (!program->mapIO()) { if (!program->mapIO())
throw love::Exception("mapIO failed"); throw love::Exception("mapIO failed");
}
uniformInfos.clear(); uniformInfos.clear();
for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++) { for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++)
{
auto shaderStage = (ShaderStageType)i; auto shaderStage = (ShaderStageType)i;
auto glslangStage = getGlslShaderType(shaderStage); auto glslangStage = getGlslShaderType(shaderStage);
auto intermediate = program->getIntermediate(glslangStage); auto intermediate = program->getIntermediate(glslangStage);
@@ -586,8 +609,7 @@ void Shader::compileShaders() {
createInfo.codeSize = spirv.size() * sizeof(uint32_t); createInfo.codeSize = spirv.size() * sizeof(uint32_t);
createInfo.pCode = spirv.data(); createInfo.pCode = spirv.data();
Graphics* vkGfx = (Graphics*)gfx; auto device = vgfx->getDevice();
auto device = vkGfx->getDevice();
VkShaderModule shaderModule; VkShaderModule shaderModule;
@@ -612,8 +634,10 @@ void Shader::compileShaders() {
auto shaderResources = comp.get_shader_resources(active); auto shaderResources = comp.get_shader_resources(active);
comp.set_enabled_interface_variables(std::move(active)); comp.set_enabled_interface_variables(std::move(active));
for (const auto& resource : shaderResources.uniform_buffers) { for (const auto& resource : shaderResources.uniform_buffers)
if (resource.name == "gl_DefaultUniformBlock") { {
if (resource.name == "gl_DefaultUniformBlock")
{
const auto& type = comp.get_type(resource.base_type_id); const auto& type = comp.get_type(resource.base_type_id);
size_t uniformBufferObjectSize = comp.get_declared_struct_size(type); size_t uniformBufferObjectSize = comp.get_declared_struct_size(type);
auto defaultUniformBlockSize = comp.get_declared_struct_size(type); auto defaultUniformBlockSize = comp.get_declared_struct_size(type);
@@ -625,12 +649,12 @@ void Shader::compileShaders() {
std::string basename(""); std::string basename("");
buildLocalUniforms(comp, type, 0, basename); buildLocalUniforms(comp, type, 0, basename);
} }
else { else
throw love::Exception("unimplemented: non default uniform blocks."); throw love::Exception("unimplemented: non default uniform blocks.");
}
} }
for (const auto& r : shaderResources.sampled_images) { for (const auto& r : shaderResources.sampled_images)
{
const SPIRType& basetype = comp.get_type(r.base_type_id); const SPIRType& basetype = comp.get_type(r.base_type_id);
const SPIRType& type = comp.get_type(r.type_id); const SPIRType& type = comp.get_type(r.type_id);
const SPIRType& imagetype = comp.get_type(basetype.image.type); const SPIRType& imagetype = comp.get_type(basetype.image.type);
@@ -643,7 +667,8 @@ void Shader::compileShaders() {
info.isDepthSampler = type.image.depth; info.isDepthSampler = type.image.depth;
info.components = 1; info.components = 1;
switch (imagetype.basetype) { switch (imagetype.basetype)
{
case SPIRType::Float: case SPIRType::Float:
info.dataBaseType = DATA_BASETYPE_FLOAT; info.dataBaseType = DATA_BASETYPE_FLOAT;
break; break;
@@ -657,7 +682,8 @@ void Shader::compileShaders() {
break; break;
} }
switch (basetype.image.dim) { switch (basetype.image.dim)
{
case spv::Dim2D: case spv::Dim2D:
info.textureType = basetype.image.arrayed ? TEXTURE_2D_ARRAY : TEXTURE_2D; info.textureType = basetype.image.arrayed ? TEXTURE_2D_ARRAY : TEXTURE_2D;
info.textures = new love::graphics::Texture * [info.count]; info.textures = new love::graphics::Texture * [info.count];
@@ -679,7 +705,8 @@ void Shader::compileShaders() {
throw love::Exception("unknown dim"); throw love::Exception("unknown dim");
} }
if (info.baseType == UNIFORM_SAMPLER) { if (info.baseType == UNIFORM_SAMPLER)
{
auto tex = vgfx->getDefaultTexture(); auto tex = vgfx->getDefaultTexture();
for (int i = 0; i < info.count; i++) { for (int i = 0; i < info.count; i++) {
info.textures[i] = tex; info.textures[i] = tex;
@@ -687,18 +714,17 @@ void Shader::compileShaders() {
} }
} }
// fixme // fixme
else if (info.baseType == UNIFORM_TEXELBUFFER) { else if (info.baseType == UNIFORM_TEXELBUFFER)
throw love::Exception("texel buffers not supported yet"); throw love::Exception("texel buffers not supported yet");
}
uniformInfos[r.name] = info; uniformInfos[r.name] = info;
BuiltinUniform builtin; BuiltinUniform builtin;
if (getConstant(r.name.c_str(), builtin)) { if (getConstant(r.name.c_str(), builtin))
builtinUniformInfo[builtin] = &uniformInfos[info.name]; builtinUniformInfo[builtin] = &uniformInfos[info.name];
}
} }
for (const auto& r : shaderResources.storage_buffers) { for (const auto& r : shaderResources.storage_buffers)
{
const auto& type = comp.get_type(r.type_id); const auto& type = comp.get_type(r.type_id);
UniformInfo u{}; UniformInfo u{};
@@ -709,27 +735,27 @@ void Shader::compileShaders() {
u.location = comp.get_decoration(r.id, spv::DecorationBinding); u.location = comp.get_decoration(r.id, spv::DecorationBinding);
const auto reflectionit = validationReflection.storageBuffers.find(u.name); const auto reflectionit = validationReflection.storageBuffers.find(u.name);
if (reflectionit != validationReflection.storageBuffers.end()) { if (reflectionit != validationReflection.storageBuffers.end())
{
u.bufferStride = reflectionit->second.stride; u.bufferStride = reflectionit->second.stride;
u.bufferMemberCount = reflectionit->second.memberCount; u.bufferMemberCount = reflectionit->second.memberCount;
u.access = reflectionit->second.access; u.access = reflectionit->second.access;
} }
else { else
continue; continue;
}
// todo: some stuff missing // todo: some stuff missing
u.buffers = new love::graphics::Buffer * [u.count]; u.buffers = new love::graphics::Buffer * [u.count];
for (int i = 0; i < u.count; i++) { for (int i = 0; i < u.count; i++)
u.buffers[i] = nullptr; u.buffers[i] = nullptr;
}
uniformInfos[u.name] = u; uniformInfos[u.name] = u;
} }
for (const auto& r : shaderResources.storage_images) { for (const auto& r : shaderResources.storage_images)
{
const auto& type = comp.get_type(r.type_id); const auto& type = comp.get_type(r.type_id);
UniformInfo u{}; UniformInfo u{};
@@ -740,53 +766,53 @@ void Shader::compileShaders() {
u.textures = new love::graphics::Texture * [u.count]; u.textures = new love::graphics::Texture * [u.count];
u.location = comp.get_decoration(r.id, spv::DecorationBinding); u.location = comp.get_decoration(r.id, spv::DecorationBinding);
for (int i = 0; i < u.count; i++) { for (int i = 0; i < u.count; i++)
u.textures[i] = nullptr; u.textures[i] = nullptr;
}
// some stuff missing ? // some stuff missing ?
uniformInfos[u.name] = u; uniformInfos[u.name] = u;
} }
if (shaderStage == SHADERSTAGE_VERTEX) { if (shaderStage == SHADERSTAGE_VERTEX)
for (const auto& r : shaderResources.stage_inputs) { for (const auto& r : shaderResources.stage_inputs)
{
const auto& name = r.name; const auto& name = r.name;
const int attributeLocation = static_cast<int>(comp.get_decoration(r.id, spv::DecorationLocation)); const int attributeLocation = static_cast<int>(comp.get_decoration(r.id, spv::DecorationLocation));
attributes[name] = attributeLocation; attributes[name] = attributeLocation;
} }
}
} }
delete program; delete program;
for (auto shader : glslangShaders) { for (auto shader : glslangShaders)
delete shader; delete shader;
}
} }
void Shader::createDescriptorSetLayout() { void Shader::createDescriptorSetLayout()
{
std::vector<VkDescriptorSetLayoutBinding> bindings; std::vector<VkDescriptorSetLayoutBinding> bindings;
for (auto const& [key, val] : uniformInfos) { for (auto const& [key, val] : uniformInfos)
{
auto type = Vulkan::getDescriptorType(val.baseType); auto type = Vulkan::getDescriptorType(val.baseType);
if (type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) { if (type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
{
VkDescriptorSetLayoutBinding layoutBinding{}; VkDescriptorSetLayoutBinding layoutBinding{};
layoutBinding.binding = val.location; layoutBinding.binding = val.location;
layoutBinding.descriptorType = type; layoutBinding.descriptorType = type;
layoutBinding.descriptorCount = val.count; layoutBinding.descriptorCount = val.count;
if (isCompute) { if (isCompute)
layoutBinding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; layoutBinding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
} else
else {
layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
}
bindings.push_back(layoutBinding); bindings.push_back(layoutBinding);
} }
} }
if (!localUniformStagingData.empty()) { if (!localUniformStagingData.empty())
{
VkDescriptorSetLayoutBinding uniformBinding{}; VkDescriptorSetLayoutBinding uniformBinding{};
uniformBinding.binding = uniformLocation; uniformBinding.binding = uniformLocation;
uniformBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; uniformBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
@@ -805,23 +831,23 @@ void Shader::createDescriptorSetLayout() {
if (pfn_vkCmdPushDescriptorSetKHR) if (pfn_vkCmdPushDescriptorSetKHR)
layoutInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; layoutInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) { if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS)
throw love::Exception("failed to create descriptor set layout"); throw love::Exception("failed to create descriptor set layout");
}
} }
void Shader::createPipelineLayout() { void Shader::createPipelineLayout()
{
VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1; pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout; pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
pipelineLayoutInfo.pushConstantRangeCount = 0; pipelineLayoutInfo.pushConstantRangeCount = 0;
if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) { if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS)
throw love::Exception("failed to create pipeline layout"); throw love::Exception("failed to create pipeline layout");
}
if (isCompute) { if (isCompute)
{
assert(shaderStages.size() == 1); assert(shaderStages.size() == 1);
VkComputePipelineCreateInfo computeInfo{}; VkComputePipelineCreateInfo computeInfo{};
@@ -829,38 +855,39 @@ void Shader::createPipelineLayout() {
computeInfo.stage = shaderStages.at(0); computeInfo.stage = shaderStages.at(0);
computeInfo.layout = pipelineLayout; computeInfo.layout = pipelineLayout;
if (vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &computeInfo, nullptr, &computePipeline) != VK_SUCCESS) { if (vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &computeInfo, nullptr, &computePipeline) != VK_SUCCESS)
throw love::Exception("failed to create compute pipeline"); throw love::Exception("failed to create compute pipeline");
}
} }
} }
void Shader::createStreamBuffers() { void Shader::createStreamBuffers()
auto vgfx = (Graphics*)gfx; {
const auto numImagesInFlight = vgfx->getNumImagesInFlight(); const auto numImagesInFlight = vgfx->getNumImagesInFlight();
streamBuffers.resize(numImagesInFlight); streamBuffers.resize(numImagesInFlight);
for (uint32_t i = 0; i < numImagesInFlight; i++) { for (uint32_t i = 0; i < numImagesInFlight; i++)
streamBuffers[i].push_back(new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned)); streamBuffers[i].push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned));
}
} }
void Shader::setVideoTextures(graphics::Texture* ytexture, graphics::Texture* cbtexture, graphics::Texture* crtexture) { void Shader::setVideoTextures(graphics::Texture* ytexture, graphics::Texture* cbtexture, graphics::Texture* crtexture)
{
// if the shader doesn't actually use these textures they might get optimized out // if the shader doesn't actually use these textures they might get optimized out
// in that case this function becomes a noop. // in that case this function becomes a noop.
if (builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_Y] != nullptr) { if (builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_Y] != nullptr)
{
auto oldTexture = builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_Y]->textures[0]; auto oldTexture = builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_Y]->textures[0];
ytexture->retain(); ytexture->retain();
oldTexture->release(); oldTexture->release();
builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_Y]->textures[0] = ytexture; builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_Y]->textures[0] = ytexture;
} }
if (builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CB] != nullptr) { if (builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CB] != nullptr)
{
auto oldTexture = builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CB]->textures[0]; auto oldTexture = builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CB]->textures[0];
cbtexture->retain(); cbtexture->retain();
oldTexture->release(); oldTexture->release();
builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CB]->textures[0] = cbtexture; builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CB]->textures[0] = cbtexture;
} }
if (builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CR] != nullptr) { if (builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CR] != nullptr)
{
auto oldTexture = builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CR]->textures[0]; auto oldTexture = builtinUniformInfo[BUILTIN_TEXTURE_VIDEO_CR]->textures[0];
crtexture->retain(); crtexture->retain();
oldTexture->release(); oldTexture->release();
@@ -868,19 +895,23 @@ void Shader::setVideoTextures(graphics::Texture* ytexture, graphics::Texture* cb
} }
} }
bool Shader::hasUniform(const std::string& name) const { bool Shader::hasUniform(const std::string& name) const
{
return uniformInfos.find(name) != uniformInfos.end(); return uniformInfos.find(name) != uniformInfos.end();
} }
void Shader::setUniformData(BuiltinUniformData& data) { void Shader::setUniformData(BuiltinUniformData& data)
{
char* ptr = (char*) builtinUniformInfo[BUILTIN_UNIFORMS_PER_DRAW]->data + builtinUniformDataOffset; char* ptr = (char*) builtinUniformInfo[BUILTIN_UNIFORMS_PER_DRAW]->data + builtinUniformDataOffset;
memcpy(ptr, &data, sizeof(BuiltinUniformData)); memcpy(ptr, &data, sizeof(BuiltinUniformData));
} }
void Shader::setMainTex(graphics::Texture* texture) { void Shader::setMainTex(graphics::Texture* texture)
{
// if the shader doesn't actually use the texture it might get optimized out // if the shader doesn't actually use the texture it might get optimized out
// in that case this function becomes a noop. // in that case this function becomes a noop.
if (builtinUniformInfo[BUILTIN_TEXTURE_MAIN] != nullptr) { if (builtinUniformInfo[BUILTIN_TEXTURE_MAIN] != nullptr)
{
auto oldTexture = builtinUniformInfo[BUILTIN_TEXTURE_MAIN]->textures[0]; auto oldTexture = builtinUniformInfo[BUILTIN_TEXTURE_MAIN]->textures[0];
texture->retain(); texture->retain();
oldTexture->release(); oldTexture->release();
@@ -888,8 +919,10 @@ void Shader::setMainTex(graphics::Texture* texture) {
} }
} }
VkDescriptorSet Shader::allocateDescriptorSet() { VkDescriptorSet Shader::allocateDescriptorSet()
if (freeDescriptorSets.empty()) { {
if (freeDescriptorSets.empty())
{
// fixme: we can optimize this, since sizes should never change for a given shader. // fixme: we can optimize this, since sizes should never change for a given shader.
std::vector<VkDescriptorPoolSize> sizes; std::vector<VkDescriptorPoolSize> sizes;
@@ -899,7 +932,8 @@ VkDescriptorSet Shader::allocateDescriptorSet() {
sizes.push_back(size); sizes.push_back(size);
for (const auto& [key, val] : uniformInfos) { for (const auto& [key, val] : uniformInfos)
{
VkDescriptorPoolSize size{}; VkDescriptorPoolSize size{};
auto type = Vulkan::getDescriptorType(val.baseType); auto type = Vulkan::getDescriptorType(val.baseType);
if (type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) { if (type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) {
@@ -917,9 +951,8 @@ VkDescriptorSet Shader::allocateDescriptorSet() {
createInfo.pPoolSizes = sizes.data(); createInfo.pPoolSizes = sizes.data();
VkDescriptorPool pool; VkDescriptorPool pool;
if (vkCreateDescriptorPool(device, &createInfo, nullptr, &pool) != VK_SUCCESS) { if (vkCreateDescriptorPool(device, &createInfo, nullptr, &pool) != VK_SUCCESS)
throw love::Exception("failed to create descriptor pool"); throw love::Exception("failed to create descriptor pool");
}
descriptorPools.push_back(pool); descriptorPools.push_back(pool);
std::vector<VkDescriptorSetLayout> layouts(DESCRIPTOR_POOL_SIZE, descriptorSetLayout); std::vector<VkDescriptorSetLayout> layouts(DESCRIPTOR_POOL_SIZE, descriptorSetLayout);
@@ -933,19 +966,18 @@ VkDescriptorSet Shader::allocateDescriptorSet() {
std::vector<VkDescriptorSet> descriptorSet; std::vector<VkDescriptorSet> descriptorSet;
descriptorSet.resize(DESCRIPTOR_POOL_SIZE); descriptorSet.resize(DESCRIPTOR_POOL_SIZE);
VkResult result = vkAllocateDescriptorSets(device, &allocInfo, descriptorSet.data()); VkResult result = vkAllocateDescriptorSets(device, &allocInfo, descriptorSet.data());
if (result != VK_SUCCESS) { if (result != VK_SUCCESS)
throw love::Exception("failed to allocate descriptor set"); throw love::Exception("failed to allocate descriptor set");
}
for (const auto ds : descriptorSet) { for (const auto ds : descriptorSet)
freeDescriptorSets.push(ds); freeDescriptorSets.push(ds);
}
} }
auto ds = freeDescriptorSets.front(); auto ds = freeDescriptorSets.front();
freeDescriptorSets.pop(); freeDescriptorSets.pop();
return ds; return ds;
} }
} // vulkan } // vulkan
} // graphics } // graphics
} // love } // love
+22 -11
View File
@@ -1,13 +1,15 @@
#ifndef LOVE_GRAPHICS_VULKAN_SHADER_H #pragma once
#define LOVE_GRAPHICS_VULKAN_SHADER_H
// LÖVE
#include <graphics/Shader.h> #include <graphics/Shader.h>
#include <graphics/vulkan/ShaderStage.h> #include <graphics/vulkan/ShaderStage.h>
#include "Vulkan.h" #include "Vulkan.h"
// Libraries
#include "VulkanWrapper.h" #include "VulkanWrapper.h"
#include "libraries/spirv_cross/spirv_reflect.hpp" #include "libraries/spirv_cross/spirv_reflect.hpp"
// C++
#include <map> #include <map>
#include <memory> #include <memory>
#include <iostream> #include <iostream>
@@ -15,10 +17,19 @@
#include <queue> #include <queue>
namespace love { namespace love
namespace graphics { {
namespace vulkan { namespace graphics
class Shader final : public graphics::Shader, public Volatile { {
namespace vulkan
{
class Graphics;
class Shader final
: public graphics::Shader
, public Volatile
{
public: public:
Shader(StrongRef<love::graphics::ShaderStage> stages[]); Shader(StrongRef<love::graphics::ShaderStage> stages[]);
virtual ~Shader(); virtual ~Shader();
@@ -94,7 +105,8 @@ private:
std::vector<VkPipelineShaderStageCreateInfo> shaderStages; std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
std::vector<VkShaderModule> shaderModules; std::vector<VkShaderModule> shaderModules;
Graphics* gfx;
Graphics *vgfx = nullptr;
VkDevice device; VkDevice device;
bool isCompute = false; bool isCompute = false;
@@ -113,8 +125,7 @@ private:
uint32_t currentUsedUniformStreamBuffersCount; uint32_t currentUsedUniformStreamBuffersCount;
uint32_t currentUsedDescriptorSetsCount; uint32_t currentUsedDescriptorSetsCount;
}; };
}
}
}
#endif }
}
}
+13 -7
View File
@@ -1,23 +1,29 @@
#include "ShaderStage.h" #include "ShaderStage.h"
#include "Graphics.h" #include "Graphics.h"
#include "libraries/glslang/glslang/Public/ShaderLang.h" #include "libraries/glslang/glslang/Public/ShaderLang.h"
#include "libraries/glslang/SPIRV/GlslangToSpv.h" #include "libraries/glslang/SPIRV/GlslangToSpv.h"
#include <iostream>
#include <fstream> #include <fstream>
#include <cstdio> #include <cstdio>
namespace love
{
namespace graphics
{
namespace vulkan
{
namespace love { ShaderStage::ShaderStage(love::graphics::Graphics *gfx, ShaderStageType stage, const std::string &glsl, bool gles, const std::string &cachekey)
namespace graphics {
namespace vulkan {
ShaderStage::ShaderStage(love::graphics::Graphics* gfx, ShaderStageType stage, const std::string& glsl, bool gles, const std::string& cachekey)
: love::graphics::ShaderStage(gfx, stage, glsl, gles, cachekey) { : love::graphics::ShaderStage(gfx, stage, glsl, gles, cachekey) {
// the compilation is done in Shader. // the compilation is done in Shader.
} }
ptrdiff_t ShaderStage::getHandle() const
{
return 0;
}
} // love } // love
} // graphics } // graphics
} // vulkan } // vulkan
+15 -14
View File
@@ -1,24 +1,25 @@
#ifndef LOVE_GRAPHICS_VULKAN_SHADERSTAGE_H #pragma once
#define LOVE_GRAPHICS_VULKAN_SHADERSTAGE_H
#include "graphics/ShaderStage.h" #include "graphics/ShaderStage.h"
#include "modules/graphics/Graphics.h" #include "modules/graphics/Graphics.h"
#include "VulkanWrapper.h" #include "VulkanWrapper.h"
namespace love { namespace love
namespace graphics { {
namespace vulkan { namespace graphics
class ShaderStage final : public graphics::ShaderStage { {
namespace vulkan
{
class ShaderStage final : public graphics::ShaderStage
{
public: public:
ShaderStage(love::graphics::Graphics* gfx, ShaderStageType stage, const std::string& glsl, bool gles, const std::string& cachekey); ShaderStage(love::graphics::Graphics *gfx, ShaderStageType stage, const std::string &glsl, bool gles, const std::string &cachekey);
ptrdiff_t getHandle() const { ptrdiff_t getHandle() const override;
return 0;
}
}; };
}
}
}
#endif }
}
}
+35 -16
View File
@@ -3,11 +3,17 @@
#include "Graphics.h" #include "Graphics.h"
namespace love { namespace love
namespace graphics { {
namespace vulkan { namespace graphics
static VkBufferUsageFlags getUsageFlags(BufferUsage mode) { {
switch (mode) { namespace vulkan
{
static VkBufferUsageFlags getUsageFlags(BufferUsage mode)
{
switch (mode)
{
case BUFFERUSAGE_VERTEX: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; case BUFFERUSAGE_VERTEX: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
case BUFFERUSAGE_INDEX: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT; case BUFFERUSAGE_INDEX: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
case BUFFERUSAGE_UNIFORM: return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; case BUFFERUSAGE_UNIFORM: return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
@@ -16,13 +22,15 @@ static VkBufferUsageFlags getUsageFlags(BufferUsage mode) {
} }
} }
StreamBuffer::StreamBuffer(graphics::Graphics* gfx, BufferUsage mode, size_t size) StreamBuffer::StreamBuffer(graphics::Graphics *gfx, BufferUsage mode, size_t size)
: love::graphics::StreamBuffer(mode, size), gfx(gfx) { : love::graphics::StreamBuffer(mode, size)
, vgfx(dynamic_cast<Graphics*>(gfx))
{
loadVolatile(); loadVolatile();
} }
bool StreamBuffer::loadVolatile() { bool StreamBuffer::loadVolatile()
Graphics* vgfx = (Graphics*)gfx; {
allocator = vgfx->getVmaAllocator(); allocator = vgfx->getVmaAllocator();
VkBufferCreateInfo bufferInfo{}; VkBufferCreateInfo bufferInfo{};
@@ -42,37 +50,48 @@ bool StreamBuffer::loadVolatile() {
return true; return true;
} }
void StreamBuffer::unloadVolatile() { void StreamBuffer::unloadVolatile()
{
if (buffer == VK_NULL_HANDLE) if (buffer == VK_NULL_HANDLE)
return; return;
auto vgfx = (Graphics*)gfx;
vgfx->queueCleanUp([allocator=allocator, buffer=buffer, allocation=allocation](){ vgfx->queueCleanUp([allocator=allocator, buffer=buffer, allocation=allocation](){
vmaDestroyBuffer(allocator, buffer, allocation); vmaDestroyBuffer(allocator, buffer, allocation);
}); });
buffer = VK_NULL_HANDLE; buffer = VK_NULL_HANDLE;
} }
StreamBuffer::~StreamBuffer() { StreamBuffer::~StreamBuffer()
{
unloadVolatile(); unloadVolatile();
} }
love::graphics::StreamBuffer::MapInfo StreamBuffer::map(size_t minsize) { ptrdiff_t StreamBuffer::getHandle() const
{
return (ptrdiff_t) buffer;
}
love::graphics::StreamBuffer::MapInfo StreamBuffer::map(size_t minsize)
{
(void)minsize; (void)minsize;
return love::graphics::StreamBuffer::MapInfo((uint8*) allocInfo.pMappedData + usedGPUMemory, getSize()); return love::graphics::StreamBuffer::MapInfo((uint8*) allocInfo.pMappedData + usedGPUMemory, getSize());
} }
size_t StreamBuffer::unmap(size_t usedSize) { size_t StreamBuffer::unmap(size_t usedSize)
{
return usedGPUMemory; return usedGPUMemory;
} }
void StreamBuffer::markUsed(size_t usedSize) { void StreamBuffer::markUsed(size_t usedSize)
{
usedGPUMemory += usedSize; usedGPUMemory += usedSize;
} }
void StreamBuffer::nextFrame() { void StreamBuffer::nextFrame()
{
usedGPUMemory = 0; usedGPUMemory = 0;
} }
} // vulkan } // vulkan
} // graphics } // graphics
} // love } // love
+18 -13
View File
@@ -1,5 +1,4 @@
#ifndef LOVE_GRAPHICS_VULKAN_STREAMBUFFER_H #pragma once
#define LOVE_GRAPHICS_VULKAN_STREAMBUFFER_H
#include "graphics/Volatile.h" #include "graphics/Volatile.h"
#include "modules/graphics/StreamBuffer.h" #include "modules/graphics/StreamBuffer.h"
@@ -7,12 +6,21 @@
#include "VulkanWrapper.h" #include "VulkanWrapper.h"
namespace love { namespace love
namespace graphics { {
namespace vulkan { namespace graphics
class StreamBuffer : public love::graphics::StreamBuffer, public graphics::Volatile { {
namespace vulkan
{
class Graphics;
class StreamBuffer
: public love::graphics::StreamBuffer
, public graphics::Volatile
{
public: public:
StreamBuffer(graphics::Graphics* gfx, BufferUsage mode, size_t size); StreamBuffer(graphics::Graphics *gfx, BufferUsage mode, size_t size);
virtual ~StreamBuffer(); virtual ~StreamBuffer();
virtual bool loadVolatile() override; virtual bool loadVolatile() override;
@@ -25,12 +33,10 @@ public:
void nextFrame() override; void nextFrame() override;
ptrdiff_t getHandle() const override { ptrdiff_t getHandle() const override;
return (ptrdiff_t) buffer;
}
private: private:
graphics::Graphics* gfx; Graphics *vgfx = nullptr;
VmaAllocator allocator; VmaAllocator allocator;
VmaAllocation allocation; VmaAllocation allocation;
VmaAllocationInfo allocInfo; VmaAllocationInfo allocInfo;
@@ -38,8 +44,7 @@ private:
size_t usedGPUMemory; size_t usedGPUMemory;
}; };
} // vulkan } // vulkan
} // graphics } // graphics
} // love } // love
#endif
+85 -50
View File
@@ -4,22 +4,26 @@
#include <limits> #include <limits>
// make vulkan::Graphics functions available namespace love
#define vgfx ((Graphics*)gfx) {
namespace graphics
{
namespace vulkan
{
namespace love { Texture::Texture(love::graphics::Graphics *gfx, const Settings &settings, const Slices *data)
namespace graphics { : love::graphics::Texture(gfx, settings, data)
namespace vulkan { , vgfx(dynamic_cast<Graphics*>(gfx))
Texture::Texture(love::graphics::Graphics* gfx, const Settings& settings, const Slices* data) , slices(settings.type)
: love::graphics::Texture(gfx, settings, data), gfx(gfx), slices(settings.type) { {
if (data) { if (data)
slices = *data; slices = *data;
}
loadVolatile(); loadVolatile();
} }
bool Texture::loadVolatile() { bool Texture::loadVolatile()
{
allocator = vgfx->getVmaAllocator(); allocator = vgfx->getVmaAllocator();
device = vgfx->getDevice(); device = vgfx->getDevice();
@@ -44,10 +48,10 @@ bool Texture::loadVolatile() {
layerCount = 1; layerCount = 1;
if (texType == TEXTURE_2D_ARRAY) { if (texType == TEXTURE_2D_ARRAY)
layerCount = getLayerCount(); layerCount = getLayerCount();
} else if (texType == TEXTURE_CUBE)
else if (texType == TEXTURE_CUBE) { {
layerCount = 6; layerCount = 6;
createFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; createFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
} }
@@ -70,9 +74,8 @@ bool Texture::loadVolatile() {
VmaAllocationCreateInfo imageAllocationCreateInfo{}; VmaAllocationCreateInfo imageAllocationCreateInfo{};
if (vmaCreateImage(allocator, &imageInfo, &imageAllocationCreateInfo, &textureImage, &textureImageAllocation, nullptr) != VK_SUCCESS) { if (vmaCreateImage(allocator, &imageInfo, &imageAllocationCreateInfo, &textureImage, &textureImageAllocation, nullptr) != VK_SUCCESS)
throw love::Exception("failed to create image"); throw love::Exception("failed to create image");
}
auto commandBuffer = vgfx->getDataTransferCommandBuffer(); auto commandBuffer = vgfx->getDataTransferCommandBuffer();
@@ -90,37 +93,36 @@ bool Texture::loadVolatile() {
bool hasdata = slices.get(0, 0) != nullptr; bool hasdata = slices.get(0, 0) != nullptr;
if (hasdata) { if (hasdata)
for (int mip = 0; mip < layerCount; mip++) { for (int mip = 0; mip < layerCount; mip++)
{
// fixme: deal with compressed images. // fixme: deal with compressed images.
int sliceCount; int sliceCount;
if (texType == TEXTURE_CUBE) { if (texType == TEXTURE_CUBE)
sliceCount = 6; sliceCount = 6;
} else { else
sliceCount = slices.getSliceCount(); sliceCount = slices.getSliceCount();
} for (int slice = 0; slice < sliceCount; slice++)
for (int slice = 0; slice < sliceCount; slice++) { {
auto* id = slices.get(slice, mip); auto* id = slices.get(slice, mip);
if (id != nullptr) { if (id != nullptr)
uploadImageData(id, mip, slice, 0, 0); uploadImageData(id, mip, slice, 0, 0);
}
} }
} }
} else { else
clear(); clear();
}
createTextureImageView(); createTextureImageView();
textureSampler = vgfx->getCachedSampler(samplerState); textureSampler = vgfx->getCachedSampler(samplerState);
if (slices.getMipmapCount() <= 1 && getMipmapsMode() != MIPMAPS_NONE) { if (slices.getMipmapCount() <= 1 && getMipmapsMode() != MIPMAPS_NONE)
generateMipmaps(); generateMipmaps();
}
return true; return true;
} }
void Texture::unloadVolatile() { void Texture::unloadVolatile()
{
if (textureImage == VK_NULL_HANDLE) if (textureImage == VK_NULL_HANDLE)
return; return;
@@ -137,20 +139,44 @@ void Texture::unloadVolatile() {
textureImage = VK_NULL_HANDLE; textureImage = VK_NULL_HANDLE;
} }
Texture::~Texture() { Texture::~Texture()
{
unloadVolatile(); unloadVolatile();
} }
void Texture::setSamplerState(const SamplerState &s) { ptrdiff_t Texture::getRenderTargetHandle() const
{
return (ptrdiff_t)textureImageView;
}
ptrdiff_t Texture::getSamplerHandle() const
{
return (ptrdiff_t)textureSampler;
}
int Texture::getMSAA() const
{
return 0;
}
ptrdiff_t Texture::getHandle() const
{
return (ptrdiff_t)textureImage;
}
void Texture::setSamplerState(const SamplerState &s)
{
love::graphics::Texture::setSamplerState(s); love::graphics::Texture::setSamplerState(s);
textureSampler = vgfx->getCachedSampler(s); textureSampler = vgfx->getCachedSampler(s);
} }
VkImageLayout Texture::getImageLayout() const { VkImageLayout Texture::getImageLayout() const
{
return imageLayout; return imageLayout;
} }
void Texture::createTextureImageView() { void Texture::createTextureImageView()
{
auto vulkanFormat = Vulkan::getTextureFormat(format); auto vulkanFormat = Vulkan::getTextureFormat(format);
VkImageViewCreateInfo viewInfo{}; VkImageViewCreateInfo viewInfo{};
@@ -168,12 +194,12 @@ void Texture::createTextureImageView() {
viewInfo.components.b = vulkanFormat.swizzleB; viewInfo.components.b = vulkanFormat.swizzleB;
viewInfo.components.a = vulkanFormat.swizzleA; viewInfo.components.a = vulkanFormat.swizzleA;
if (vkCreateImageView(device, &viewInfo, nullptr, &textureImageView) != VK_SUCCESS) { if (vkCreateImageView(device, &viewInfo, nullptr, &textureImageView) != VK_SUCCESS)
throw love::Exception("could not create texture image view"); throw love::Exception("could not create texture image view");
}
} }
void Texture::clear() { void Texture::clear()
{
auto commandBuffer = vgfx->getDataTransferCommandBuffer(); auto commandBuffer = vgfx->getDataTransferCommandBuffer();
auto clearColor = getClearValue(); auto clearColor = getClearValue();
@@ -185,7 +211,8 @@ void Texture::clear() {
range.baseArrayLayer = 0; range.baseArrayLayer = 0;
range.layerCount = VK_REMAINING_ARRAY_LAYERS; range.layerCount = VK_REMAINING_ARRAY_LAYERS;
if (imageLayout != VK_IMAGE_LAYOUT_GENERAL) { if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
{
Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
0, range.levelCount, 0, range.layerCount); 0, range.levelCount, 0, range.layerCount);
@@ -196,16 +223,17 @@ void Texture::clear() {
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
0, range.levelCount, 0, range.layerCount); 0, range.levelCount, 0, range.layerCount);
} }
else { else
vkCmdClearColorImage(commandBuffer, textureImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &range); vkCmdClearColorImage(commandBuffer, textureImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &range);
}
} }
VkClearColorValue Texture::getClearValue() { VkClearColorValue Texture::getClearValue()
{
auto vulkanFormat = Vulkan::getTextureFormat(format); auto vulkanFormat = Vulkan::getTextureFormat(format);
VkClearColorValue clearColor{}; VkClearColorValue clearColor{};
switch (vulkanFormat.internalFormatRepresentation) { switch (vulkanFormat.internalFormatRepresentation)
{
case FORMATREPRESENTATION_FLOAT: case FORMATREPRESENTATION_FLOAT:
clearColor.float32[0] = 0.0f; clearColor.float32[0] = 0.0f;
clearColor.float32[1] = 0.0f; clearColor.float32[1] = 0.0f;
@@ -228,7 +256,8 @@ VkClearColorValue Texture::getClearValue() {
return clearColor; return clearColor;
} }
void Texture::generateMipmapsInternal() { void Texture::generateMipmapsInternal()
{
auto commandBuffer = vgfx->getDataTransferCommandBuffer(); auto commandBuffer = vgfx->getDataTransferCommandBuffer();
if (imageLayout != VK_IMAGE_LAYOUT_GENERAL) if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
@@ -249,7 +278,8 @@ void Texture::generateMipmapsInternal() {
uint32_t mipLevels = static_cast<uint32_t>(getMipmapCount()); uint32_t mipLevels = static_cast<uint32_t>(getMipmapCount());
for (uint32_t i = 1; i < mipLevels; i++) { for (uint32_t i = 1; i < mipLevels; i++)
{
barrier.subresourceRange.baseMipLevel = i - 1; barrier.subresourceRange.baseMipLevel = i - 1;
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
@@ -309,7 +339,8 @@ void Texture::generateMipmapsInternal() {
1, &barrier); 1, &barrier);
} }
void Texture::uploadByteData(PixelFormat pixelformat, const void* data, size_t size, int level, int slice, const Rect& r) { void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r)
{
VkBuffer stagingBuffer; VkBuffer stagingBuffer;
VmaAllocation vmaAllocation; VmaAllocation vmaAllocation;
@@ -346,7 +377,8 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void* data, size_t s
auto commandBuffer = vgfx->getDataTransferCommandBuffer(); auto commandBuffer = vgfx->getDataTransferCommandBuffer();
if (imageLayout != VK_IMAGE_LAYOUT_GENERAL) { if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
{
Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
level, 1, slice, 1); level, 1, slice, 1);
@@ -365,7 +397,7 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void* data, size_t s
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
level, 1, slice, 1); level, 1, slice, 1);
} }
else { else
vkCmdCopyBufferToImage( vkCmdCopyBufferToImage(
commandBuffer, commandBuffer,
stagingBuffer, stagingBuffer,
@@ -374,14 +406,14 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void* data, size_t s
1, 1,
&region &region
); );
}
vgfx->queueCleanUp([allocator = allocator, stagingBuffer, vmaAllocation]() { vgfx->queueCleanUp([allocator = allocator, stagingBuffer, vmaAllocation]() {
vmaDestroyBuffer(allocator, stagingBuffer, vmaAllocation); vmaDestroyBuffer(allocator, stagingBuffer, vmaAllocation);
}); });
} }
void Texture::copyFromBuffer(graphics::Buffer* source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect& rect) { void Texture::copyFromBuffer(graphics::Buffer *source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect &rect)
{
auto commandBuffer = vgfx->getDataTransferCommandBuffer(); auto commandBuffer = vgfx->getDataTransferCommandBuffer();
VkImageSubresourceLayers layers{}; VkImageSubresourceLayers layers{};
@@ -398,7 +430,8 @@ void Texture::copyFromBuffer(graphics::Buffer* source, size_t sourceoffset, int
region.imageExtent.width = static_cast<uint32_t>(rect.w); region.imageExtent.width = static_cast<uint32_t>(rect.w);
region.imageExtent.height = static_cast<uint32_t>(rect.h); region.imageExtent.height = static_cast<uint32_t>(rect.h);
if (imageLayout != VK_IMAGE_LAYOUT_GENERAL) { if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
{
Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
vkCmdCopyBufferToImage(commandBuffer, (VkBuffer)source->getHandle(), textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region); vkCmdCopyBufferToImage(commandBuffer, (VkBuffer)source->getHandle(), textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
@@ -409,7 +442,8 @@ void Texture::copyFromBuffer(graphics::Buffer* source, size_t sourceoffset, int
vkCmdCopyBufferToImage(commandBuffer, (VkBuffer)source->getHandle(), textureImage, VK_IMAGE_LAYOUT_GENERAL, 1, &region); vkCmdCopyBufferToImage(commandBuffer, (VkBuffer)source->getHandle(), textureImage, VK_IMAGE_LAYOUT_GENERAL, 1, &region);
} }
void Texture::copyToBuffer(graphics::Buffer* dest, int slice, int mipmap, const Rect& rect, size_t destoffset, int destwidth, size_t size) { void Texture::copyToBuffer(graphics::Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth, size_t size)
{
auto commandBuffer = vgfx->getReadbackCommandBuffer(); auto commandBuffer = vgfx->getReadbackCommandBuffer();
VkImageSubresourceLayers layers{}; VkImageSubresourceLayers layers{};
@@ -427,7 +461,8 @@ void Texture::copyToBuffer(graphics::Buffer* dest, int slice, int mipmap, const
region.imageExtent.height = static_cast<uint32_t>(rect.h); region.imageExtent.height = static_cast<uint32_t>(rect.h);
region.imageExtent.depth = 1; region.imageExtent.depth = 1;
if (imageLayout != VK_IMAGE_LAYOUT_GENERAL) { if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
{
Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
vkCmdCopyImageToBuffer(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, (VkBuffer) dest->getHandle(), 1, &region); vkCmdCopyImageToBuffer(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, (VkBuffer) dest->getHandle(), 1, &region);
+23 -18
View File
@@ -1,20 +1,26 @@
#ifndef LOVE_GRAPHICS_VULKAN_TEXTURE_H #pragma once
#define LOVE_GRAPHICS_VULKAN_TEXTURE_H
#include "graphics/Texture.h" #include "graphics/Texture.h"
#include "graphics/Volatile.h" #include "graphics/Volatile.h"
#include "VulkanWrapper.h" #include "VulkanWrapper.h"
#include <iostream>
namespace love
{
namespace graphics
{
namespace vulkan
{
namespace love { class Graphics;
namespace graphics {
namespace vulkan { class Texture
class Texture : public graphics::Texture, public Volatile { : public graphics::Texture
, public Volatile
{
public: public:
Texture(love::graphics::Graphics* gfx, const Settings& settings, const Slices* data); Texture(love::graphics::Graphics *gfx, const Settings &settings, const Slices *data);
~Texture(); ~Texture();
virtual bool loadVolatile() override; virtual bool loadVolatile() override;
@@ -24,18 +30,18 @@ public:
VkImageLayout getImageLayout() const; VkImageLayout getImageLayout() const;
void copyFromBuffer(graphics::Buffer* source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect& rect) override; void copyFromBuffer(graphics::Buffer *source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect &rect) override;
void copyToBuffer(graphics::Buffer* dest, int slice, int mipmap, const Rect& rect, size_t destoffset, int destwidth, size_t size) override; void copyToBuffer(graphics::Buffer *dest, int slice, int mipmap, const Rect &rect, size_t destoffset, int destwidth, size_t size) override;
ptrdiff_t getRenderTargetHandle() const override { return (ptrdiff_t)textureImageView; }; ptrdiff_t getRenderTargetHandle() const override;
ptrdiff_t getSamplerHandle() const override { return (ptrdiff_t)textureSampler; }; ptrdiff_t getSamplerHandle() const override;
void uploadByteData(PixelFormat pixelformat, const void* data, size_t size, int level, int slice, const Rect& r) override; void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) override;
void generateMipmapsInternal() override; void generateMipmapsInternal() override;
int getMSAA() const override { return 0; }; int getMSAA() const override;
ptrdiff_t getHandle() const override { return (ptrdiff_t)textureImage; } ptrdiff_t getHandle() const override;
private: private:
void createTextureImageView(); void createTextureImageView();
@@ -43,7 +49,7 @@ private:
VkClearColorValue getClearValue(); VkClearColorValue getClearValue();
graphics::Graphics* gfx = nullptr; Graphics *vgfx = nullptr;
VkDevice device = VK_NULL_HANDLE; VkDevice device = VK_NULL_HANDLE;
VmaAllocator allocator = VK_NULL_HANDLE; VmaAllocator allocator = VK_NULL_HANDLE;
VkImage textureImage = VK_NULL_HANDLE; VkImage textureImage = VK_NULL_HANDLE;
@@ -54,8 +60,7 @@ private:
Slices slices; Slices slices;
int layerCount = 0; int layerCount = 0;
}; };
} // vulkan } // vulkan
} // graphics } // graphics
} // love } // love
#endif
+124 -74
View File
@@ -3,34 +3,45 @@
#include <sstream> #include <sstream>
namespace love { namespace love
namespace graphics { {
namespace vulkan { namespace graphics
{
namespace vulkan
{
static uint32_t numShaderSwitches; static uint32_t numShaderSwitches;
static int vsync = 1; static int vsync = 1;
void Vulkan::shaderSwitch() { void Vulkan::shaderSwitch()
{
numShaderSwitches++; numShaderSwitches++;
} }
uint32_t Vulkan::getNumShaderSwitches() { uint32_t Vulkan::getNumShaderSwitches()
{
return numShaderSwitches; return numShaderSwitches;
} }
void Vulkan::resetShaderSwitches() { void Vulkan::resetShaderSwitches()
{
numShaderSwitches = 0; numShaderSwitches = 0;
} }
void Vulkan::setVsync(int value) { void Vulkan::setVsync(int value)
{
vsync = value; vsync = value;
} }
int Vulkan::getVsync() { int Vulkan::getVsync()
{
return vsync; return vsync;
} }
VkFormat Vulkan::getVulkanVertexFormat(DataFormat format) { VkFormat Vulkan::getVulkanVertexFormat(DataFormat format)
switch (format) { {
switch (format)
{
case DATAFORMAT_FLOAT: case DATAFORMAT_FLOAT:
return VK_FORMAT_R32_SFLOAT; return VK_FORMAT_R32_SFLOAT;
case DATAFORMAT_FLOAT_VEC2: case DATAFORMAT_FLOAT_VEC2:
@@ -110,10 +121,12 @@ VkFormat Vulkan::getVulkanVertexFormat(DataFormat format) {
} }
} }
TextureFormat Vulkan::getTextureFormat(PixelFormat format) { TextureFormat Vulkan::getTextureFormat(PixelFormat format)
{
TextureFormat textureFormat{}; TextureFormat textureFormat{};
switch (format) { switch (format)
{
case PIXELFORMAT_UNKNOWN: case PIXELFORMAT_UNKNOWN:
throw love::Exception("unknown pixel format"); throw love::Exception("unknown pixel format");
case PIXELFORMAT_NORMAL: case PIXELFORMAT_NORMAL:
@@ -353,8 +366,10 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format) {
// values taken from https://pcisig.com/membership/member-companies // values taken from https://pcisig.com/membership/member-companies
// as specified at https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceProperties.html // as specified at https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceProperties.html
std::string Vulkan::getVendorName(uint32_t vendorId) { std::string Vulkan::getVendorName(uint32_t vendorId)
switch (vendorId) { {
switch (vendorId)
{
case 4130: case 4130:
return "AMD"; return "AMD";
case 4318: case 4318:
@@ -376,7 +391,8 @@ std::string Vulkan::getVendorName(uint32_t vendorId) {
} }
} }
std::string Vulkan::getVulkanApiVersion(uint32_t version) { std::string Vulkan::getVulkanApiVersion(uint32_t version)
{
std::stringstream ss; std::stringstream ss;
ss << VK_API_VERSION_MAJOR(version) ss << VK_API_VERSION_MAJOR(version)
@@ -386,8 +402,10 @@ std::string Vulkan::getVulkanApiVersion(uint32_t version) {
return ss.str(); return ss.str();
} }
VkPrimitiveTopology Vulkan::getPrimitiveTypeTopology(graphics::PrimitiveType primitiveType) { VkPrimitiveTopology Vulkan::getPrimitiveTypeTopology(graphics::PrimitiveType primitiveType)
switch (primitiveType) { {
switch (primitiveType)
{
case PRIMITIVE_POINTS: case PRIMITIVE_POINTS:
return VK_PRIMITIVE_TOPOLOGY_POINT_LIST; return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
case PRIMITIVE_TRIANGLES: case PRIMITIVE_TRIANGLES:
@@ -401,8 +419,10 @@ VkPrimitiveTopology Vulkan::getPrimitiveTypeTopology(graphics::PrimitiveType pri
} }
} }
VkBlendFactor Vulkan::getBlendFactor(BlendFactor blendFactor) { VkBlendFactor Vulkan::getBlendFactor(BlendFactor blendFactor)
switch (blendFactor) { {
switch (blendFactor)
{
case BLENDFACTOR_ZERO: case BLENDFACTOR_ZERO:
return VK_BLEND_FACTOR_ZERO; return VK_BLEND_FACTOR_ZERO;
case BLENDFACTOR_ONE: case BLENDFACTOR_ONE:
@@ -430,8 +450,10 @@ VkBlendFactor Vulkan::getBlendFactor(BlendFactor blendFactor) {
} }
} }
VkBlendOp Vulkan::getBlendOp(BlendOperation op) { VkBlendOp Vulkan::getBlendOp(BlendOperation op)
switch (op) { {
switch (op)
{
case BLENDOP_ADD: case BLENDOP_ADD:
return VK_BLEND_OP_ADD; return VK_BLEND_OP_ADD;
case BLENDOP_MAX: case BLENDOP_MAX:
@@ -447,35 +469,34 @@ VkBlendOp Vulkan::getBlendOp(BlendOperation op) {
} }
} }
VkBool32 Vulkan::getBool(bool b) { VkBool32 Vulkan::getBool(bool b)
if (b) { {
if (b)
return VK_TRUE; return VK_TRUE;
} else { else
return VK_FALSE; return VK_FALSE;
}
} }
VkColorComponentFlags Vulkan::getColorMask(ColorChannelMask mask) { VkColorComponentFlags Vulkan::getColorMask(ColorChannelMask mask)
{
VkColorComponentFlags flags = 0; VkColorComponentFlags flags = 0;
if (mask.r) { if (mask.r)
flags |= VK_COLOR_COMPONENT_R_BIT; flags |= VK_COLOR_COMPONENT_R_BIT;
} if (mask.g)
if (mask.g) {
flags |= VK_COLOR_COMPONENT_G_BIT; flags |= VK_COLOR_COMPONENT_G_BIT;
} if (mask.b)
if (mask.b) {
flags |= VK_COLOR_COMPONENT_B_BIT; flags |= VK_COLOR_COMPONENT_B_BIT;
} if (mask.a)
if (mask.a) {
flags |= VK_COLOR_COMPONENT_A_BIT; flags |= VK_COLOR_COMPONENT_A_BIT;
}
return flags; return flags;
} }
VkFrontFace Vulkan::getFrontFace(Winding winding) { VkFrontFace Vulkan::getFrontFace(Winding winding)
switch (winding) { {
switch (winding)
{
case WINDING_CW: case WINDING_CW:
return VK_FRONT_FACE_CLOCKWISE; return VK_FRONT_FACE_CLOCKWISE;
case WINDING_CCW: case WINDING_CCW:
@@ -485,8 +506,10 @@ VkFrontFace Vulkan::getFrontFace(Winding winding) {
} }
} }
VkCullModeFlags Vulkan::getCullMode(CullMode cullmode) { VkCullModeFlags Vulkan::getCullMode(CullMode cullmode)
switch (cullmode) { {
switch (cullmode)
{
case CULL_BACK: case CULL_BACK:
return VK_CULL_MODE_BACK_BIT; return VK_CULL_MODE_BACK_BIT;
case CULL_FRONT: case CULL_FRONT:
@@ -498,8 +521,10 @@ VkCullModeFlags Vulkan::getCullMode(CullMode cullmode) {
} }
} }
VkImageType Vulkan::getImageType(TextureType textureType) { VkImageType Vulkan::getImageType(TextureType textureType)
switch (textureType) { {
switch (textureType)
{
case TEXTURE_2D: case TEXTURE_2D:
case TEXTURE_2D_ARRAY: case TEXTURE_2D_ARRAY:
case TEXTURE_CUBE: case TEXTURE_CUBE:
@@ -511,8 +536,10 @@ VkImageType Vulkan::getImageType(TextureType textureType) {
} }
} }
VkImageViewType Vulkan::getImageViewType(TextureType textureType) { VkImageViewType Vulkan::getImageViewType(TextureType textureType)
switch (textureType) { {
switch (textureType)
{
case TEXTURE_2D: case TEXTURE_2D:
return VK_IMAGE_VIEW_TYPE_2D; return VK_IMAGE_VIEW_TYPE_2D;
case TEXTURE_2D_ARRAY: case TEXTURE_2D_ARRAY:
@@ -526,16 +553,18 @@ VkImageViewType Vulkan::getImageViewType(TextureType textureType) {
} }
} }
VkPolygonMode Vulkan::getPolygonMode(bool wireframe) { VkPolygonMode Vulkan::getPolygonMode(bool wireframe)
if (wireframe) { {
if (wireframe)
return VK_POLYGON_MODE_LINE; return VK_POLYGON_MODE_LINE;
} else { else
return VK_POLYGON_MODE_FILL; return VK_POLYGON_MODE_FILL;
}
} }
VkFilter Vulkan::getFilter(SamplerState::FilterMode mode) { VkFilter Vulkan::getFilter(SamplerState::FilterMode mode)
switch (mode) { {
switch (mode)
{
case SamplerState::FILTER_LINEAR: case SamplerState::FILTER_LINEAR:
return VK_FILTER_LINEAR; return VK_FILTER_LINEAR;
case SamplerState::FILTER_NEAREST: case SamplerState::FILTER_NEAREST:
@@ -545,8 +574,10 @@ VkFilter Vulkan::getFilter(SamplerState::FilterMode mode) {
} }
} }
VkSamplerAddressMode Vulkan::getWrapMode(SamplerState::WrapMode mode) { VkSamplerAddressMode Vulkan::getWrapMode(SamplerState::WrapMode mode)
switch (mode) { {
switch (mode)
{
//fixme: not accounting for different clamps (how does that work in vulkan?) //fixme: not accounting for different clamps (how does that work in vulkan?)
case SamplerState::WRAP_CLAMP: case SamplerState::WRAP_CLAMP:
case SamplerState::WRAP_CLAMP_ZERO: case SamplerState::WRAP_CLAMP_ZERO:
@@ -561,8 +592,10 @@ VkSamplerAddressMode Vulkan::getWrapMode(SamplerState::WrapMode mode) {
} }
} }
VkCompareOp Vulkan::getCompareOp(CompareMode mode) { VkCompareOp Vulkan::getCompareOp(CompareMode mode)
switch (mode) { {
switch (mode)
{
case COMPARE_LESS: case COMPARE_LESS:
return VK_COMPARE_OP_LESS; return VK_COMPARE_OP_LESS;
case COMPARE_LEQUAL: case COMPARE_LEQUAL:
@@ -584,8 +617,10 @@ VkCompareOp Vulkan::getCompareOp(CompareMode mode) {
} }
} }
VkSamplerMipmapMode Vulkan::getMipMapMode(SamplerState::MipmapFilterMode mode) { VkSamplerMipmapMode Vulkan::getMipMapMode(SamplerState::MipmapFilterMode mode)
switch (mode) { {
switch (mode)
{
case SamplerState::MIPMAP_FILTER_NEAREST: case SamplerState::MIPMAP_FILTER_NEAREST:
return VK_SAMPLER_MIPMAP_MODE_NEAREST; return VK_SAMPLER_MIPMAP_MODE_NEAREST;
case SamplerState::MIPMAP_FILTER_NONE: case SamplerState::MIPMAP_FILTER_NONE:
@@ -595,9 +630,10 @@ VkSamplerMipmapMode Vulkan::getMipMapMode(SamplerState::MipmapFilterMode mode) {
} }
} }
VkDescriptorType Vulkan::getDescriptorType(graphics::Shader::UniformType type)
VkDescriptorType Vulkan::getDescriptorType(graphics::Shader::UniformType type) { {
switch (type) { switch (type)
{
case graphics::Shader::UniformType::UNIFORM_FLOAT: case graphics::Shader::UniformType::UNIFORM_FLOAT:
case graphics::Shader::UniformType::UNIFORM_MATRIX: case graphics::Shader::UniformType::UNIFORM_MATRIX:
case graphics::Shader::UniformType::UNIFORM_INT: case graphics::Shader::UniformType::UNIFORM_INT:
@@ -617,8 +653,10 @@ VkDescriptorType Vulkan::getDescriptorType(graphics::Shader::UniformType type) {
} }
} }
VkStencilOp Vulkan::getStencilOp(StencilAction action) { VkStencilOp Vulkan::getStencilOp(StencilAction action)
switch (action) { {
switch (action)
{
case STENCIL_KEEP: case STENCIL_KEEP:
return VK_STENCIL_OP_KEEP; return VK_STENCIL_OP_KEEP;
case STENCIL_ZERO: case STENCIL_ZERO:
@@ -640,8 +678,10 @@ VkStencilOp Vulkan::getStencilOp(StencilAction action) {
} }
} }
VkIndexType Vulkan::getVulkanIndexBufferType(IndexDataType type) { VkIndexType Vulkan::getVulkanIndexBufferType(IndexDataType type)
switch (type) { {
switch (type)
{
case INDEX_UINT16: return VK_INDEX_TYPE_UINT16; case INDEX_UINT16: return VK_INDEX_TYPE_UINT16;
case INDEX_UINT32: return VK_INDEX_TYPE_UINT32; case INDEX_UINT32: return VK_INDEX_TYPE_UINT32;
default: default:
@@ -650,7 +690,8 @@ VkIndexType Vulkan::getVulkanIndexBufferType(IndexDataType type) {
} }
void Vulkan::cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, void Vulkan::cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout,
uint32_t baseLevel, uint32_t levelCount, uint32_t baseLayer, uint32_t layerCount) { uint32_t baseLevel, uint32_t levelCount, uint32_t baseLayer, uint32_t layerCount)
{
VkImageMemoryBarrier barrier{}; VkImageMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = oldLayout; barrier.oldLayout = oldLayout;
@@ -667,63 +708,72 @@ void Vulkan::cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImage ima
VkPipelineStageFlags sourceStage; VkPipelineStageFlags sourceStage;
VkPipelineStageFlags destinationStage; VkPipelineStageFlags destinationStage;
if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{
barrier.srcAccessMask = 0; barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} }
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} }
else if (oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { else if (oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
{
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; sourceStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} }
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} }
else if (oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) { else if (oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
{
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; sourceStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} }
else if (oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { else if (oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; sourceStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} }
else if (oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { else if (oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
{
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; sourceStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
destinationStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; destinationStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
} }
else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
{
barrier.srcAccessMask = 0; barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; destinationStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
} }
else if (oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { else if (oldLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
{
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
barrier.dstAccessMask = 0; barrier.dstAccessMask = 0;
@@ -731,16 +781,16 @@ void Vulkan::cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImage ima
destinationStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; destinationStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
} }
// we use general for images that are both sampled and compute write // we use general for images that are both sampled and compute write
else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_GENERAL) { else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_GENERAL)
{
barrier.srcAccessMask = 0; barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT; destinationStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
} }
else { else
throw std::invalid_argument("unsupported layout transition!"); throw std::invalid_argument("unsupported layout transition!");
}
vkCmdPipelineBarrier( vkCmdPipelineBarrier(
commandBuffer, commandBuffer,
+15 -10
View File
@@ -1,20 +1,25 @@
#ifndef LOVE_GRAPHICS_VULKAN_VULKAN_H #pragma once
#define LOVE_GRAPHICS_VULKAN_VULKAN_H
#include "graphics/Graphics.h" #include "graphics/Graphics.h"
#include "VulkanWrapper.h" #include "VulkanWrapper.h"
namespace love { namespace love
namespace graphics { {
namespace vulkan { namespace graphics
enum InternalFormatRepresentation { {
namespace vulkan
{
enum InternalFormatRepresentation
{
FORMATREPRESENTATION_FLOAT, FORMATREPRESENTATION_FLOAT,
FORMATREPRESENTATION_UINT, FORMATREPRESENTATION_UINT,
FORMATREPRESENTATION_SINT, FORMATREPRESENTATION_SINT,
FORMATREPRESENTATION_MAX_ENUM FORMATREPRESENTATION_MAX_ENUM
}; };
struct TextureFormat { struct TextureFormat
{
InternalFormatRepresentation internalFormatRepresentation; InternalFormatRepresentation internalFormatRepresentation;
VkFormat internalFormat = VK_FORMAT_UNDEFINED; VkFormat internalFormat = VK_FORMAT_UNDEFINED;
@@ -24,7 +29,8 @@ struct TextureFormat {
VkComponentSwizzle swizzleA = VK_COMPONENT_SWIZZLE_IDENTITY; VkComponentSwizzle swizzleA = VK_COMPONENT_SWIZZLE_IDENTITY;
}; };
class Vulkan { class Vulkan
{
public: public:
static void shaderSwitch(); static void shaderSwitch();
static uint32_t getNumShaderSwitches(); static uint32_t getNumShaderSwitches();
@@ -59,8 +65,7 @@ public:
VkCommandBuffer, VkImage, VkImageLayout oldLayout, VkImageLayout newLayout, VkCommandBuffer, VkImage, VkImageLayout oldLayout, VkImageLayout newLayout,
uint32_t baseLevel = 0, uint32_t levelCount = 1, uint32_t baseLayer = 0, uint32_t layerCount = 1); uint32_t baseLevel = 0, uint32_t levelCount = 1, uint32_t baseLayer = 0, uint32_t layerCount = 1);
}; };
} // vulkan } // vulkan
} // graphics } // graphics
} // love } // love
#endif
+1 -4
View File
@@ -1,5 +1,4 @@
#ifndef LOVE_GRAPHICS_VULKAN_VULKANWRAPPER_H #pragma once
#define LOVE_GRAPHICS_VULKAN_VULKANWRAPPER_H
#include "common/config.h" #include "common/config.h"
@@ -13,5 +12,3 @@
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#endif #endif
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
#endif //LOVE_GRAPHICS_VULKAN_VULKANWRAPPER_H