Skip to content

Commit

Permalink
Mappable resource initial impl
Browse files Browse the repository at this point in the history
Support for buffer map
  • Loading branch information
kecho committed Dec 29, 2023
1 parent 338fbfb commit b8c5be8
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 5 deletions.
9 changes: 9 additions & 0 deletions Source/modules/render/dx12/Dx12Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,15 @@ void Dx12Device::transitionResourceState(ResourceHandle resource, D3D12_RESOURCE
resourceInfo.gpuState = getGpuState(newState);
}

void* Dx12Device::mappedMemory(Buffer buffer)
{
if (!buffer.valid())
return nullptr;

Dx12Resource& resource = m_resources->unsafeGetResource(buffer);
return resource.mappedMemory();
}

Dx12PixApi* Dx12Device::getPixApi() const
{
return Dx12PixApi::get(m_config.resourcePath.c_str());
Expand Down
1 change: 1 addition & 0 deletions Source/modules/render/dx12/Dx12Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class Dx12Device : public TDevice<Dx12Device>
virtual const DeviceInfo& info() const override { return m_info; }
virtual const DeviceRuntimeInfo& runtimeInfo() const { return m_runtimeInfo; }
virtual SmartPtr<IDisplay> createDisplay(const DisplayConfig& config) override;
virtual void* mappedMemory (Buffer buffer) override;

virtual void removeShaderDb() { m_shaderDb = nullptr; }
virtual IShaderDb* db() override { return (IShaderDb*)m_shaderDb; }
Expand Down
3 changes: 3 additions & 0 deletions Source/modules/render/dx12/Dx12ResourceCollection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ BufferResult Dx12ResourceCollection::createBuffer(const BufferDesc& desc, ID3D12
std::unique_lock lock(m_resourceMutex);
ResourceHandle resHandle;

if ((desc.usage & BufferUsage_Upload) != 0)
flags = (ResourceSpecialFlags)(flags | ResourceSpecialFlag_CpuUpload);

SmartPtr<Dx12Resource> bufferObj = new Dx12Buffer(m_device, desc, flags);
if (resource)
bufferObj->acquireD3D12Resource(resource);
Expand Down
3 changes: 2 additions & 1 deletion Source/modules/render/dx12/Dx12Resources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Dx12Resource::Dx12Resource(Dx12Device& device, const ResourceDesc& config, Resou

m_data.heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
m_usage = Usage::Dynamic; //assume all read / write

if ((specialFlags & (ResourceSpecialFlag_CpuReadback | ResourceSpecialFlag_CpuUpload)) == 0)
{
m_usage = Usage::Default;
Expand Down Expand Up @@ -390,7 +391,7 @@ Dx12ResourceInitResult Dx12Texture::init()
}

Dx12Buffer::Dx12Buffer(Dx12Device& device, const BufferDesc& desc, ResourceSpecialFlags specialFlags)
: Dx12Resource(device, desc, ResourceSpecialFlags(specialFlags | ResourceSpecialFlag_CanDenyShaderResources))
: Dx12Resource(device, desc, ResourceSpecialFlags(specialFlags | ResourceSpecialFlag_CanDenyShaderResources | (desc.usage & BufferUsage_Upload != 0 ? ResourceSpecialFlag_CpuUpload : (ResourceSpecialFlags)0)))
, m_buffDesc(desc)
{
if ((desc.memFlags & MemFlag_GpuRead) != 0)
Expand Down
2 changes: 2 additions & 0 deletions Source/modules/render/public/coalpy.render/IDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class IDevice

virtual TextureResult recreateTexture(Texture handle, const TextureDesc& config) = 0;

virtual void* mappedMemory(Buffer buffer) = 0;

virtual void release(ResourceHandle resource) = 0;
virtual void release(ResourceTable table) = 0;
virtual void release(WorkHandle handle) = 0;
Expand Down
3 changes: 2 additions & 1 deletion Source/modules/render/public/coalpy.render/Resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ enum BufferUsage : int
{
BufferUsage_Constant = 1 << 0,
BufferUsage_AppendConsume = 1 << 1,
BufferUsage_IndirectArgs = 1 << 2
BufferUsage_IndirectArgs = 1 << 2,
BufferUsage_Upload = 1 << 3
};

enum class BufferType
Expand Down
13 changes: 13 additions & 0 deletions Source/modules/render/vulkan/VulkanDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,5 +480,18 @@ ScheduleStatus VulkanDevice::internalSchedule(CommandList** commandLists, int li
return status;
}


void* VulkanDevice::mappedMemory(Buffer buffer)
{
if (!buffer.valid())
return nullptr;

VulkanResource& resource = m_resources->unsafeGetResource(buffer);
if (!resource.isBuffer())
return nullptr;

return resource.mappedMemory;
}

}
}
2 changes: 2 additions & 0 deletions Source/modules/render/vulkan/VulkanDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class VulkanDevice : public TDevice<VulkanDevice>
void internalReleaseWorkHandle(WorkHandle handle);
ScheduleStatus internalSchedule(CommandList** commandLists, int listCounts, WorkHandle workHandle);

virtual void* mappedMemory(Buffer buffer) override;

VkInstance vkInstance() const { return m_vkInstance; }
VkDevice vkDevice() const { return m_vkDevice; }
VkPhysicalDevice vkPhysicalDevice() const { return m_vkPhysicalDevice; }
Expand Down
18 changes: 16 additions & 2 deletions Source/modules/render/vulkan/VulkanResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ VulkanResources::~VulkanResources()

BufferResult VulkanResources::createBuffer(const BufferDesc& desc, VkBuffer resourceToAcquire, ResourceSpecialFlags specialFlags)
{
if ((desc.usage & ResourceSpecialFlag_CpuReadback) != 0)
specialFlags = (ResourceSpecialFlags)(specialFlags | ResourceSpecialFlag_CpuUpload | ResourceSpecialFlag_MapMemory);

std::unique_lock lock(m_mutex);
ResourceHandle handle;
VulkanResource& resource = m_container.allocate(handle);
Expand Down Expand Up @@ -142,6 +145,11 @@ BufferResult VulkanResources::createBuffer(const BufferDesc& desc, VkBuffer reso
return BufferResult { ResourceResult::InternalApiFailure, Buffer(), "Failed to allocating buffer memory." };
}

if ((specialFlags & ResourceSpecialFlag_MapMemory) != 0)
{
VK_OK(vkMapMemory(m_device.vkDevice(), resource.memory, 0u, VK_WHOLE_SIZE, 0u, &resource.mappedMemory));
}

if (bufferData.ownsBuffer && vkBindBufferMemory(m_device.vkDevice(), bufferData.vkBuffer, resource.memory, 0u) != VK_SUCCESS)
{
vkDestroyBuffer(m_device.vkDevice(), bufferData.vkBuffer, nullptr);
Expand Down Expand Up @@ -337,7 +345,7 @@ TextureResult VulkanResources::createTextureInternal(ResourceHandle handle, cons

VkImageCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;

resource.memFlags = desc.memFlags;
resource.specialFlags = specialFlags;

Expand Down Expand Up @@ -414,7 +422,7 @@ TextureResult VulkanResources::createTextureInternal(ResourceHandle handle, cons
VkMemoryAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memReqs.size;
if (textureData.ownsImage && !m_device.findMemoryType(memReqs.memoryTypeBits, 0u, allocInfo.memoryTypeIndex))
if (textureData.ownsImage && !m_device.findMemoryType(memReqs.memoryTypeBits, 0, allocInfo.memoryTypeIndex))
{
if (textureData.ownsImage)
vkDestroyImage(m_device.vkDevice(), textureData.vkImage, nullptr);
Expand Down Expand Up @@ -875,6 +883,12 @@ void VulkanResources::releaseResourceInternal(ResourceHandle handle, VulkanResou

if (resource.isBuffer())
{
if ((resource.specialFlags & ResourceSpecialFlag_MapMemory) != 0)
{
vkUnmapMemory(m_device.vkDevice(), resource.memory);
resource.mappedMemory = nullptr;
}

if ((resource.specialFlags & ResourceSpecialFlag_NoDeferDelete) == 0)
{
m_device.gc().deferRelease(
Expand Down
4 changes: 3 additions & 1 deletion Source/modules/render/vulkan/VulkanResources.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ enum ResourceSpecialFlags : int
ResourceSpecialFlag_TrackTables = 1 << 2,
ResourceSpecialFlag_CpuReadback = 1 << 3,
ResourceSpecialFlag_CpuUpload = 1 << 4,
ResourceSpecialFlag_EnableColorAttachment = 1 << 5,
ResourceSpecialFlag_MapMemory = 1 << 5,
ResourceSpecialFlag_EnableColorAttachment = 1 << 6,
};

class VulkanDevice;
Expand Down Expand Up @@ -84,6 +85,7 @@ struct VulkanResource
VkDeviceSize requestSize = {};
VkDeviceSize actualSize = {};
VkDeviceMemory memory = {};
void* mappedMemory = {};

std::set<ResourceTable> trackedTables;
};
Expand Down
1 change: 1 addition & 0 deletions Source/pymodules/gpu/bindings/Enums.inl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ COALPY_ENUM_BEGIN(BufferUsage, "Buffer usage flags. Use enum values located at
COALPY_ENUM(Constant, render::BufferUsage_Constant, "Set flag when buffer is to be bound in a dispatch called through the constant argument.")
COALPY_ENUM(AppendConsume, render::BufferUsage_AppendConsume, "Set flag when a buffer is to be used as an append consume queue. In HLSL this corresponds to AppendStructuredBuffer")
COALPY_ENUM(IndirectArgs, render::BufferUsage_IndirectArgs, "Set flag when a buffer is to be used as an argument buffer on a dispatch call.")
COALPY_ENUM(Upload, render::BufferUsage_Upload, "Use this buffer as an upload resource.")
COALPY_ENUM_END(BufferUsage)

#undef COALPY_ENUM_BEGIN
Expand Down
120 changes: 120 additions & 0 deletions Source/tests/RenderTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1941,6 +1941,125 @@ void testCollectGpuMarkers(TestContext& ctx)
renderTestCtx.end();
}

void testBufferCpuMap(TestContext& ctx)
{
auto& renderTestCtx = (RenderTestContext&)ctx;
renderTestCtx.begin();
IDevice& device = *renderTestCtx.device;
IShaderDb& db = *renderTestCtx.db;

const char* verifyKernelSrc = R"(
Buffer<int> g_input : register(t0);
RWBuffer<int> g_output : register(u0);
[numthreads(1,1,1)]
void csMain(uint3 gti : SV_GroupID)
{
int matches = 0;
for (uint i = 0; i < 64; ++i)
matches += (g_input[i] == i) ? 1 : 0;
g_output[0] = matches;
}
)";

ShaderHandle verifyShader;
{
ShaderInlineDesc shaderDesc;
shaderDesc.type = ShaderType::Compute;
shaderDesc.name = "verifyKernel";
shaderDesc.mainFn = "csMain";
shaderDesc.immCode = verifyKernelSrc;
verifyShader = db.requestCompile(shaderDesc);
db.resolve(verifyShader);
CPY_ASSERT(db.isValid(verifyShader));
}

BufferDesc bufferDesc;
bufferDesc.format = Format::R32_SINT;
bufferDesc.elementCount = 64;
bufferDesc.memFlags = MemFlag_GpuRead;
bufferDesc.usage = BufferUsage_Upload;
BufferResult uploadBuffResult = device.createBuffer(bufferDesc);
CPY_ASSERT_MSG(uploadBuffResult.success(), uploadBuffResult.message.c_str());
if (!uploadBuffResult.success())
{
renderTestCtx.end();
return;
}

Buffer uploadBuff = uploadBuffResult.object;

Buffer outputBuffer;
{
BufferDesc outDesc;
outDesc.format = Format::R32_SINT;
outDesc.elementCount = 1;
outDesc.memFlags = MemFlag_GpuWrite;
outputBuffer = device.createBuffer(outDesc);
}

OutResourceTable outputTable;
{
ResourceTableDesc desc;
desc.resources = &outputBuffer;
desc.resourcesCount = 1;
outputTable = device.createOutResourceTable(desc);
}

InResourceTable inputTable;
{
ResourceTableDesc desc;
desc.resources = &uploadBuff;
desc.resourcesCount = 1;
inputTable = device.createInResourceTable(desc);
}

int* memory = static_cast<int*>(device.mappedMemory(uploadBuff));
CPY_ASSERT(memory != nullptr);
if (memory != nullptr)
{
for (int i = 0; i < bufferDesc.elementCount; ++i)
memory[i] = i;
}


CommandList cmdList;
{
ComputeCommand cmd;
cmd.setShader(verifyShader);
cmd.setInResources(&inputTable, 1);
cmd.setOutResources(&outputTable, 1);
cmd.setDispatch("matchDispatch", 1, 1, 1);
cmdList.writeCommand(cmd);
}

{
DownloadCommand cmd;
cmd.setData(outputBuffer);
cmdList.writeCommand(cmd);
}

cmdList.finalize();

CommandList* cmdLists = &cmdList;
ScheduleStatus scheduleStatus = device.schedule(&cmdLists, 1, ScheduleFlags_GetWorkHandle);
CPY_ASSERT(scheduleStatus.success());

WaitStatus waitStatus = device.waitOnCpu(scheduleStatus.workHandle, -1);
CPY_ASSERT(waitStatus.success());

DownloadStatus downloadResult = device.getDownloadStatus(scheduleStatus.workHandle, outputBuffer);
CPY_ASSERT(downloadResult.success());
if (downloadResult.success())
CPY_ASSERT(*(int*)downloadResult.downloadPtr == 64);

device.release(uploadBuff);
device.release(outputBuffer);
device.release(outputTable);
device.release(inputTable);
renderTestCtx.end();
}

static const TestCase* createCases(int& caseCounts)
{
static const TestCase sCases[] = {
Expand All @@ -1967,6 +2086,7 @@ static const TestCase* createCases(int& caseCounts)
{ "copyTexture", testCopyTexture },
{ "copyTextureArrayAndMips", testCopyTextureArrayAndMips },
{ "collectGpuMarkers", testCollectGpuMarkers },
{ "bufferCpuMap", testBufferCpuMap },
};

caseCounts = sizeof(sCases)/sizeof(sCases[0]);
Expand Down

0 comments on commit b8c5be8

Please sign in to comment.