Skip to content

Introduce a new Texture type with DX,VK,MTL implementations.#1020

Merged
manon-traverse merged 10 commits intollvm:mainfrom
Traverse-Research:render-backend-api-texture
Apr 14, 2026
Merged

Introduce a new Texture type with DX,VK,MTL implementations.#1020
manon-traverse merged 10 commits intollvm:mainfrom
Traverse-Research:render-backend-api-texture

Conversation

@EmilioLaiso
Copy link
Copy Markdown
Contributor

@EmilioLaiso EmilioLaiso commented Mar 26, 2026

Summary

  • Introduced Texture.h with a shared TextureCreateDesc, TextureFormat enum, TextureUsage flags, ClearValue variant (ClearColor / ClearDepthStencil), and validateTextureCreateDesc returning specific llvm::Error messages
  • Added createTexture to all three backends (DX, Vulkan, Metal) as a virtual method on Device, handling resource creation, optimized clear values, and format/usage validation
  • Unified render target creation via createRenderTargetFromCPUBuffer(Device&, CPUBuffer&) free function — all backends now route through createTexture instead of manually calling API-specific resource creation
  • Unified depth/stencil creation via createDefaultDepthStencilTarget(Device&, Width, Height) free function with D32FloatS8Uint format — added depth testing to DX and Metal backends (previously only Vulkan had it)
  • Readback buffers created through the virtual createBuffer API with MemoryLocation::GpuToCpu; Metal refactored from StorageModeShared texture with getBytes() to StorageModePrivate texture + blit copy to readback buffer (this is to align functionality between backends in preparation of api-agnostic code-flow. Sacrifices had to be made 😛)
  • Views on textures — RTV/DSV descriptor heaps (DX) and VkImageView (VK) are now created at createTexture time for RenderTarget/DepthStencil usage, removing view creation boilerplate from pipeline setup
  • Render target and readback buffer are stored directly as shared_ptr<VulkanTexture> / shared_ptr<VulkanBuffer> on InvocationState
  • Clear values read from texture descriptors in all backends instead of being hardcoded
  • Added toTextureFormat(DataFormat, Channels) as a bridge function while refactoring, with validateTextureDescMatchesCPUBuffer to catch mismatches between the old and new description systems
  • Split Metal storage mode helpers into getMetalTextureStorageMode and getMetalBufferResourceOptions because GpuToCpu maps differently for textures (Managed) vs buffers (Shared)

Future direction

Added for context to better understand some of the changes in this PR.

  • SRV/UAV views on textures — currently not stored on the texture because they would require a descriptor heap allocation scheme
  • Work towards eliminating DataFormat + Channels dual description.
  • Route VK vertex buffer through createBuffer — still uses the old ResourceRef/BufferRef system
  • Abstract readback copy
  • Unify InvocationState across backends

@EmilioLaiso EmilioLaiso force-pushed the render-backend-api-texture branch from ee21f04 to 48dadd6 Compare March 26, 2026 16:13
@EmilioLaiso EmilioLaiso force-pushed the render-backend-api-texture branch 2 times, most recently from 217f6ef to 505d3f0 Compare March 31, 2026 07:37
@EmilioLaiso EmilioLaiso marked this pull request as draft March 31, 2026 08:37
@EmilioLaiso EmilioLaiso marked this pull request as ready for review March 31, 2026 08:44
@EmilioLaiso EmilioLaiso force-pushed the render-backend-api-texture branch from de634bd to 0bf7cfc Compare March 31, 2026 08:53
@EmilioLaiso EmilioLaiso force-pushed the render-backend-api-texture branch from e1c50e9 to eb9f868 Compare April 1, 2026 07:04
const CPUBuffer &B = *P.Bindings.RTargetBufferPtr;
memcpy(B.Data[0].get(), Mapped, B.size());
vkUnmapMemory(Device, ResRef.Host.Memory);
vkUnmapMemory(Device, IS.RTReadback->Memory);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: unmapping is not necessary in Vulkan or DX12. It's fine to leave it as is, but I thought it was good to know it's fine to leave this persistently mapped.

Copy link
Copy Markdown
Contributor

@manon-traverse manon-traverse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of small comments, but other than that looks good to me

@EmilioLaiso EmilioLaiso force-pushed the render-backend-api-texture branch 4 times, most recently from 4c4f1a6 to c0ab760 Compare April 7, 2026 07:56
Comment on lines +485 to +489
// Readback heaps do not support UAV access.
const D3D12_RESOURCE_FLAGS Flags =
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
HeapType == D3D12_HEAP_TYPE_READBACK
? D3D12_RESOURCE_FLAG_NONE
: D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fwiw in our codebase we use a custom heap that might not place this restriction on buffers.

Comment on lines +573 to +575
std::shared_ptr<VulkanTexture> RenderTarget;
std::shared_ptr<VulkanBuffer> RTReadback;
std::shared_ptr<VulkanTexture> DepthStencil;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: we should try to store the platform-agnostic pointer here and downcast where needed, as the goal is to use these only in the platform-abstract way.

I am fine with keeping it this way for this PR, but it's something we should do in the future. Perhaps once we have an agnostic way of binding resources?

@EmilioLaiso EmilioLaiso force-pushed the render-backend-api-texture branch from 352383a to f6ac12e Compare April 10, 2026 11:51
@s-perron s-perron self-requested a review April 12, 2026 20:50
Copy link
Copy Markdown
Contributor

@MarijnS95 MarijnS95 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM; I can mostly see where the flow is intended to be going, albeit this still needs quite a significant portion of helpers to keep the current APIs working before they're migrated to the new createTexture() call with (more) general arguments.

Left a few notes where comments could be better, specifically some comments that seem to have appeared on the wrong line (maybe a rebase artifact?) but nothing major.

Comment on lines +1 to +11
//===- FormatConversion.h - Refactoring helpers ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Transitional helpers for converting between the legacy DataFormat + Channels
// description system and the unified Format enum. This file should be deleted
// once the pipeline is fully migrated to use Format directly.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a tracking issue for this conversion and removal?


Range.memory = ResRef.Host.Memory;
vkMapMemory(Device, IS.RTReadback->Memory, 0, VK_WHOLE_SIZE, 0, &Mapped);
vkInvalidateMappedMemoryRanges(Device, 1, &Range);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

@EmilioLaiso EmilioLaiso force-pushed the render-backend-api-texture branch from f10c02a to 5527e94 Compare April 13, 2026 13:00
@EmilioLaiso EmilioLaiso force-pushed the render-backend-api-texture branch from 170b07b to 5527e94 Compare April 13, 2026 13:40
…oryLocation` and `Format` types. Add `FormatConversion.h` containing bridge functions between old and new API.
…earDepthStencil` types defined in `Texture.h` and `validateTextureCreateDesc` function

Add `createTexture` function in device and supporting function `createRenderTargetFromCPUBuffer`
…eanup code to use the new helper functions
…ncil support to both MTL and DX backend to align with behaviour of VK backend
@EmilioLaiso EmilioLaiso force-pushed the render-backend-api-texture branch from 5527e94 to fd2c6de Compare April 13, 2026 14:31
@EmilioLaiso EmilioLaiso force-pushed the render-backend-api-texture branch from fd2c6de to 824ef1e Compare April 13, 2026 14:37
Copy link
Copy Markdown
Contributor

@s-perron s-perron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at the Vulkan code. Looks good to me. My only real question is the use of std::shared_ptr. If other are okay with it, I won't get in the way.

// Creates a render target texture using the format and dimensions from a
// CPUBuffer. Does not upload the buffer's data — only uses its description to
// configure the texture.
llvm::Expected<std::shared_ptr<Texture>>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to use std::shared_ptr? I know a lot of projects avoid using it because it is slow.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend using the shared_ptr. We want to be able to use reference counting to determine if resources need to be kept alive so that we can free them once they are no longer being used on the GPU timeline.

IMO the overhead of shared_ptr is a bit overblown (an atomic increment on copy). If we ever run into a case where we need thousands of textures that need to be kept alive we can look at alternative solutions for those use cases. However, in my experience, that case is only there for bindless resources where you are going to need an alternative anyway.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to revisit this. I'm not sure how you count "thousands of textures", but, as the number of tests increases, we could easily reach that over all of the tests. I'll let others like @bogner and @llvm-beanz give their opinions.

I'll go along with what the community thinks.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@manon-traverse - can you file an issue to follow up on this please? Ideally, we'd get consensus before the PR is merged, but we as long as we figure it all out it's ok to that post-merge.

Comment on lines +622 to +624
std::shared_ptr<VulkanTexture> RenderTarget;
std::shared_ptr<VulkanBuffer> RTReadback;
std::shared_ptr<VulkanTexture> DepthStencil;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm use to the Google style guide. We generally do not allow std::shared_ptr unless there is a very good reason for it.

I've only looked at the code quickly. However, would it be possible to make the std::unqiue_ptr to say that they are owned by the InvocationState?

I'll don't have strong opinions for this project, but we should make a conscience decision.

@manon-traverse
Copy link
Copy Markdown
Contributor

manon-traverse commented Apr 14, 2026

This PR fails some CI tests, but only after changing the name of a getter (unrelated to any errors). It fails on Mac because that machine is out of storage. Intel-clang failure is one that also happens on main, I am going to assume this is because of a change in the llvm-project repo.

Because these reasons have nothing to do with the PR and enough reviewing and applying feedback has happened I am gonig to merge this PR so we can move forward. If any more issues arise, we can address those in follow-up PRs.

@manon-traverse manon-traverse merged commit 8c6a168 into llvm:main Apr 14, 2026
17 of 23 checks passed
@MarijnS95 MarijnS95 deleted the render-backend-api-texture branch April 14, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants