Skip to content

Commit

Permalink
Move VulkanPushBuffer into VulkanMemory.h
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Mar 20, 2016
1 parent f7113bb commit 5d56537
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 126 deletions.
2 changes: 2 additions & 0 deletions Common/Common.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@
<ClInclude Include="Vulkan\VulkanContext.h" />
<ClInclude Include="Vulkan\VulkanImage.h" />
<ClInclude Include="Vulkan\VulkanLoader.h" />
<ClInclude Include="Vulkan\VulkanMemory.h" />
<ClInclude Include="x64Analyzer.h" />
<ClInclude Include="x64Emitter.h" />
</ItemGroup>
Expand Down Expand Up @@ -316,6 +317,7 @@
<ClCompile Include="Vulkan\VulkanContext.cpp" />
<ClCompile Include="Vulkan\VulkanImage.cpp" />
<ClCompile Include="Vulkan\VulkanLoader.cpp" />
<ClCompile Include="Vulkan\VulkanMemory.cpp" />
<ClCompile Include="x64Analyzer.cpp" />
<ClCompile Include="x64Emitter.cpp" />
</ItemGroup>
Expand Down
6 changes: 6 additions & 0 deletions Common/Common.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@
<ClInclude Include="Vulkan\VulkanImage.h">
<Filter>Vulkan</Filter>
</ClInclude>
<ClInclude Include="Vulkan\VulkanMemory.h">
<Filter>Vulkan</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp" />
Expand Down Expand Up @@ -127,6 +130,9 @@
<ClCompile Include="Vulkan\VulkanImage.cpp">
<Filter>Vulkan</Filter>
</ClCompile>
<ClCompile Include="Vulkan\VulkanMemory.cpp">
<Filter>Vulkan</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
Expand Down
136 changes: 10 additions & 126 deletions Common/Vulkan/VulkanContext.h
Original file line number Diff line number Diff line change
@@ -1,28 +1,3 @@
/*
* Vulkan Samples Kit
*
* Copyright (C) 2015 Valve Corporation
* Copyright (C) 2015 Google, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

#ifndef UTIL_INIT
#define UTIL_INIT

Expand Down Expand Up @@ -52,7 +27,7 @@

#include "Common/Vulkan/VulkanLoader.h"

/* Amount of time, in nanoseconds, to wait for a command buffer to complete */
// Amount of time, in nanoseconds, to wait for a command buffer to complete
#define FENCE_TIMEOUT 10000000000

#if defined(NDEBUG) && defined(__GNUC__)
Expand Down Expand Up @@ -88,6 +63,15 @@ class VulkanDeleteList {
void QueueDeletePipelineCache(VkPipelineCache pipelineCache) { pipelineCaches_.push_back(pipelineCache); }

void Take(VulkanDeleteList &del) {
assert(descPools_.size() == 0);
assert(modules_.size() == 0);
assert(buffers_.size() == 0);
assert(bufferViews_.size() == 0);
assert(images_.size() == 0);
assert(imageViews_.size() == 0);
assert(deviceMemory_.size() == 0);
assert(samplers_.size() == 0);
assert(pipelineCaches_.size() == 0);
descPools_ = std::move(del.descPools_);
modules_ = std::move(del.modules_);
buffers_ = std::move(del.buffers_);
Expand Down Expand Up @@ -340,106 +324,6 @@ class VulkanContext {
std::vector<VkCommandBuffer> cmdQueue_;
};

// Use these to push vertex, index and uniform data. Generally you'll have two of these
// and alternate on each frame.
// TODO: Make it possible to suballocate pushbuffers from a large DeviceMemory block.
// We'll have two of these that we alternate between on each frame.
// TODO: Make this auto-grow and shrink. Need to be careful about returning and using the new
// buffer handle on overflow.
class VulkanPushBuffer {
public:
VulkanPushBuffer(VulkanContext *vulkan, size_t size) : offset_(0), size_(size), writePtr_(nullptr), deviceMemory_(0) {
VkDevice device = vulkan->GetDevice();

VkBufferCreateInfo b = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
b.size = size;
b.flags = 0;
b.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
b.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
b.queueFamilyIndexCount = 0;
b.pQueueFamilyIndices = nullptr;
VkResult res = vkCreateBuffer(device, &b, nullptr, &buffer_);
assert(VK_SUCCESS == res);

// Okay, that's the buffer. Now let's allocate some memory for it.
VkMemoryAllocateInfo alloc = {};
alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
alloc.pNext = nullptr;
vulkan->MemoryTypeFromProperties(0xFFFFFFFF, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &alloc.memoryTypeIndex);
alloc.allocationSize = size;

res = vkAllocateMemory(device, &alloc, nullptr, &deviceMemory_);
assert(VK_SUCCESS == res);
res = vkBindBufferMemory(device, buffer_, deviceMemory_, 0);
assert(VK_SUCCESS == res);
}

void Destroy(VulkanContext *vulkan) {
vulkan->Delete().QueueDeleteBuffer(buffer_);
vulkan->Delete().QueueDeleteDeviceMemory(deviceMemory_);
}

void Reset() { offset_ = 0; }

void Begin(VkDevice device) {
offset_ = 0;
VkResult res = vkMapMemory(device, deviceMemory_, 0, size_, 0, (void **)(&writePtr_));
assert(VK_SUCCESS == res);
}

void End(VkDevice device) {
vkUnmapMemory(device, deviceMemory_);
writePtr_ = nullptr;
}

size_t Allocate(size_t numBytes) {
size_t out = offset_;
offset_ += (numBytes + 3) & ~3; // Round up to 4 bytes.
if (offset_ >= size_) {
// TODO: Allocate a second buffer, then combine them on the next frame.
#ifdef _WIN32
DebugBreak();
#endif
}
return out;
}

// TODO: Add alignment support?
// Returns the offset that should be used when binding this buffer to get this data.
size_t Push(const void *data, size_t size) {
size_t off = Allocate(size);
memcpy(writePtr_ + off, data, size);
return off;
}

uint32_t PushAligned(const void *data, size_t size, int align) {
offset_ = (offset_ + align - 1) & ~(align - 1);
size_t off = Allocate(size);
memcpy(writePtr_ + off, data, size);
return (uint32_t)off;
}

size_t GetOffset() const {
return offset_;
}

// "Zero-copy" variant - you can write the data directly as you compute it.
void *Push(size_t size, size_t *bindOffset) {
size_t off = Allocate(size);
*bindOffset = off;
return writePtr_ + off;
}

VkBuffer GetVkBuffer() const { return buffer_; }

private:
VkDeviceMemory deviceMemory_;
VkBuffer buffer_;
size_t offset_;
size_t size_;
uint8_t *writePtr_;
};

// Stand-alone utility functions
void VulkanBeginCommandBuffer(VkCommandBuffer cmd);
void TransitionImageLayout(
Expand Down
47 changes: 47 additions & 0 deletions Common/Vulkan/VulkanMemory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) 2016- PPSSPP Project.

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.

// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/

// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.

// Additionally, Common/Vulkan/* , including this file, are also licensed
// under the public domain.

#include "Common/Vulkan/VulkanMemory.h"

VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, size_t size) : offset_(0), size_(size), writePtr_(nullptr), deviceMemory_(0) {
VkDevice device = vulkan->GetDevice();

VkBufferCreateInfo b = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
b.size = size;
b.flags = 0;
b.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
b.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
b.queueFamilyIndexCount = 0;
b.pQueueFamilyIndices = nullptr;
VkResult res = vkCreateBuffer(device, &b, nullptr, &buffer_);
assert(VK_SUCCESS == res);

// Okay, that's the buffer. Now let's allocate some memory for it.
VkMemoryAllocateInfo alloc = {};
alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
alloc.pNext = nullptr;
vulkan->MemoryTypeFromProperties(0xFFFFFFFF, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &alloc.memoryTypeIndex);
alloc.allocationSize = size;

res = vkAllocateMemory(device, &alloc, nullptr, &deviceMemory_);
assert(VK_SUCCESS == res);
res = vkBindBufferMemory(device, buffer_, deviceMemory_, 0);
assert(VK_SUCCESS == res);
}
93 changes: 93 additions & 0 deletions Common/Vulkan/VulkanMemory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#pragma once

#include "Common/Vulkan/VulkanContext.h"

// VulkanMemory
//
// Vulkan memory management utils.

// VulkanPushBuffer
// Simple incrementing allocator.
// Use these to push vertex, index and uniform data. Generally you'll have two of these
// and alternate on each frame. Make sure not to reset until the fence from the last time you used it
// has completed.
//
// TODO: Make it possible to suballocate pushbuffers from a large DeviceMemory block.
// TODO: Make this auto-grow and shrink. Need to be careful about returning and using the new
// buffer handle on overflow.
class VulkanPushBuffer {
public:
VulkanPushBuffer(VulkanContext *vulkan, size_t size);

~VulkanPushBuffer() {
assert(buffer_ == VK_NULL_HANDLE);
assert(deviceMemory_ == VK_NULL_HANDLE);
}

void Destroy(VulkanContext *vulkan) {
vulkan->Delete().QueueDeleteBuffer(buffer_);
vulkan->Delete().QueueDeleteDeviceMemory(deviceMemory_);
buffer_ = VK_NULL_HANDLE;
deviceMemory_ = VK_NULL_HANDLE;
}

void Reset() { offset_ = 0; }

void Begin(VkDevice device) {
offset_ = 0;
VkResult res = vkMapMemory(device, deviceMemory_, 0, size_, 0, (void **)(&writePtr_));
assert(VK_SUCCESS == res);
}

void End(VkDevice device) {
vkUnmapMemory(device, deviceMemory_);
writePtr_ = nullptr;
}

size_t Allocate(size_t numBytes) {
size_t out = offset_;
offset_ += (numBytes + 3) & ~3; // Round up to 4 bytes.
if (offset_ >= size_) {
// TODO: Allocate a second buffer, then combine them on the next frame.
#ifdef _WIN32
DebugBreak();
#endif
}
return out;
}

// TODO: Add alignment support?
// Returns the offset that should be used when binding this buffer to get this data.
size_t Push(const void *data, size_t size) {
size_t off = Allocate(size);
memcpy(writePtr_ + off, data, size);
return off;
}

uint32_t PushAligned(const void *data, size_t size, int align) {
offset_ = (offset_ + align - 1) & ~(align - 1);
size_t off = Allocate(size);
memcpy(writePtr_ + off, data, size);
return (uint32_t)off;
}

size_t GetOffset() const {
return offset_;
}

// "Zero-copy" variant - you can write the data directly as you compute it.
void *Push(size_t size, size_t *bindOffset) {
size_t off = Allocate(size);
*bindOffset = off;
return writePtr_ + off;
}

VkBuffer GetVkBuffer() const { return buffer_; }

private:
VkDeviceMemory deviceMemory_;
VkBuffer buffer_;
size_t offset_;
size_t size_;
uint8_t *writePtr_;
};
3 changes: 3 additions & 0 deletions GPU/Vulkan/DrawEngineVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
#include "GPU/GPUState.h"
#include "GPU/ge_constants.h"

#include "Common/Vulkan/VulkanContext.h"
#include "Common/Vulkan/VulkanMemory.h"

#include "GPU/Common/TextureDecoder.h"
#include "GPU/Common/SplineCommon.h"
#include "GPU/Common/TransformCommon.h"
Expand Down
1 change: 1 addition & 0 deletions GPU/Vulkan/ShaderManagerVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "math/dataconv.h"
#include "util/text/utf8.h"
#include "Common/Vulkan/VulkanContext.h"
#include "Common/Vulkan/VulkanMemory.h"
#include "Common/Common.h"
#include "Core/Config.h"
#include "Core/Reporting.h"
Expand Down
1 change: 1 addition & 0 deletions GPU/Vulkan/TextureCacheVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "Common/Vulkan/VulkanContext.h"
#include "Common/Vulkan/VulkanImage.h"
#include "Common/Vulkan/VulkanMemory.h"

#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
Expand Down
1 change: 1 addition & 0 deletions GPU/Vulkan/TextureCacheVulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class DrawEngineVulkan;

class VulkanContext;
class VulkanTexture;
class VulkanPushBuffer;

struct SamplerCacheKey {
SamplerCacheKey() : fullKey(0) {}
Expand Down
1 change: 1 addition & 0 deletions android/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ VULKAN_FILES := \
$(SRC)/Common/Vulkan/VulkanLoader.cpp \
$(SRC)/Common/Vulkan/VulkanContext.cpp \
$(SRC)/Common/Vulkan/VulkanImage.cpp \
$(SRC)/Common/Vulkan/VulkanMemory.cpp \
$(SRC)/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp \
$(SRC)/GPU/Vulkan/DrawEngineVulkan.cpp \
$(SRC)/GPU/Vulkan/FramebufferVulkan.cpp \
Expand Down
1 change: 1 addition & 0 deletions ext/native/thin3d/thin3d_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include "Common/Vulkan/VulkanContext.h"
#include "Common/Vulkan/VulkanImage.h"
#include "Common/Vulkan/VulkanMemory.h"

// We use a simple descriptor set for all rendering: 1 sampler, 1 texture, 1 UBO binding point.
// binding 0 - uniform data
Expand Down

0 comments on commit 5d56537

Please sign in to comment.