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