Skip to content

Commit

Permalink
Merge pull request #1958 from nikeinikei/12.0-development
Browse files Browse the repository at this point in the history
vk: maintenance
  • Loading branch information
slime73 authored Aug 8, 2023
2 parents 8913ca2 + 61cafd7 commit 98663ec
Show file tree
Hide file tree
Showing 5 changed files with 352 additions and 438 deletions.
95 changes: 67 additions & 28 deletions src/modules/graphics/vulkan/Graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ void Graphics::present(void *screenshotCallbackdata)

void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight)
{
if (swapChain != VK_NULL_HANDLE && (pixelWidth != this->pixelWidth || pixelHeight != this->pixelHeight || width != this->width || height != this->height))
if (swapChain != VK_NULL_HANDLE && (pixelwidth != this->pixelWidth || pixelheight != this->pixelHeight || width != this->width || height != this->height))
requestSwapchainRecreation();

this->width = width;
Expand Down Expand Up @@ -559,8 +559,6 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int

beginFrame();

uint8 whiteColor[] = { 255, 255, 255, 255 };

if (batchedDrawState.vb[0] == nullptr)
{
// Initial sizes that should be good enough for most cases. It will
Expand All @@ -570,9 +568,19 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int
batchedDrawState.indexBuffer = new StreamBuffer(this, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
}

// sometimes the VertexTexCoord is not set, so we manually adjust it to (0, 0)
if (defaultConstantTexCoord == nullptr)
{
float zeroTexCoord[2] = { 0.0f, 0.0f };
Buffer::DataDeclaration format("ConstantTexCoord", DATAFORMAT_FLOAT_VEC2);
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
defaultConstantTexCoord = newBuffer(settings, { format }, zeroTexCoord, sizeof(zeroTexCoord), 1);
}

// sometimes the VertexColor is not set, so we manually adjust it to white color
if (defaultConstantColor == nullptr)
{
uint8 whiteColor[] = { 255, 255, 255, 255 };
Buffer::DataDeclaration format("ConstantColor", DATAFORMAT_UNORM8_VEC4);
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
defaultConstantColor = newBuffer(settings, { format }, whiteColor, sizeof(whiteColor), 1);
Expand Down Expand Up @@ -1173,7 +1181,6 @@ void Graphics::beginFrame()

if (frameCounter >= USAGES_POLL_INTERVAL)
{
vkDeviceWaitIdle(device);
cleanupUnusedObjects();
frameCounter = 0;
}
Expand Down Expand Up @@ -1263,11 +1270,6 @@ const VkDeviceSize Graphics::getMinUniformBufferOffsetAlignment() const
return minUniformBufferOffsetAlignment;
}

graphics::Texture *Graphics::getDefaultTexture() const
{
return defaultTexture;
}

VkCommandBuffer Graphics::getCommandBufferForDataTransfer()
{
if (renderPassState.active)
Expand Down Expand Up @@ -1653,10 +1655,11 @@ void Graphics::createLogicalDevice()

VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extendedDynamicStateFeatures{};
extendedDynamicStateFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
extendedDynamicStateFeatures.extendedDynamicState = Vulkan::getBool(optionalDeviceExtensions.extendedDynamicState);
extendedDynamicStateFeatures.extendedDynamicState = VK_TRUE;
extendedDynamicStateFeatures.pNext = nullptr;

createInfo.pNext = &extendedDynamicStateFeatures;
if (optionalDeviceExtensions.extendedDynamicState)
createInfo.pNext = &extendedDynamicStateFeatures;

if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS)
throw love::Exception("failed to create logical device");
Expand Down Expand Up @@ -1850,20 +1853,34 @@ void Graphics::createSwapChain()

VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats)
{
std::vector<VkFormat> formatOrder;

// TODO: turn off GammaCorrect if a sRGB format can't be found?
// TODO: does every platform have these formats?
if (isGammaCorrect())
{
formatOrder = {
VK_FORMAT_B8G8R8A8_SRGB,
VK_FORMAT_R8G8B8A8_SRGB,
};
}
else
{
formatOrder = {
VK_FORMAT_B8G8R8A8_UNORM,
VK_FORMAT_R8G8B8A8_SNORM,
};
}

for (const auto format : formatOrder)
{
for (const auto &availableFormat : availableFormats)
// fixme: what if this format and colorspace is not available?
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
{
if (availableFormat.format == format && availableFormat.colorSpace == VK_COLORSPACE_SRGB_NONLINEAR_KHR)
return availableFormat;
}
}

for (const auto &availableFormat : availableFormats)
// fixme: what if this format and colorspace is not available?
if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
return availableFormat;


return availableFormats[0];
}

Expand Down Expand Up @@ -2208,11 +2225,6 @@ VkRenderPass Graphics::getRenderPass(RenderPassConfiguration &configuration)
return renderPass;
}

bool Graphics::usesConstantVertexColor(const VertexAttributes &vertexAttributes)
{
return !!(vertexAttributes.enableBits & (1u << ATTRIB_COLOR));
}

void Graphics::createVulkanVertexFormat(
VertexAttributes vertexAttributes,
std::vector<VkVertexInputBindingDescription> &bindingDescriptions,
Expand All @@ -2224,6 +2236,7 @@ void Graphics::createVulkanVertexFormat(
auto allBits = enableBits;

bool usesColor = false;
bool usesTexCoord = false;

uint8_t highestBufferBinding = 0;

Expand All @@ -2233,6 +2246,8 @@ void Graphics::createVulkanVertexFormat(
uint32 bit = 1u << i;
if (enableBits & bit)
{
if (i == ATTRIB_TEXCOORD)
usesTexCoord = true;
if (i == ATTRIB_COLOR)
usesColor = true;

Expand Down Expand Up @@ -2267,11 +2282,31 @@ void Graphics::createVulkanVertexFormat(
allBits >>= 1;
}

if (!usesTexCoord)
{
// FIXME: is there a case where gaps happen between buffer bindings?
// then this doesn't work. We might need to enable null buffers again.
const auto constantTexCoordBufferBinding = ++highestBufferBinding;

VkVertexInputBindingDescription bindingDescription{};
bindingDescription.binding = constantTexCoordBufferBinding;
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
bindingDescription.stride = 0; // no stride, will always read the same coord multiple times.
bindingDescriptions.push_back(bindingDescription);

VkVertexInputAttributeDescription attributeDescription{};
attributeDescription.binding = constantTexCoordBufferBinding;
attributeDescription.location = ATTRIB_TEXCOORD;
attributeDescription.offset = 0;
attributeDescription.format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions.push_back(attributeDescription);
}

if (!usesColor)
{
// FIXME: is there a case where gaps happen between buffer bindings?
// then this doesn't work. We might need to enable null buffers again.
const auto constantColorBufferBinding = highestBufferBinding + 1;
const auto constantColorBufferBinding = ++highestBufferBinding;

VkVertexInputBindingDescription bindingDescription{};
bindingDescription.binding = constantColorBufferBinding;
Expand Down Expand Up @@ -2331,7 +2366,13 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi
}
}

if (!usesConstantVertexColor(attributes))
if (!(attributes.enableBits & (1u << ATTRIB_TEXCOORD)))
{
bufferVector.push_back((VkBuffer)defaultConstantTexCoord->getHandle());
offsets.push_back((VkDeviceSize)0);
}

if (!(attributes.enableBits & (1u << ATTRIB_COLOR)))
{
bufferVector.push_back((VkBuffer)defaultConstantColor->getHandle());
offsets.push_back((VkDeviceSize)0);
Expand Down Expand Up @@ -2402,8 +2443,6 @@ void Graphics::setDefaultRenderPass()

void Graphics::setRenderPass(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture)
{
auto currentCommandBuffer = commandBuffers.at(currentFrame);

// fixme: hasSRGBtexture
RenderPassConfiguration renderPassConfiguration{};
for (const auto &color : rts.colors)
Expand Down
15 changes: 6 additions & 9 deletions src/modules/graphics/vulkan/Graphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,12 @@ class Graphics final : public love::graphics::Graphics
Graphics();
~Graphics();

const char *getName() const override;
const VkDevice getDevice() const;
const VmaAllocator getVmaAllocator() const;

// implementation for virtual functions
const char *getName() const 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;
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;
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;
Expand Down Expand Up @@ -299,17 +298,15 @@ class Graphics final : public love::graphics::Graphics
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;

// internal functions.

const VkDevice getDevice() const;
const VmaAllocator getVmaAllocator() const;
VkCommandBuffer getCommandBufferForDataTransfer();
void queueCleanUp(std::function<void()> cleanUp);
void addReadbackCallback(std::function<void()> callback);
void submitGpuCommands(bool present, void *screenshotCallbackData = nullptr);
const VkDeviceSize getMinUniformBufferOffsetAlignment() const;
graphics::Texture *getDefaultTexture() const;
VkSampler getCachedSampler(const SamplerState &sampler);
void setComputeShader(Shader *computeShader);
graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData();
Expand Down Expand Up @@ -369,7 +366,6 @@ class Graphics final : public love::graphics::Graphics
void startRecordingGraphicsCommands();
void endRecordingGraphicsCommands();
void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration &configuration);
bool usesConstantVertexColor(const VertexAttributes &attribs);
void createVulkanVertexFormat(
VertexAttributes vertexAttributes,
std::vector<VkVertexInputBindingDescription> &bindingDescriptions,
Expand Down Expand Up @@ -438,6 +434,7 @@ class Graphics final : public love::graphics::Graphics
VmaAllocator vmaAllocator = VK_NULL_HANDLE;
StrongRef<love::graphics::Texture> defaultTexture;
StrongRef<love::graphics::Buffer> defaultConstantColor;
StrongRef<love::graphics::Buffer> defaultConstantTexCoord;
// functions that need to be called to cleanup objects that were needed for rendering a frame.
// We need a vector for each frame in flight.
std::vector<std::vector<std::function<void()>>> cleanUpFunctions;
Expand Down
Loading

0 comments on commit 98663ec

Please sign in to comment.