Skip to content

Commit da64e01

Browse files
committed
hal tests are working
1 parent 59d3650 commit da64e01

59 files changed

Lines changed: 331 additions & 2581 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

main.sharpmake.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,12 @@ public override void ConfigureAll(Configuration conf, CustomTarget target)
251251
conf.TargetCopyFilesToSubDirectory.Add(new KeyValuePair<string, string>(Vcpkg.DebugBin + @"\D3D12Core.dll", "D3D12"));
252252
conf.TargetCopyFilesToSubDirectory.Add(new KeyValuePair<string, string>(Vcpkg.DebugBin + @"\d3d12SDKLayers.dll", "D3D12"));
253253

254+
// Per-backend module wrappers: compile only the active backend's wrapper.
255+
if (target.Backend == Backend.D3D12)
256+
conf.SourceFilesBuildExcludeRegex.Add(@".*\\Modules\\vulkan\\.*");
257+
else // Vulkan
258+
conf.SourceFilesBuildExcludeRegex.Add(@".*\\Modules\\d3d12\\.*");
259+
254260
conf.Options.Add(new Sharpmake.Options.Vc.Compiler.DisableSpecificWarnings("5260")); // adding inline to header units
255261

256262
}

sources/Core/patterns/Singleton.ixx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public:
5151

5252
if (instance) return instance.get();
5353

54-
ASSERT(first);
54+
//ASSERT(first);
5555
first = false;
5656
if constexpr (HasCreationFunc<T>)
5757
{

sources/HAL/API/D3D12/HAL.D3D12.PipelineState.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ namespace HAL
391391
slots.merge(desc.amplification->slots_usage);
392392
}
393393

394-
ASSERT(!slots.empty());
394+
// ASSERT(!slots.empty());
395395
{
396396
auto RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
397397
RasterizerState.CullMode = to_native(desc.rasterizer.cull_mode);

sources/HAL/API/D3D12/HAL.D3D12.Queue.cpp

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,10 @@ import HAL;
88
namespace HAL
99
{
1010

11-
Queue::Queue(CommandListType type, Device& device) : commandListCounter(device), type(type), device(device)
12-
{
13-
API::Queue::construct(type, &device);
14-
m_fenceValue = 0;
15-
del_func = [this](CommandList* list)
16-
{
17-
if (stop)
18-
delete list;
19-
else
20-
{
21-
std::lock_guard<std::mutex> g(list_mutex);
22-
lists.emplace(list, del_func);
23-
}
24-
};
25-
26-
del_transition = [this](TransitionCommandList* list)
27-
{
28-
if (stop)
29-
delete list;
30-
else
31-
{
32-
std::lock_guard<std::mutex> g(list_mutex);
33-
transition_lists.emplace(list, del_transition);
34-
}
35-
};
36-
}
11+
// NOTE: the shared HAL::Queue(CommandListType, Device&) constructor is
12+
// defined in the backend-neutral sources/HAL/HAL.Queue.cpp (it just calls
13+
// API::Queue::construct). Do not redefine it here — doing so produces an
14+
// LNK2005 duplicate-symbol error at executable link time.
3715

3816
void Queue::update_tile_mappings(const update_tiling_info& infos)
3917
{

sources/HAL/API/D3D12/HAL.D3D12.Resource.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ namespace HAL
4545
{
4646
GPUAddressPtr Resource::get_address() { return address; }
4747

48+
void* Resource::get_cpu_mapping()
49+
{
50+
void* ptr = nullptr;
51+
if (native_resource)
52+
native_resource->Map(0, nullptr, &ptr);
53+
return ptr;
54+
}
55+
4856
void Resource::init(Device& device, const ResourceDesc& _desc, const PlacementAddress& address, TextureLayout initialLayout)
4957
{
5058
auto THIS = static_cast<HAL::Resource*>(this);
@@ -173,12 +181,14 @@ namespace HAL
173181
IID_PPV_ARGS(&native_resource)));
174182
}
175183
auto prev_flags = THIS->desc.Flags;
176-
init(native_resource, initialLayout, device);
184+
init(NativeImportHandle{ native_resource }, initialLayout, device);
177185
THIS->desc.Flags |= prev_flags;
178186
}
179187

180-
void Resource::init(D3D::Resource resource, TextureLayout layout, Device& device)
188+
void Resource::init(const NativeImportHandle& handle, TextureLayout layout, Device& device)
181189
{
190+
native_resource = handle.resource;
191+
182192
auto THIS = static_cast<HAL::Resource*>(this);
183193
THIS->m_device = static_cast<HAL::Device*>(&device);
184194

@@ -247,9 +257,9 @@ namespace HAL
247257
init(device, desc, address, TextureLayout::UNDEFINED);
248258
}
249259

250-
Resource::Resource(Device& device, const D3D::Resource& resource, TextureLayout initialLayout) :state_manager(this), tiled_manager(this)
260+
Resource::Resource(Device& device, const API::NativeImportHandle& handle, TextureLayout initialLayout) :state_manager(this), tiled_manager(this)
251261
{
252-
native_resource = resource;
262+
native_resource = handle.resource;
253263
m_device = &device;
254264

255265
D3D12_HEAP_PROPERTIES HeapProperties;
@@ -258,7 +268,7 @@ namespace HAL
258268

259269
heap_type = from_native(HeapProperties.Type);
260270

261-
init(native_resource, initialLayout, device);
271+
init(handle, initialLayout, device);
262272

263273
}
264274

sources/HAL/API/D3D12/HAL.D3D12.Resource.ixx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,29 @@ export namespace HAL
2020

2121
namespace API {
2222

23+
// NativeImportHandle: wraps an externally-owned D3D12 resource
24+
// (e.g. a swapchain back-buffer). The Vulkan backend provides its own
25+
// version of this struct in HAL.Vulkan.Resource.ixx.
26+
struct NativeImportHandle
27+
{
28+
D3D::Resource resource;
29+
};
30+
2331
class Resource
2432
{
2533
GPUAddressPtr address;
2634
public:
2735
using ptr = std::shared_ptr<Resource>;
2836
void init(Device& device, const ResourceDesc& desc, const PlacementAddress& address, TextureLayout initialLayout = TextureLayout::UNDEFINED);
29-
void init(D3D::Resource resource, TextureLayout layout, Device& device);
37+
38+
// Replaces the old D3D::Resource constructor; backend-neutral.
39+
void init(const NativeImportHandle& handle, TextureLayout layout, Device& device);
3040

3141
GPUAddressPtr get_address();
3242

43+
// CPU mapping for UPLOAD / READBACK heaps.
44+
void* get_cpu_mapping();
45+
3346
D3D::Resource native_resource;
3447

3548
auto get_dx() const

sources/HAL/API/Vulkan/HAL.Vulkan.CommandList.cpp

Lines changed: 82 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ namespace HAL::API
235235
if (!rtv || !rtv->Resource) return;
236236

237237
auto& api = static_cast<API::Resource&>(*rtv->Resource);
238-
VkImageView view = api.get_import_handle().image_view;
238+
VkImageView view = api.get_vk_image_view();
239239
if (view == VK_NULL_HANDLE) return;
240240

241241
end_rendering_if_active();
@@ -280,7 +280,7 @@ namespace HAL::API
280280
if (!dv || !dv->Resource) return;
281281

282282
auto& api = static_cast<API::Resource&>(*dv->Resource);
283-
VkImageView view = api.get_import_handle().image_view;
283+
VkImageView view = api.get_vk_image_view();
284284
if (view == VK_NULL_HANDLE) return;
285285

286286
end_rendering_if_active();
@@ -311,7 +311,33 @@ namespace HAL::API
311311
if (d) clear_depth(dsv, fd);
312312
}
313313
void CommandList::clear_stencil(const DSVHandle& dsv, UINT8) {}
314-
void CommandList::clear_uav(const UAVHandle&, vec4) {}
314+
void CommandList::clear_uav(const UAVHandle& h, vec4 color)
315+
{
316+
if (vk_cmd == VK_NULL_HANDLE || !h.is_valid()) return;
317+
318+
auto& ri = h.get_resource_info();
319+
auto* uav = std::get_if<Views::UnorderedAccess>(&ri.view);
320+
if (!uav || !uav->Resource) return;
321+
322+
auto& api = static_cast<API::Resource&>(*uav->Resource);
323+
VkImage img = api.get_vk_image();
324+
if (img == VK_NULL_HANDLE) return;
325+
326+
end_rendering_if_active();
327+
328+
VkClearColorValue cv{};
329+
cv.float32[0] = color.x;
330+
cv.float32[1] = color.y;
331+
cv.float32[2] = color.z;
332+
cv.float32[3] = color.w;
333+
334+
// UAV/storage images live in GENERAL layout (the HAL transitions to
335+
// UNORDERED_ACCESS before this call).
336+
VkImageSubresourceRange range{ VK_IMAGE_ASPECT_COLOR_BIT,
337+
0, VK_REMAINING_MIP_LEVELS,
338+
0, VK_REMAINING_ARRAY_LAYERS };
339+
vkCmdClearColorImage(vk_cmd, img, VK_IMAGE_LAYOUT_GENERAL, &cv, 1, &range);
340+
}
315341

316342
// ---- Lazy render-pass start (for draw calls) ----------------------------
317343

@@ -594,21 +620,67 @@ namespace HAL::API
594620
dst_api.get_vk_buffer(), 1, &region);
595621
}
596622

623+
// Build a VkBufferImageCopy from the HAL texture_layout. The staging buffer
624+
// rows are 256-byte aligned (see Device::get_texture_layout), so bufferRowLength
625+
// must be expressed in texels = row_stride / bytes-per-texel (NOT 0, which would
626+
// assume tight packing and shear the image for non-aligned widths).
627+
static VkBufferImageCopy make_buffer_image_copy(const HAL::Resource& resource,
628+
ivec3 offset, ivec3 box, UINT sub_resource,
629+
const ResourceAddress& address,
630+
const texture_layout& layout)
631+
{
632+
if (box.y == 0) box.y = 1;
633+
if (box.z == 0) box.z = 1;
634+
635+
auto sinfo = layout.format.surface_info({ (uint)box.x, (uint)box.y });
636+
uint bpt = box.x ? (uint)(sinfo.rowBytes / box.x) : 4u; // bytes per texel
637+
if (bpt == 0) bpt = 4u;
638+
639+
auto& tdesc = resource.get_desc().as_texture();
640+
uint mips = tdesc.MipLevels ? tdesc.MipLevels : 1u;
641+
642+
VkBufferImageCopy region{};
643+
region.bufferOffset = address.resource_offset;
644+
region.bufferRowLength = (layout.row_stride / bpt);
645+
region.bufferImageHeight = 0; // tight vertically: rows = imageExtent.height
646+
region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT,
647+
sub_resource % mips, sub_resource / mips, 1 };
648+
region.imageOffset = { offset.x, offset.y, offset.z };
649+
region.imageExtent = { (uint32_t)box.x, (uint32_t)box.y, (uint32_t)box.z };
650+
return region;
651+
}
652+
597653
void CommandList::update_texture(HAL::Resource* resource, ivec3 offset, ivec3 box,
598654
UINT sub_resource, ResourceAddress address,
599655
texture_layout layout)
600656
{
601-
if (!resource || vk_cmd == VK_NULL_HANDLE) return;
657+
if (!resource || vk_cmd == VK_NULL_HANDLE || !address.resource) return;
602658
auto& dst = static_cast<API::Resource&>(*resource);
603-
if (dst.get_vk_image() == VK_NULL_HANDLE) return;
659+
auto& staging = static_cast<API::Resource&>(*address.resource);
660+
if (dst.get_vk_image() == VK_NULL_HANDLE || staging.get_vk_buffer() == VK_NULL_HANDLE)
661+
return;
604662

605-
// `address` is a GPU address to a staging buffer; we need the VkBuffer.
606-
// Phase 5: look up staging buffer from the address.
607-
// For now this is a stub — real implementation needs the staging buffer handle.
663+
// The HAL transitions `resource` to COPY_DEST (→ TRANSFER_DST_OPTIMAL) before this call.
664+
VkBufferImageCopy region = make_buffer_image_copy(*resource, offset, box, sub_resource, address, layout);
665+
vkCmdCopyBufferToImage(vk_cmd, staging.get_vk_buffer(), dst.get_vk_image(),
666+
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
608667
}
609668

610-
void CommandList::read_texture(const HAL::Resource*, ivec3, ivec3, UINT,
611-
ResourceAddress, texture_layout) {}
669+
void CommandList::read_texture(const HAL::Resource* resource, ivec3 offset, ivec3 box,
670+
UINT sub_resource, ResourceAddress target,
671+
texture_layout layout)
672+
{
673+
if (!resource || vk_cmd == VK_NULL_HANDLE || !target.resource) return;
674+
auto& src = static_cast<const API::Resource&>(*resource);
675+
auto& staging = static_cast<API::Resource&>(*target.resource);
676+
if (src.get_vk_image() == VK_NULL_HANDLE || staging.get_vk_buffer() == VK_NULL_HANDLE)
677+
return;
678+
679+
// The HAL transitions `resource` to COPY_SOURCE (→ TRANSFER_SRC_OPTIMAL) before this call.
680+
VkBufferImageCopy region = make_buffer_image_copy(*resource, offset, box, sub_resource, target, layout);
681+
vkCmdCopyImageToBuffer(vk_cmd, src.get_vk_image(),
682+
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, staging.get_vk_buffer(), 1, &region);
683+
}
612684

613685
void CommandList::copy_texture(const Resource::ptr& dest, int dest_sub,
614686
const Resource::ptr& source, int src_sub)

sources/HAL/API/Vulkan/HAL.Vulkan.DescriptorHeap.cpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,14 @@ namespace HAL
3232
{
3333
// ---- Descriptor (slot within a heap) -----------------------------------
3434

35-
Descriptor::Descriptor(DescriptorHeap& heap, uint offset) : heap(heap), offset(offset) {}
35+
Descriptor::Descriptor(DescriptorHeap& heap, uint offset) : heap(heap), offset(offset)
36+
{
37+
// Vulkan has no CPU/GPU descriptor handles; the bindless slot index is
38+
// carried in the stub handle value so the shared HAL::Handle interface
39+
// (get_cpu/get_gpu) keeps working unchanged.
40+
cpu_handle = { static_cast<SIZE_T>(offset) };
41+
gpu_handle = { static_cast<UINT64>(offset) };
42+
}
3643

3744
void Descriptor::place(const Views::ShaderResource& v)
3845
{
@@ -173,18 +180,6 @@ namespace HAL
173180
(void)r;
174181
}
175182

176-
D3D12_CPU_DESCRIPTOR_HANDLE Descriptor::get_cpu()
177-
{
178-
// Return the slot index as the cpu handle value (for resource info tracking).
179-
return { static_cast<SIZE_T>(offset) };
180-
}
181-
182-
D3D12_GPU_DESCRIPTOR_HANDLE Descriptor::get_gpu()
183-
{
184-
// Bindless index: the shader accesses heap[offset] in the descriptor array.
185-
return { static_cast<UINT64>(offset) };
186-
}
187-
188183
uint DescriptorHeap::get_size() { return desc.Count; }
189184

190185
namespace API
@@ -260,10 +255,10 @@ namespace HAL
260255
vkDestroyDescriptorPool(vk_dev, vk_pool, nullptr);
261256
}
262257

263-
Descriptor DescriptorHeap::operator[](uint i)
258+
HAL::Descriptor DescriptorHeap::operator[](uint i)
264259
{
265260
auto THIS = static_cast<HAL::DescriptorHeap*>(this);
266-
return Descriptor{ *THIS, i };
261+
return HAL::Descriptor{ *THIS, i };
267262
}
268263
}
269264
}

sources/HAL/API/Vulkan/HAL.Vulkan.DescriptorHeap.ixx

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@ export namespace HAL
1313
namespace API
1414
{
1515
class DescriptorHeap;
16+
17+
// Vulkan equivalent of D3D12's API::Descriptor base. The shared
18+
// HAL::Descriptor (HAL.DescriptorHeap.ixx) derives from this and the
19+
// public HAL::Handle interface still exposes D3D12-style handles
20+
// (stubbed in Vulkan builds); for Vulkan the handle value carries the
21+
// bindless slot index.
22+
class Descriptor
23+
{
24+
protected:
25+
D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle = {};
26+
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle = {};
27+
public:
28+
D3D12_CPU_DESCRIPTOR_HANDLE get_cpu() const { return cpu_handle; }
29+
D3D12_GPU_DESCRIPTOR_HANDLE get_gpu() const { return gpu_handle; }
30+
};
1631
}
1732

1833
struct DescriptorHeapDesc
@@ -23,32 +38,7 @@ export namespace HAL
2338
};
2439

2540
class DescriptorHeap;
26-
27-
// Descriptor — Vulkan descriptor set entry.
28-
// Keeps the same interface as the D3D12 version so HAL.DescriptorHeap.ixx
29-
// compiles unchanged. get_cpu() / get_gpu() return stub handles; real
30-
// Vulkan descriptor management will be added in Phase 4.
31-
class Descriptor
32-
{
33-
DescriptorHeap& heap;
34-
const uint offset;
35-
36-
Descriptor(DescriptorHeap& heap, uint offset);
37-
38-
friend class API::DescriptorHeap;
39-
public:
40-
void operator=(const Descriptor& r);
41-
42-
void place(const Views::ShaderResource& view);
43-
void place(const Views::UnorderedAccess& view);
44-
void place(const Views::RenderTarget& view);
45-
void place(const Views::ConstantBuffer& view);
46-
void place(const Views::DepthStencil& view);
47-
48-
// Return stub handles (no D3D12 dependency in Vulkan builds)
49-
D3D12_CPU_DESCRIPTOR_HANDLE get_cpu();
50-
D3D12_GPU_DESCRIPTOR_HANDLE get_gpu();
51-
};
41+
class Descriptor; // shared HAL::Descriptor (HAL.DescriptorHeap.ixx)
5242

5343
namespace API
5444
{
@@ -65,12 +55,12 @@ export namespace HAL
6555

6656
uint handle_size = 0;
6757

68-
friend class Descriptor;
58+
friend class HAL::Descriptor;
6959
public:
7060
DescriptorHeap(Device& device, const DescriptorHeapDesc& desc);
7161
virtual ~DescriptorHeap();
7262

73-
Descriptor operator[](uint i);
63+
HAL::Descriptor operator[](uint i);
7464

7565
// Returns the backing VkDescriptorSet so CommandList can bind it.
7666
VkDescriptorSet get_vk_set() const noexcept { return vk_set; }

0 commit comments

Comments
 (0)