Initial graphics implementation.

This commit is contained in:
Skyth 2024-10-06 20:12:17 +03:00
parent b2f92ff2a9
commit 24830e1326
18 changed files with 9001 additions and 54 deletions

3
.gitmodules vendored
View file

@ -8,3 +8,6 @@
[submodule "thirdparty/unordered_dense"]
path = thirdparty/unordered_dense
url = https://github.com/martinus/unordered_dense.git
[submodule "thirdparty/D3D12MemoryAllocator"]
path = thirdparty/D3D12MemoryAllocator
url = https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator.git

View file

@ -6,13 +6,14 @@ add_compile_definitions(SWA_IMPL)
add_compile_definitions(SDL_MAIN_HANDLED)
# Microsoft wtf?
add_compile_definitions(_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR )
add_compile_definitions(
_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR
_HAS_EXCEPTIONS=0)
add_compile_options(
"/D_HAS_EXCEPTIONS=0"
"/fp:strict"
"/GS-"
"/EHa-"
"/EHs-c-"
"-march=sandybridge"
"-fno-strict-aliasing")
@ -41,6 +42,7 @@ set(SWA_CPU_CXX_SOURCES
set(SWA_GPU_CXX_SOURCES
"gpu/window.cpp"
"gpu/video.cpp"
"gpu/rhi/rt64_d3d12.cpp"
)
set(SWA_APU_CXX_SOURCES
@ -76,8 +78,15 @@ target_link_libraries(UnleashedRecomp PUBLIC
winmm
ntdll
comctl32
d3d12
dxgi
)
target_include_directories(UnleashedRecomp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(UnleashedRecomp PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${SWA_THIRDPARTY_ROOT}/ddspp
${SWA_THIRDPARTY_ROOT}/D3D12MemoryAllocator/include
${SWA_THIRDPARTY_ROOT}/D3D12MemoryAllocator/src)
target_precompile_headers(UnleashedRecomp PUBLIC ${SWA_PRECOMPILED_HEADERS})
target_compile_definitions(PowerRecomp PRIVATE CONFIG_FILE_PATH=\"${CMAKE_CURRENT_SOURCE_DIR}/ppc/config/SWA.toml\")

View file

@ -1,9 +1,7 @@
#include "window.h"
#include <config.h>
#include <kernel/function.h>
SDL_Window* Window::s_window = nullptr;
void* Window::s_windowHandle = nullptr;
#include <SDL_syswm.h>
void Window::Init()
{
@ -15,5 +13,19 @@ void Window::Init()
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
s_window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_RESIZABLE);
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(s_window, &info);
s_windowHandle = info.info.win.window;
}
// CApplication::Update
PPC_FUNC_IMPL(__imp__sub_822C1130);
PPC_FUNC(sub_822C1130)
{
SDL_PumpEvents();
SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
__imp__sub_822C1130(ctx, base);
}

View file

@ -3,8 +3,8 @@
struct Window
{
static SDL_Window* s_window;
static void* s_windowHandle;
static inline SDL_Window* s_window;
static inline HWND s_windowHandle;
static void Init();
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,450 @@
//
// RT64
//
#pragma once
#include "rt64_render_interface.h"
#include <map>
#include <mutex>
#include <unordered_map>
#include <d3d12.h>
#include <dxgi1_4.h>
#include "D3D12MemAlloc.h"
namespace RT64 {
struct D3D12Buffer;
struct D3D12CommandQueue;
struct D3D12Device;
struct D3D12GraphicsPipeline;
struct D3D12Interface;
struct D3D12Pipeline;
struct D3D12Pool;
struct D3D12PipelineLayout;
struct D3D12Texture;
struct D3D12DescriptorHeapAllocator {
enum : uint32_t {
INVALID_OFFSET = 0xFFFFFFFFU
};
// Reference implementation http://diligentgraphics.com/diligent-engine/architecture/d3d12/variable-size-memory-allocations-manager/
struct FreeBlock;
typedef std::map<uint32_t, FreeBlock> OffsetFreeBlockMap;
typedef std::multimap<uint32_t, OffsetFreeBlockMap::iterator> SizeFreeBlockMap;
struct FreeBlock {
uint32_t size;
SizeFreeBlockMap::iterator sizeMapIterator;
FreeBlock(uint32_t size) {
this->size = size;
}
};
ID3D12DescriptorHeap *hostHeap = nullptr;
ID3D12DescriptorHeap *shaderHeap = nullptr;
uint32_t heapSize = 0;
uint32_t freeSize = 0;
D3D12Device *device = nullptr;
D3D12_CPU_DESCRIPTOR_HANDLE hostCPUDescriptorHandle = {};
D3D12_CPU_DESCRIPTOR_HANDLE shaderCPUDescriptorHandle = {};
D3D12_GPU_DESCRIPTOR_HANDLE shaderGPUDescriptorHandle = {};
UINT descriptorHandleIncrement = 0;
OffsetFreeBlockMap offsetFreeBlockMap;
SizeFreeBlockMap sizeFreeBlockMap;
std::mutex allocationMutex;
D3D12DescriptorHeapAllocator(D3D12Device *device, uint32_t heapSize, D3D12_DESCRIPTOR_HEAP_TYPE heapType);
~D3D12DescriptorHeapAllocator();
void addFreeBlock(uint32_t offset, uint32_t size);
uint32_t allocate(uint32_t size);
void free(uint32_t offset, uint32_t size);
D3D12_CPU_DESCRIPTOR_HANDLE getHostCPUHandleAt(uint32_t index) const;
D3D12_CPU_DESCRIPTOR_HANDLE getShaderCPUHandleAt(uint32_t index) const;
D3D12_GPU_DESCRIPTOR_HANDLE getShaderGPUHandleAt(uint32_t index) const;
};
struct D3D12DescriptorSet : RenderDescriptorSet {
D3D12Device *device = nullptr;
struct HeapAllocation {
uint32_t offset = 0;
uint32_t count = 0;
uint32_t hostModifiedIndex = 0;
uint32_t hostModifiedCount = 0;
};
HeapAllocation viewAllocation;
HeapAllocation samplerAllocation;
std::vector<RenderDescriptorRangeType> descriptorTypes;
std::vector<uint32_t> descriptorHeapIndices;
uint32_t descriptorTypeMaxIndex = 0;
D3D12DescriptorSet(D3D12Device *device, const RenderDescriptorSetDesc &desc);
~D3D12DescriptorSet() override;
void setBuffer(uint32_t descriptorIndex, const RenderBuffer *buffer, uint64_t bufferSize, const RenderBufferStructuredView *bufferStructuredView, const RenderBufferFormattedView *bufferFormattedView) override;
void setTexture(uint32_t descriptorIndex, const RenderTexture *texture, RenderTextureLayout textureLayout, const RenderTextureView *textureView) override;
void setSampler(uint32_t descriptorIndex, const RenderSampler *sampler) override;
void setAccelerationStructure(uint32_t descriptorIndex, const RenderAccelerationStructure *accelerationStructure) override;
void setSRV(uint32_t descriptorIndex, ID3D12Resource *resource, const D3D12_SHADER_RESOURCE_VIEW_DESC *viewDesc);
void setUAV(uint32_t descriptorIndex, ID3D12Resource *resource, const D3D12_UNORDERED_ACCESS_VIEW_DESC *viewDesc);
void setCBV(uint32_t descriptorIndex, ID3D12Resource *resource, uint64_t bufferSize);
void setHostModified(HeapAllocation &heapAllocation, uint32_t heapIndex);
};
struct D3D12SwapChain : RenderSwapChain {
IDXGISwapChain3 *d3d = nullptr;
HANDLE waitableObject = 0;
D3D12CommandQueue *commandQueue = nullptr;
RenderWindow renderWindow = {};
std::vector<D3D12Texture> textures;
uint32_t textureCount = 0;
RenderFormat format = RenderFormat::UNKNOWN;
DXGI_FORMAT nativeFormat = DXGI_FORMAT_UNKNOWN;
uint32_t width = 0;
uint32_t height = 0;
uint32_t refreshRate = 0;
D3D12SwapChain(D3D12CommandQueue *commandQueue, RenderWindow renderWindow, uint32_t textureCount, RenderFormat format);
~D3D12SwapChain() override;
bool present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) override;
bool resize() override;
bool needsResize() const override;
uint32_t getWidth() const override;
uint32_t getHeight() const override;
RenderTexture *getTexture(uint32_t textureIndex) override;
uint32_t getTextureCount() const override;
bool acquireTexture(RenderCommandSemaphore *signalSemaphore, uint32_t *textureIndex) override;
RenderWindow getWindow() const override;
bool isEmpty() const override;
uint32_t getRefreshRate() const override;
void getWindowSize(uint32_t &dstWidth, uint32_t &dstHeight) const;
void setTextures();
};
struct D3D12Framebuffer : RenderFramebuffer {
D3D12Device *device = nullptr;
uint32_t width = 0;
uint32_t height = 0;
std::vector<const D3D12Texture *> colorTargets;
const D3D12Texture *depthTarget = nullptr;
std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> colorHandles;
D3D12_CPU_DESCRIPTOR_HANDLE depthHandle = {};
D3D12Framebuffer(D3D12Device *device, const RenderFramebufferDesc &desc);
~D3D12Framebuffer() override;
uint32_t getWidth() const override;
uint32_t getHeight() const override;
};
struct D3D12CommandList : RenderCommandList {
ID3D12GraphicsCommandList4 *d3d = nullptr;
ID3D12CommandAllocator *commandAllocator = nullptr;
D3D12Device *device = nullptr;
RenderCommandListType type = RenderCommandListType::UNKNOWN;
const D3D12Framebuffer *targetFramebuffer = nullptr;
bool targetFramebufferSamplePositionsSet = false;
bool open = false;
const D3D12PipelineLayout *activeComputePipelineLayout = nullptr;
const D3D12PipelineLayout *activeGraphicsPipelineLayout = nullptr;
const D3D12GraphicsPipeline *activeGraphicsPipeline = nullptr;
bool descriptorHeapsSet = false;
D3D12_PRIMITIVE_TOPOLOGY activeTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
bool activeSamplePositions = false;
D3D12CommandList(D3D12Device *device, RenderCommandListType type);
~D3D12CommandList() override;
bool isOpen() override;
void begin() override;
void end() override;
void barriers(RenderBarrierStages stages, const RenderBufferBarrier *bufferBarriers, uint32_t bufferBarriersCount, const RenderTextureBarrier *textureBarriers, uint32_t textureBarriersCount) override;
void dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) override;
void traceRays(uint32_t width, uint32_t height, uint32_t depth, RenderBufferReference shaderBindingTable, const RenderShaderBindingGroupsInfo &shaderBindingGroupsInfo) override;
void drawInstanced(uint32_t vertexCountPerInstance, uint32_t instanceCount, uint32_t startVertexLocation, uint32_t startInstanceLocation) override;
void drawIndexedInstanced(uint32_t indexCountPerInstance, uint32_t instanceCount, uint32_t startIndexLocation, int32_t baseVertexLocation, uint32_t startInstanceLocation) override;
void setPipeline(const RenderPipeline *pipeline) override;
void setComputePipelineLayout(const RenderPipelineLayout *pipelineLayout) override;
void setComputePushConstants(uint32_t rangeIndex, const void *data) override;
void setComputeDescriptorSet(RenderDescriptorSet *descriptorSet, uint32_t setIndex) override;
void setGraphicsPipelineLayout(const RenderPipelineLayout *pipelineLayout) override;
void setGraphicsPushConstants(uint32_t rangeIndex, const void *data) override;
void setGraphicsDescriptorSet(RenderDescriptorSet *descriptorSet, uint32_t setIndex) override;
void setGraphicsRootDescriptor(RenderBufferReference bufferReference, uint32_t rootDescriptorIndex) override;
void setRaytracingPipelineLayout(const RenderPipelineLayout *pipelineLayout) override;
void setRaytracingPushConstants(uint32_t rangeIndex, const void *data) override;
void setRaytracingDescriptorSet(RenderDescriptorSet *descriptorSet, uint32_t setIndex) override;
void setIndexBuffer(const RenderIndexBufferView *view) override;
void setVertexBuffers(uint32_t startSlot, const RenderVertexBufferView *views, uint32_t viewCount, const RenderInputSlot *inputSlots) override;
void setViewports(const RenderViewport *viewports, uint32_t count) override;
void setScissors(const RenderRect *scissorRects, uint32_t count) override;
void setFramebuffer(const RenderFramebuffer *framebuffer) override;
void clearColor(uint32_t attachmentIndex, RenderColor colorValue, const RenderRect *clearRects, uint32_t clearRectsCount) override;
void clearDepth(bool clearDepth, float depthValue, const RenderRect *clearRects, uint32_t clearRectsCount) override;
void copyBufferRegion(RenderBufferReference dstBuffer, RenderBufferReference srcBuffer, uint64_t size) override;
void copyTextureRegion(const RenderTextureCopyLocation &dstLocation, const RenderTextureCopyLocation &srcLocation, uint32_t dstX, uint32_t dstY, uint32_t dstZ, const RenderBox *srcBox) override;
void copyBuffer(const RenderBuffer *dstBuffer, const RenderBuffer *srcBuffer) override;
void copyTexture(const RenderTexture *dstTexture, const RenderTexture *srcTexture) override;
void resolveTexture(const RenderTexture *dstTexture, const RenderTexture *srcTexture) override;
void resolveTextureRegion(const RenderTexture *dstTexture, uint32_t dstX, uint32_t dstY, const RenderTexture *srcTexture, const RenderRect *srcRect) override;
void buildBottomLevelAS(const RenderAccelerationStructure *dstAccelerationStructure, RenderBufferReference scratchBuffer, const RenderBottomLevelASBuildInfo &buildInfo) override;
void buildTopLevelAS(const RenderAccelerationStructure *dstAccelerationStructure, RenderBufferReference scratchBuffer, RenderBufferReference instancesBuffer, const RenderTopLevelASBuildInfo &buildInfo) override;
void checkDescriptorHeaps();
void notifyDescriptorHeapWasChangedExternally();
void checkTopology();
void checkFramebufferSamplePositions();
void setSamplePositions(const RenderTexture *texture);
void resetSamplePositions();
void setDescriptorSet(const D3D12PipelineLayout *activePipelineLayout, RenderDescriptorSet *descriptorSet, uint32_t setIndex, bool setCompute);
void setRootDescriptorTable(D3D12DescriptorHeapAllocator *heapAllocator, D3D12DescriptorSet::HeapAllocation &heapAllocation, uint32_t rootIndex, bool setCompute);
void setRootDescriptor(const D3D12PipelineLayout *activePipelineLayout, RenderBufferReference bufferReference, uint32_t setIndex, bool setCompute);
};
struct D3D12CommandFence : RenderCommandFence {
ID3D12Fence *d3d = nullptr;
D3D12Device *device = nullptr;
HANDLE fenceEvent = 0;
UINT64 fenceValue = 0;
D3D12CommandFence(D3D12Device *device);
~D3D12CommandFence() override;
};
struct D3D12CommandSemaphore : RenderCommandSemaphore {
ID3D12Fence *d3d = nullptr;
D3D12Device *device = nullptr;
UINT64 semaphoreValue = 0;
D3D12CommandSemaphore(D3D12Device *device);
~D3D12CommandSemaphore() override;
};
struct D3D12CommandQueue : RenderCommandQueue {
ID3D12CommandQueue *d3d = nullptr;
D3D12Device *device = nullptr;
RenderCommandListType type = RenderCommandListType::UNKNOWN;
D3D12CommandQueue(D3D12Device *device, RenderCommandListType type);
~D3D12CommandQueue() override;
std::unique_ptr<RenderSwapChain> createSwapChain(RenderWindow renderWindow, uint32_t textureCount, RenderFormat format) override;
void executeCommandLists(const RenderCommandList **commandLists, uint32_t commandListCount, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount, RenderCommandSemaphore **signalSemaphores, uint32_t signalSemaphoreCount, RenderCommandFence *signalFence) override;
void waitForCommandFence(RenderCommandFence *fence) override;
};
struct D3D12Buffer : RenderBuffer {
ID3D12Resource *d3d = nullptr;
D3D12_RESOURCE_STATES resourceStates = D3D12_RESOURCE_STATE_COMMON;
D3D12Device *device = nullptr;
D3D12MA::Allocation *allocation = nullptr;
D3D12Pool *pool = nullptr;
RenderBufferDesc desc;
D3D12Buffer() = default;
D3D12Buffer(D3D12Device *device, D3D12Pool *pool, const RenderBufferDesc &desc);
~D3D12Buffer() override;
void *map(uint32_t subresource, const RenderRange *readRange) override;
void unmap(uint32_t subresource, const RenderRange *writtenRange) override;
std::unique_ptr<RenderBufferFormattedView> createBufferFormattedView(RenderFormat format) override;
void setName(const std::string &name) override;
};
struct D3D12BufferFormattedView : RenderBufferFormattedView {
RenderFormat format = RenderFormat::UNKNOWN;
D3D12Buffer *buffer = nullptr;
D3D12BufferFormattedView(D3D12Buffer *buffer, RenderFormat format);
~D3D12BufferFormattedView() override;
};
struct D3D12Texture : RenderTexture {
ID3D12Resource *d3d = nullptr;
D3D12_RESOURCE_STATES resourceStates = D3D12_RESOURCE_STATE_COMMON;
RenderTextureLayout layout = RenderTextureLayout::UNKNOWN;
D3D12Device *device = nullptr;
D3D12MA::Allocation *allocation = nullptr;
D3D12Pool *pool = nullptr;
RenderTextureDesc desc;
uint32_t targetAllocatorOffset = 0;
uint32_t targetEntryCount = 0;
bool targetHeapDepth = false;
D3D12Texture() = default;
D3D12Texture(D3D12Device *device, D3D12Pool *pool, const RenderTextureDesc &desc);
~D3D12Texture() override;
std::unique_ptr<RenderTextureView> createTextureView(const RenderTextureViewDesc &desc) override;
void setName(const std::string &name) override;
void createRenderTargetHeap();
void createDepthStencilHeap();
void releaseTargetHeap();
};
struct D3D12TextureView : RenderTextureView {
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
D3D12Texture *texture = nullptr;
RenderTextureViewDimension dimension = RenderTextureViewDimension::UNKNOWN;
uint32_t mipLevels = 0;
uint32_t mipSlice = 0;
D3D12TextureView(D3D12Texture *texture, const RenderTextureViewDesc &desc);
~D3D12TextureView() override;
};
struct D3D12AccelerationStructure :RenderAccelerationStructure {
D3D12Device *device = nullptr;
const D3D12Buffer *buffer = nullptr;
uint64_t offset = 0;
uint64_t size = 0;
RenderAccelerationStructureType type = RenderAccelerationStructureType::UNKNOWN;
D3D12AccelerationStructure(D3D12Device *device, const RenderAccelerationStructureDesc &desc);
~D3D12AccelerationStructure() override;
};
struct D3D12Pool : RenderPool {
D3D12MA::Pool *d3d = nullptr;
D3D12Device *device = nullptr;
RenderPoolDesc desc;
D3D12Pool(D3D12Device *device, const RenderPoolDesc &desc);
~D3D12Pool() override;
std::unique_ptr<RenderBuffer> createBuffer(const RenderBufferDesc &desc) override;
std::unique_ptr<RenderTexture> createTexture(const RenderTextureDesc &desc) override;
};
struct D3D12Shader : RenderShader {
std::vector<uint8_t> d3d;
std::string entryPointName;
D3D12Device *device = nullptr;
RenderShaderFormat format = RenderShaderFormat::UNKNOWN;
D3D12Shader(D3D12Device *device, const void *data, uint64_t size, const char *entryPointName, RenderShaderFormat format);
~D3D12Shader() override;
};
struct D3D12Sampler : RenderSampler {
D3D12_SAMPLER_DESC samplerDesc = {};
D3D12Device *device = nullptr;
RenderBorderColor borderColor = RenderBorderColor::UNKNOWN;
RenderShaderVisibility shaderVisibility = RenderShaderVisibility::UNKNOWN;
D3D12Sampler(D3D12Device *device, const RenderSamplerDesc &desc);
~D3D12Sampler() override;
};
struct D3D12Pipeline : RenderPipeline {
enum class Type {
Unknown,
Compute,
Graphics,
Raytracing
};
D3D12Device *device = nullptr;
Type type = Type::Unknown;
D3D12Pipeline(D3D12Device *device, Type type);
virtual ~D3D12Pipeline() override;
};
struct D3D12ComputePipeline : D3D12Pipeline {
ID3D12PipelineState *d3d = nullptr;
D3D12ComputePipeline(D3D12Device *device, const RenderComputePipelineDesc &desc);
~D3D12ComputePipeline() override;
virtual RenderPipelineProgram getProgram(const std::string &name) const override;
};
struct D3D12GraphicsPipeline : D3D12Pipeline {
ID3D12PipelineState *d3d = nullptr;
std::vector<RenderInputSlot> inputSlots;
D3D12_PRIMITIVE_TOPOLOGY topology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
D3D12GraphicsPipeline(D3D12Device *device, const RenderGraphicsPipelineDesc &desc);
~D3D12GraphicsPipeline() override;
virtual RenderPipelineProgram getProgram(const std::string &name) const override;
};
struct D3D12RaytracingPipeline : D3D12Pipeline {
ID3D12StateObject *stateObject = nullptr;
ID3D12StateObjectProperties *stateObjectProperties = nullptr;
std::vector<void *> programShaderIdentifiers;
std::unordered_map<std::string, RenderPipelineProgram> nameProgramMap;
const D3D12PipelineLayout *pipelineLayout = nullptr;
D3D12RaytracingPipeline(D3D12Device *device, const RenderRaytracingPipelineDesc &desc, const RenderPipeline *previousPipeline);
~D3D12RaytracingPipeline() override;
virtual RenderPipelineProgram getProgram(const std::string &name) const override;
};
struct D3D12PipelineLayout : RenderPipelineLayout {
ID3D12RootSignature *rootSignature = nullptr;
D3D12Device *device = nullptr;
std::vector<RenderPushConstantRange> pushConstantRanges;
std::vector<uint32_t> setViewRootIndices;
std::vector<uint32_t> setSamplerRootIndices;
std::vector<std::pair<uint32_t, RenderRootDescriptorType>> rootDescriptorRootIndicesAndTypes;
uint32_t setCount = 0;
uint32_t rootCount = 0;
D3D12PipelineLayout(D3D12Device *device, const RenderPipelineLayoutDesc &desc);
~D3D12PipelineLayout() override;
};
struct D3D12Device : RenderDevice {
ID3D12Device8 *d3d = nullptr;
D3D12Interface *renderInterface = nullptr;
IDXGIAdapter1 *adapter = nullptr;
D3D12MA::Allocator *allocator = nullptr;
D3D_SHADER_MODEL shaderModel = D3D_SHADER_MODEL(0);
std::unique_ptr<RenderPipelineLayout> rtDummyGlobalPipelineLayout;
std::unique_ptr<RenderPipelineLayout> rtDummyLocalPipelineLayout;
std::unique_ptr<D3D12DescriptorHeapAllocator> viewHeapAllocator;
std::unique_ptr<D3D12DescriptorHeapAllocator> samplerHeapAllocator;
std::unique_ptr<D3D12DescriptorHeapAllocator> colorTargetHeapAllocator;
std::unique_ptr<D3D12DescriptorHeapAllocator> depthTargetHeapAllocator;
RenderDeviceCapabilities capabilities;
RenderDeviceDescription description;
D3D12Device(D3D12Interface *renderInterface);
~D3D12Device() override;
std::unique_ptr<RenderCommandList> createCommandList(RenderCommandListType type) override;
std::unique_ptr<RenderDescriptorSet> createDescriptorSet(const RenderDescriptorSetDesc &desc) override;
std::unique_ptr<RenderShader> createShader(const void *data, uint64_t size, const char *entryPointName, RenderShaderFormat format) override;
std::unique_ptr<RenderSampler> createSampler(const RenderSamplerDesc &desc) override;
std::unique_ptr<RenderPipeline> createComputePipeline(const RenderComputePipelineDesc &desc) override;
std::unique_ptr<RenderPipeline> createGraphicsPipeline(const RenderGraphicsPipelineDesc &desc) override;
std::unique_ptr<RenderPipeline> createRaytracingPipeline(const RenderRaytracingPipelineDesc &desc, const RenderPipeline *previousPipeline) override;
std::unique_ptr<RenderCommandQueue> createCommandQueue(RenderCommandListType type) override;
std::unique_ptr<RenderBuffer> createBuffer(const RenderBufferDesc &desc) override;
std::unique_ptr<RenderTexture> createTexture(const RenderTextureDesc &desc) override;
std::unique_ptr<RenderAccelerationStructure> createAccelerationStructure(const RenderAccelerationStructureDesc &desc) override;
std::unique_ptr<RenderPool> createPool(const RenderPoolDesc &desc) override;
std::unique_ptr<RenderPipelineLayout> createPipelineLayout(const RenderPipelineLayoutDesc &desc) override;
std::unique_ptr<RenderCommandFence> createCommandFence() override;
std::unique_ptr<RenderCommandSemaphore> createCommandSemaphore() override;
std::unique_ptr<RenderFramebuffer> createFramebuffer(const RenderFramebufferDesc &desc) override;
void setBottomLevelASBuildInfo(RenderBottomLevelASBuildInfo &buildInfo, const RenderBottomLevelASMesh *meshes, uint32_t meshCount, bool preferFastBuild, bool preferFastTrace) override;
void setTopLevelASBuildInfo(RenderTopLevelASBuildInfo &buildInfo, const RenderTopLevelASInstance *instances, uint32_t instanceCount, bool preferFastBuild, bool preferFastTrace) override;
void setShaderBindingTableInfo(RenderShaderBindingTableInfo &tableInfo, const RenderShaderBindingGroups &groups, const RenderPipeline *pipeline, RenderDescriptorSet **descriptorSets, uint32_t descriptorSetCount) override;
const RenderDeviceCapabilities &getCapabilities() const override;
const RenderDeviceDescription &getDescription() const override;
RenderSampleCounts getSampleCountsSupported(RenderFormat format) const override;
void release();
bool isValid() const;
};
struct D3D12Interface : RenderInterface {
IDXGIFactory4 *dxgiFactory = nullptr;
RenderInterfaceCapabilities capabilities;
D3D12Interface();
~D3D12Interface() override;
std::unique_ptr<RenderDevice> createDevice() override;
const RenderInterfaceCapabilities &getCapabilities() const override;
bool isValid() const;
};
};

View file

@ -0,0 +1,241 @@
//
// RT64
//
#pragma once
#include <climits>
#include "rt64_render_interface_types.h"
namespace RT64 {
// Interfaces.
struct RenderBufferFormattedView {
virtual ~RenderBufferFormattedView() { }
};
struct RenderBuffer {
virtual ~RenderBuffer() { }
virtual void *map(uint32_t subresource = 0, const RenderRange *readRange = nullptr) = 0;
virtual void unmap(uint32_t subresource = 0, const RenderRange *writtenRange = nullptr) = 0;
virtual std::unique_ptr<RenderBufferFormattedView> createBufferFormattedView(RenderFormat format) = 0;
virtual void setName(const std::string &name) = 0;
// Concrete implementation shortcuts.
inline RenderBufferReference at(uint64_t offset) const {
return RenderBufferReference(this, offset);
}
};
struct RenderTextureView {
virtual ~RenderTextureView() { }
};
struct RenderTexture {
virtual ~RenderTexture() { }
virtual std::unique_ptr<RenderTextureView> createTextureView(const RenderTextureViewDesc &desc) = 0;
virtual void setName(const std::string &name) = 0;
};
struct RenderAccelerationStructure {
virtual ~RenderAccelerationStructure() { }
};
struct RenderShader {
virtual ~RenderShader() { }
};
struct RenderSampler {
virtual ~RenderSampler() { }
};
struct RenderPipeline {
virtual ~RenderPipeline() { }
virtual RenderPipelineProgram getProgram(const std::string &name) const = 0;
};
struct RenderPipelineLayout {
virtual ~RenderPipelineLayout() { }
};
struct RenderCommandFence {
virtual ~RenderCommandFence() { }
};
struct RenderCommandSemaphore {
virtual ~RenderCommandSemaphore() { }
};
struct RenderDescriptorSet {
// Descriptor indices correspond to the index assuming the descriptor set is one contiguous array. They DO NOT correspond to the bindings, which can be sparse.
// User code should derive these indices on its own by looking at the order the bindings were assigned during set creation along with the descriptor count and
// assume it was all allocated in one contiguous array. This allows efficient mapping between Vulkan and D3D12's descriptor models.
virtual ~RenderDescriptorSet() { }
virtual void setBuffer(uint32_t descriptorIndex, const RenderBuffer *buffer, uint64_t bufferSize = 0, const RenderBufferStructuredView *bufferStructuredView = nullptr, const RenderBufferFormattedView *bufferFormattedView = nullptr) = 0;
virtual void setTexture(uint32_t descriptorIndex, const RenderTexture *texture, RenderTextureLayout textureLayout, const RenderTextureView *textureView = nullptr) = 0;
virtual void setSampler(uint32_t descriptorIndex, const RenderSampler *sampler) = 0;
virtual void setAccelerationStructure(uint32_t descriptorIndex, const RenderAccelerationStructure *accelerationStructure) = 0;
};
struct RenderSwapChain {
virtual ~RenderSwapChain() { }
virtual bool present(uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, uint32_t waitSemaphoreCount) = 0;
virtual bool resize() = 0;
virtual bool needsResize() const = 0;
virtual uint32_t getWidth() const = 0;
virtual uint32_t getHeight() const = 0;
virtual RenderTexture *getTexture(uint32_t textureIndex) = 0;
virtual uint32_t getTextureCount() const = 0;
virtual bool acquireTexture(RenderCommandSemaphore *signalSemaphore, uint32_t *textureIndex) = 0;
virtual RenderWindow getWindow() const = 0;
virtual bool isEmpty() const = 0;
// Only valid if displayTiming is enabled in capabilities.
virtual uint32_t getRefreshRate() const = 0;
};
struct RenderFramebuffer {
virtual ~RenderFramebuffer() { }
virtual uint32_t getWidth() const = 0;
virtual uint32_t getHeight() const = 0;
};
struct RenderCommandList {
virtual ~RenderCommandList() { }
virtual bool isOpen() = 0;
virtual void begin() = 0;
virtual void end() = 0;
virtual void barriers(RenderBarrierStages stages, const RenderBufferBarrier *bufferBarriers, uint32_t bufferBarriersCount, const RenderTextureBarrier *textureBarriers, uint32_t textureBarriersCount) = 0;
virtual void dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) = 0;
virtual void traceRays(uint32_t width, uint32_t height, uint32_t depth, RenderBufferReference shaderBindingTable, const RenderShaderBindingGroupsInfo &shaderBindingGroupsInfo) = 0;
virtual void drawInstanced(uint32_t vertexCountPerInstance, uint32_t instanceCount, uint32_t startVertexLocation, uint32_t startInstanceLocation) = 0;
virtual void drawIndexedInstanced(uint32_t indexCountPerInstance, uint32_t instanceCount, uint32_t startIndexLocation, int32_t baseVertexLocation, uint32_t startInstanceLocation) = 0;
virtual void setPipeline(const RenderPipeline *pipeline) = 0;
virtual void setComputePipelineLayout(const RenderPipelineLayout *pipelineLayout) = 0;
virtual void setComputePushConstants(uint32_t rangeIndex, const void *data) = 0;
virtual void setComputeDescriptorSet(RenderDescriptorSet *descriptorSet, uint32_t setIndex) = 0;
virtual void setGraphicsPipelineLayout(const RenderPipelineLayout *pipelineLayout) = 0;
virtual void setGraphicsPushConstants(uint32_t rangeIndex, const void *data) = 0;
virtual void setGraphicsDescriptorSet(RenderDescriptorSet *descriptorSet, uint32_t setIndex) = 0;
virtual void setGraphicsRootDescriptor(RenderBufferReference bufferReference, uint32_t rootDescriptorIndex) = 0;
virtual void setRaytracingPipelineLayout(const RenderPipelineLayout *pipelineLayout) = 0;
virtual void setRaytracingPushConstants(uint32_t rangeIndex, const void *data) = 0;
virtual void setRaytracingDescriptorSet(RenderDescriptorSet *descriptorSet, uint32_t setIndex) = 0;
virtual void setIndexBuffer(const RenderIndexBufferView *view) = 0;
virtual void setVertexBuffers(uint32_t startSlot, const RenderVertexBufferView *views, uint32_t viewCount, const RenderInputSlot *inputSlots) = 0;
virtual void setViewports(const RenderViewport *viewports, uint32_t count) = 0;
virtual void setScissors(const RenderRect *scissorRects, uint32_t count) = 0;
virtual void setFramebuffer(const RenderFramebuffer *framebuffer) = 0;
virtual void clearColor(uint32_t attachmentIndex = 0, RenderColor colorValue = RenderColor(), const RenderRect *clearRects = nullptr, uint32_t clearRectsCount = 0) = 0;
virtual void clearDepth(bool clearDepth = true, float depthValue = 1.0f, const RenderRect *clearRects = nullptr, uint32_t clearRectsCount = 0) = 0;
virtual void copyBufferRegion(RenderBufferReference dstBuffer, RenderBufferReference srcBuffer, uint64_t size) = 0;
virtual void copyTextureRegion(const RenderTextureCopyLocation &dstLocation, const RenderTextureCopyLocation &srcLocation, uint32_t dstX = 0, uint32_t dstY = 0, uint32_t dstZ = 0, const RenderBox *srcBox = nullptr) = 0;
virtual void copyBuffer(const RenderBuffer *dstBuffer, const RenderBuffer *srcBuffer) = 0;
virtual void copyTexture(const RenderTexture *dstTexture, const RenderTexture *srcTexture) = 0;
virtual void resolveTexture(const RenderTexture *dstTexture, const RenderTexture *srcTexture) = 0;
virtual void resolveTextureRegion(const RenderTexture *dstTexture, uint32_t dstX, uint32_t dstY, const RenderTexture *srcTexture, const RenderRect *srcRect = nullptr) = 0;
virtual void buildBottomLevelAS(const RenderAccelerationStructure *dstAccelerationStructure, RenderBufferReference scratchBuffer, const RenderBottomLevelASBuildInfo &buildInfo) = 0;
virtual void buildTopLevelAS(const RenderAccelerationStructure *dstAccelerationStructure, RenderBufferReference scratchBuffer, RenderBufferReference instancesBuffer, const RenderTopLevelASBuildInfo &buildInfo) = 0;
// Concrete implementation shortcuts.
inline void barriers(RenderBarrierStages stages, const RenderBufferBarrier &barrier) {
barriers(stages, &barrier, 1, nullptr, 0);
}
inline void barriers(RenderBarrierStages stages, const RenderTextureBarrier &barrier) {
barriers(stages, nullptr, 0, &barrier, 1);
}
inline void barriers(RenderBarrierStages stages, const RenderBufferBarrier &bufferBarrier, const RenderTextureBarrier &textureBarrier) {
barriers(stages, &bufferBarrier, 1, &textureBarrier, 1);
}
inline void barriers(RenderBarrierStages stages, const RenderBufferBarrier *bufferBarriers, uint32_t bufferBarriersCount) {
barriers(stages, bufferBarriers, bufferBarriersCount, nullptr, 0);
}
inline void barriers(RenderBarrierStages stages, const std::vector<RenderBufferBarrier> &bufferBarriers) {
barriers(stages, bufferBarriers.data(), uint32_t(bufferBarriers.size()), nullptr, 0);
}
inline void barriers(RenderBarrierStages stages, const RenderTextureBarrier *textureBarriers, uint32_t textureBarriersCount) {
barriers(stages, nullptr, 0, textureBarriers, textureBarriersCount);
}
inline void barriers(RenderBarrierStages stages, const std::vector<RenderTextureBarrier> &textureBarriers) {
barriers(stages, nullptr, 0, textureBarriers.data(), uint32_t(textureBarriers.size()));
}
inline void barriers(RenderBarrierStages stages, const std::vector<RenderBufferBarrier> &bufferBarriers, const std::vector<RenderTextureBarrier> &textureBarriers) {
barriers(stages, bufferBarriers.data(), uint32_t(bufferBarriers.size()), textureBarriers.data(), uint32_t(textureBarriers.size()));
}
inline void setViewports(const RenderViewport &viewport) {
setViewports(&viewport, 1);
}
inline void setScissors(const RenderRect &scissorRect) {
setScissors(&scissorRect, 1);
}
};
struct RenderCommandQueue {
virtual ~RenderCommandQueue() { }
virtual std::unique_ptr<RenderSwapChain> createSwapChain(RenderWindow renderWindow, uint32_t textureCount, RenderFormat format) = 0;
virtual void executeCommandLists(const RenderCommandList **commandLists, uint32_t commandListCount, RenderCommandSemaphore **waitSemaphores = nullptr, uint32_t waitSemaphoreCount = 0, RenderCommandSemaphore **signalSemaphores = nullptr, uint32_t signalSemaphoreCount = 0, RenderCommandFence *signalFence = nullptr) = 0;
virtual void waitForCommandFence(RenderCommandFence *fence) = 0;
// Concrete implementation shortcuts.
inline void executeCommandLists(const RenderCommandList *commandList, RenderCommandFence *signalFence = nullptr) {
executeCommandLists(&commandList, 1, nullptr, 0, nullptr, 0, signalFence);
}
};
struct RenderPool {
virtual ~RenderPool() { }
virtual std::unique_ptr<RenderBuffer> createBuffer(const RenderBufferDesc &desc) = 0;
virtual std::unique_ptr<RenderTexture> createTexture(const RenderTextureDesc &desc) = 0;
};
struct RenderDevice {
virtual ~RenderDevice() { }
virtual std::unique_ptr<RenderCommandList> createCommandList(RenderCommandListType type) = 0;
virtual std::unique_ptr<RenderDescriptorSet> createDescriptorSet(const RenderDescriptorSetDesc &desc) = 0;
virtual std::unique_ptr<RenderShader> createShader(const void *data, uint64_t size, const char *entryPointName, RenderShaderFormat format) = 0;
virtual std::unique_ptr<RenderSampler> createSampler(const RenderSamplerDesc &desc) = 0;
virtual std::unique_ptr<RenderPipeline> createComputePipeline(const RenderComputePipelineDesc &desc) = 0;
virtual std::unique_ptr<RenderPipeline> createGraphicsPipeline(const RenderGraphicsPipelineDesc &desc) = 0;
virtual std::unique_ptr<RenderPipeline> createRaytracingPipeline(const RenderRaytracingPipelineDesc &desc, const RenderPipeline *previousPipeline = nullptr) = 0;
virtual std::unique_ptr<RenderCommandQueue> createCommandQueue(RenderCommandListType type) = 0;
virtual std::unique_ptr<RenderBuffer> createBuffer(const RenderBufferDesc &desc) = 0;
virtual std::unique_ptr<RenderTexture> createTexture(const RenderTextureDesc &desc) = 0;
virtual std::unique_ptr<RenderAccelerationStructure> createAccelerationStructure(const RenderAccelerationStructureDesc &desc) = 0;
virtual std::unique_ptr<RenderPool> createPool(const RenderPoolDesc &desc) = 0;
virtual std::unique_ptr<RenderPipelineLayout> createPipelineLayout(const RenderPipelineLayoutDesc &desc) = 0;
virtual std::unique_ptr<RenderCommandFence> createCommandFence() = 0;
virtual std::unique_ptr<RenderCommandSemaphore> createCommandSemaphore() = 0;
virtual std::unique_ptr<RenderFramebuffer> createFramebuffer(const RenderFramebufferDesc &desc) = 0;
virtual void setBottomLevelASBuildInfo(RenderBottomLevelASBuildInfo &buildInfo, const RenderBottomLevelASMesh *meshes, uint32_t meshCount, bool preferFastBuild = true, bool preferFastTrace = false) = 0;
virtual void setTopLevelASBuildInfo(RenderTopLevelASBuildInfo &buildInfo, const RenderTopLevelASInstance *instances, uint32_t instanceCount, bool preferFastBuild = true, bool preferFastTrace = false) = 0;
virtual void setShaderBindingTableInfo(RenderShaderBindingTableInfo &tableInfo, const RenderShaderBindingGroups &groups, const RenderPipeline *pipeline, RenderDescriptorSet **descriptorSets, uint32_t descriptorSetCount) = 0;
virtual const RenderDeviceCapabilities &getCapabilities() const = 0;
virtual const RenderDeviceDescription &getDescription() const = 0;
virtual RenderSampleCounts getSampleCountsSupported(RenderFormat format) const = 0;
};
struct RenderInterface {
virtual ~RenderInterface() { }
virtual std::unique_ptr<RenderDevice> createDevice() = 0;
virtual const RenderInterfaceCapabilities &getCapabilities() const = 0;
};
extern void RenderInterfaceTest(RenderInterface *renderInterface);
extern void TestInitialize(RenderInterface* renderInterface, RenderWindow window);
extern void TestDraw();
extern void TestResize();
extern void TestShutdown();
};
#include "rt64_render_interface_builders.h"

View file

@ -0,0 +1,278 @@
//
// RT64
//
#pragma once
#include <unordered_set>
namespace RT64 {
struct RenderDescriptorSetBuilder {
std::list<std::vector<const RenderSampler *>> samplerPointerVectorList;
std::vector<RenderDescriptorRange> descriptorRanges;
RenderDescriptorSetDesc descriptorSetDesc;
bool open = false;
uint32_t setIndex = 0;
RenderDescriptorSetBuilder() = default;
void begin() {
assert(!open && "Builder must be closed.");
descriptorSetDesc = RenderDescriptorSetDesc();
samplerPointerVectorList.clear();
descriptorRanges.clear();
open = true;
setIndex = 0;
}
uint32_t addConstantBuffer(uint32_t binding, uint32_t count = 1) {
return addRange(RenderDescriptorRange(RenderDescriptorRangeType::CONSTANT_BUFFER, binding, count, nullptr));
}
uint32_t addFormattedBuffer(uint32_t binding, uint32_t count = 1) {
return addRange(RenderDescriptorRange(RenderDescriptorRangeType::FORMATTED_BUFFER, binding, count, nullptr));
}
uint32_t addReadWriteFormattedBuffer(uint32_t binding, uint32_t count = 1) {
return addRange(RenderDescriptorRange(RenderDescriptorRangeType::READ_WRITE_FORMATTED_BUFFER, binding, count, nullptr));
}
uint32_t addTexture(uint32_t binding, uint32_t count = 1) {
return addRange(RenderDescriptorRange(RenderDescriptorRangeType::TEXTURE, binding, count, nullptr));
}
uint32_t addReadWriteTexture(uint32_t binding, uint32_t count = 1) {
return addRange(RenderDescriptorRange(RenderDescriptorRangeType::READ_WRITE_TEXTURE, binding, count, nullptr));
}
uint32_t addSampler(uint32_t binding, uint32_t count = 1) {
return addRange(RenderDescriptorRange(RenderDescriptorRangeType::SAMPLER, binding, count, nullptr));
}
uint32_t addImmutableSampler(uint32_t binding, const RenderSampler *immutableSampler) {
assert(immutableSampler != nullptr);
return addImmutableSampler(binding, &immutableSampler);
}
uint32_t addImmutableSampler(uint32_t binding, const RenderSampler **immutableSampler, uint32_t count = 1) {
assert(immutableSampler != nullptr);
samplerPointerVectorList.emplace_back(std::vector<const RenderSampler *>(immutableSampler, immutableSampler + count));
return addRange(RenderDescriptorRange(RenderDescriptorRangeType::SAMPLER, binding, count, samplerPointerVectorList.back().data()));
}
uint32_t addStructuredBuffer(uint32_t binding, uint32_t count = 1) {
return addRange(RenderDescriptorRange(RenderDescriptorRangeType::STRUCTURED_BUFFER, binding, count, nullptr));
}
uint32_t addReadWriteStructuredBuffer(uint32_t binding, uint32_t count = 1) {
return addRange(RenderDescriptorRange(RenderDescriptorRangeType::READ_WRITE_STRUCTURED_BUFFER, binding, count, nullptr));
}
uint32_t addByteAddressBuffer(uint32_t binding, uint32_t count = 1) {
return addRange(RenderDescriptorRange(RenderDescriptorRangeType::BYTE_ADDRESS_BUFFER, binding, count, nullptr));
}
uint32_t addReadWriteByteAddressBuffer(uint32_t binding, uint32_t count = 1) {
return addRange(RenderDescriptorRange(RenderDescriptorRangeType::READ_WRITE_BYTE_ADDRESS_BUFFER, binding, count, nullptr));
}
uint32_t addAccelerationStructure(uint32_t binding, uint32_t count = 1) {
return addRange(RenderDescriptorRange(RenderDescriptorRangeType::ACCELERATION_STRUCTURE, binding, count, nullptr));
}
uint32_t addRange(const RenderDescriptorRange &range) {
assert(open && "Builder must be open.");
uint32_t returnValue = setIndex;
descriptorRanges.emplace_back(range);
descriptorSetDesc.descriptorRangesCount++;
setIndex += range.count;
return returnValue;
}
void end(bool lastRangeIsBoundless = false, uint32_t boundlessRangeSize = 0) {
assert(open && "Builder must be open.");
descriptorSetDesc.lastRangeIsBoundless = lastRangeIsBoundless;
descriptorSetDesc.boundlessRangeSize = boundlessRangeSize;
descriptorSetDesc.descriptorRanges = descriptorRanges.data();
open = false;
}
std::unique_ptr<RenderDescriptorSet> create(RenderDevice *device) const {
assert(!open && "Builder must be closed.");
return device->createDescriptorSet(descriptorSetDesc);
}
};
struct RenderDescriptorSetBase {
RenderDescriptorSetBuilder builder;
std::unique_ptr<RenderDescriptorSet> descriptorSet;
void create(RenderDevice *device) {
descriptorSet = builder.create(device);
}
RenderDescriptorSet *get() const {
return descriptorSet.get();
}
void setBuffer(uint32_t descriptorIndex, const RenderBuffer *buffer, uint64_t bufferSize = 0, const RenderBufferStructuredView *bufferStructuredView = nullptr, const RenderBufferFormattedView *bufferFormattedView = nullptr) {
descriptorSet->setBuffer(descriptorIndex, buffer, bufferSize, bufferStructuredView, bufferFormattedView);
}
void setBuffer(uint32_t descriptorIndex, const RenderBuffer *buffer, uint64_t bufferSize, const RenderBufferStructuredView &bufferStructuredView) {
descriptorSet->setBuffer(descriptorIndex, buffer, bufferSize, &bufferStructuredView);
}
void setBuffer(uint32_t descriptorIndex, const RenderBuffer *buffer, uint64_t bufferSize, const RenderBufferFormattedView *bufferFormattedView) {
descriptorSet->setBuffer(descriptorIndex, buffer, bufferSize, nullptr, bufferFormattedView);
}
void setBuffer(uint32_t descriptorIndex, const RenderBuffer *buffer, const RenderBufferStructuredView &bufferStructuredView) {
descriptorSet->setBuffer(descriptorIndex, buffer, 0, &bufferStructuredView);
}
void setBuffer(uint32_t descriptorIndex, const RenderBuffer *buffer, const RenderBufferFormattedView *bufferFormattedView) {
descriptorSet->setBuffer(descriptorIndex, buffer, 0, nullptr, bufferFormattedView);
}
void setTexture(uint32_t descriptorIndex, const RenderTexture *texture, const RenderTextureLayout textureLayout, const RenderTextureView *textureView = nullptr) {
descriptorSet->setTexture(descriptorIndex, texture, textureLayout, textureView);
}
void setSampler(uint32_t descriptorIndex, const RenderSampler *sampler) {
descriptorSet->setSampler(descriptorIndex, sampler);
}
void setAccelerationStructure(uint32_t descriptorIndex, const RenderAccelerationStructure *accelerationStructure) {
descriptorSet->setAccelerationStructure(descriptorIndex, accelerationStructure);
}
};
struct RenderDescriptorSetInclusionFilter {
const uint32_t *bindings = nullptr;
uint32_t bindingsCount = 0;
};
struct RenderPipelineLayoutBuilder {
std::vector<RenderPushConstantRange> pushConstantRanges;
std::list<std::vector<const RenderSampler *>> samplerPointerVectorList;
std::vector<RenderDescriptorRange> descriptorRanges;
std::vector<RenderDescriptorSetDesc> descriptorSetDescs;
std::vector<uint32_t> descriptorRangeIndexPerSet;
std::vector<RenderRootDescriptorDesc> rootDescriptorDescs;
RenderPipelineLayoutDesc layoutDesc;
bool open = false;
// Start filling the description.
void begin(bool isLocal = false, bool allowInputLayout = false) {
assert(!open && "Builder must be closed.");
layoutDesc = RenderPipelineLayoutDesc();
layoutDesc.isLocal = isLocal;
layoutDesc.allowInputLayout = allowInputLayout;
pushConstantRanges.clear();
samplerPointerVectorList.clear();
descriptorRanges.clear();
descriptorSetDescs.clear();
descriptorRangeIndexPerSet.clear();
rootDescriptorDescs.clear();
open = true;
}
// Returns push constant index.
uint32_t addPushConstant(uint32_t binding, uint32_t set, uint32_t size, RenderShaderStageFlags stageFlags, uint32_t offset = 0) {
assert(open && "Builder must be open.");
uint32_t returnValue = layoutDesc.pushConstantRangesCount;
pushConstantRanges.emplace_back(RenderPushConstantRange(binding, set, offset, size, stageFlags));
layoutDesc.pushConstantRangesCount++;
return returnValue;
}
// Returns set index.
uint32_t addDescriptorSet(const RenderDescriptorSetDesc &descriptorSetDesc) {
assert(open && "Builder must be open.");
uint32_t returnValue = layoutDesc.descriptorSetDescsCount;
descriptorRangeIndexPerSet.emplace_back(uint32_t(descriptorRanges.size()));
descriptorSetDescs.emplace_back(descriptorSetDesc);
for (uint32_t j = 0; j < descriptorSetDesc.descriptorRangesCount; j++) {
descriptorRanges.emplace_back(descriptorSetDesc.descriptorRanges[j]);
// Copy the immutable sampler pointers to a local vector list.
if (descriptorRanges.back().immutableSampler != nullptr) {
const RenderSampler **immutableSampler = descriptorRanges.back().immutableSampler;
samplerPointerVectorList.emplace_back(std::vector<const RenderSampler *>(immutableSampler, immutableSampler + descriptorRanges.back().count));
descriptorRanges.back().immutableSampler = samplerPointerVectorList.back().data();
}
}
layoutDesc.descriptorSetDescsCount++;
return returnValue;
}
// Returns set index.
uint32_t addDescriptorSet(const RenderDescriptorSetBuilder &descriptorSetBuilder) {
return addDescriptorSet(descriptorSetBuilder.descriptorSetDesc);
}
// Returns set index.
uint32_t addDescriptorSet(const RenderDescriptorSetBase &descriptorSetBase) {
return addDescriptorSet(descriptorSetBase.builder);
}
// Returns root descriptor index. D3D12 only.
uint32_t addRootDescriptor(uint32_t shaderRegister, uint32_t registerSpace, RenderRootDescriptorType type) {
assert(open && "Builder must be open.");
uint32_t returnValue = layoutDesc.rootDescriptorDescsCount;
rootDescriptorDescs.emplace_back(shaderRegister, registerSpace, type);
++layoutDesc.rootDescriptorDescsCount;
return returnValue;
}
// Finish the description.
void end() {
assert(open && "Builder must be open.");
if (layoutDesc.pushConstantRangesCount > 0) {
layoutDesc.pushConstantRanges = pushConstantRanges.data();
}
if (layoutDesc.descriptorSetDescsCount > 0) {
for (uint32_t i = 0; i < layoutDesc.descriptorSetDescsCount; i++) {
const uint32_t rangeIndex = descriptorRangeIndexPerSet[i];
descriptorSetDescs[i].descriptorRanges = &descriptorRanges[rangeIndex];
}
layoutDesc.descriptorSetDescs = descriptorSetDescs.data();
}
if (layoutDesc.rootDescriptorDescsCount > 0) {
layoutDesc.rootDescriptorDescs = rootDescriptorDescs.data();
}
open = false;
}
// Create a pipeline layout with the final description.
std::unique_ptr<RenderPipelineLayout> create(RenderDevice *device) const {
assert(!open && "Builder must be closed.");
return device->createPipelineLayout(layoutDesc);
}
};
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,338 @@
#pragma once
void VdInitializeSystem();
SWA_API void* VdGetGlobalDevice();
#include "rhi/rt64_render_interface.h"
#define D3DCLEAR_TARGET 0x1
#define D3DCLEAR_ZBUFFER 0x10
using namespace RT64;
struct GuestSamplerState
{
be<uint32_t> data[6];
};
struct GuestDevice
{
be<uint64_t> dirtyFlags[8];
be<uint32_t> setRenderStateFunctions[0x65];
uint32_t setSamplerStateFunctions[0x14];
uint8_t padding224[0x25C];
GuestSamplerState samplerStates[0x20];
uint32_t vertexShaderFloatConstants[0x400];
uint32_t pixelShaderFloatConstants[0x400];
be<uint32_t> vertexShaderBoolConstants[0x4];
be<uint32_t> pixelShaderBoolConstants[0x4];
uint8_t padding27A0[0x68C];
struct GuestVertexDeclaration* vertexDeclaration;
uint8_t padding2E30[0x2FD0];
};
enum class ResourceType
{
Texture,
VolumeTexture,
VertexBuffer,
IndexBuffer,
RenderTarget,
DepthStencil,
VertexDeclaration,
VertexShader,
PixelShader
};
struct GuestResource
{
uint32_t unused = 0;
be<uint32_t> refCount = 1;
ResourceType type;
GuestResource(ResourceType type) : type(type)
{
}
void AddRef()
{
uint32_t originalValue, incrementedValue;
do
{
originalValue = refCount.value;
incrementedValue = std::byteswap(std::byteswap(originalValue) + 1);
} while (InterlockedCompareExchange(reinterpret_cast<LONG*>(&refCount), incrementedValue, originalValue) != originalValue);
}
};
enum GuestFormat
{
D3DFMT_A16B16G16R16F = 0x1A22AB60,
D3DFMT_A16B16G16R16F_2 = 0x1A2201BF,
D3DFMT_A8B8G8R8 = 0x1A200186,
D3DFMT_A8R8G8B8 = 0x18280186,
D3DFMT_D24FS8 = 0x1A220197,
D3DFMT_D24S8 = 0x2D200196,
D3DFMT_G16R16F = 0x2D22AB9F,
D3DFMT_G16R16F_2 = 0x2D20AB8D,
D3DFMT_INDEX16 = 1,
D3DFMT_INDEX32 = 6,
D3DFMT_L8 = 0x28000102,
D3DFMT_L8_2 = 0x28000002,
D3DFMT_X8R8G8B8 = 0x28280086,
D3DFMT_UNKNOWN = 0xFFFFFFFF
};
// Texture/VolumeTexture
struct GuestTexture : GuestResource
{
std::unique_ptr<RenderTexture> texture;
std::unique_ptr<RenderTextureView> textureView;
uint32_t width = 0;
uint32_t height = 0;
uint32_t depth = 0;
RenderFormat format = RenderFormat::UNKNOWN;
void* mappedMemory = nullptr;
uint32_t descriptorIndex = 0;
};
struct GuestLockedRect
{
be<uint32_t> pitch;
be<uint32_t> bits;
};
struct GuestBufferDesc
{
be<uint32_t> format;
be<uint32_t> type;
be<uint32_t> usage;
be<uint32_t> pool;
be<uint32_t> size;
be<uint32_t> fvf;
};
// VertexBuffer/IndexBuffer
struct GuestBuffer : GuestResource
{
std::unique_ptr<RenderBuffer> buffer;
void* mappedMemory = nullptr;
uint32_t dataSize = 0;
RenderFormat format = RenderFormat::UNKNOWN;
uint32_t guestFormat = 0;
bool lockedReadOnly = false;
};
struct GuestSurfaceDesc
{
be<uint32_t> format;
be<uint32_t> type;
be<uint32_t> usage;
be<uint32_t> pool;
be<uint32_t> multiSampleType;
be<uint32_t> multiSampleQuality;
be<uint32_t> width;
be<uint32_t> height;
};
// RenderTarget/DepthStencil
struct GuestSurface : GuestResource
{
std::unique_ptr<RenderTexture> textureHolder;
RenderTexture* texture = nullptr;
uint32_t width = 0;
uint32_t height = 0;
RenderFormat format = RenderFormat::UNKNOWN;
ankerl::unordered_dense::map<const RenderTexture*, std::unique_ptr<RenderFramebuffer>> framebuffers;
};
enum GuestDeclType
{
D3DDECLTYPE_FLOAT1 = 0x2C83A4,
D3DDECLTYPE_FLOAT2 = 0x2C23A5,
D3DDECLTYPE_FLOAT3 = 0x2A23B9,
D3DDECLTYPE_FLOAT4 = 0x1A23A6,
D3DDECLTYPE_D3DCOLOR = 0x182886,
D3DDECLTYPE_UBYTE4 = 0x1A2286,
D3DDECLTYPE_UBYTE4_2 = 0x1A2386,
D3DDECLTYPE_SHORT2 = 0x2C2359,
D3DDECLTYPE_SHORT4 = 0x1A235A,
D3DDECLTYPE_UBYTE4N = 0x1A2086,
D3DDECLTYPE_UBYTE4N_2 = 0x1A2186,
D3DDECLTYPE_SHORT2N = 0x2C2159,
D3DDECLTYPE_SHORT4N = 0x1A215A,
D3DDECLTYPE_USHORT2N = 0x2C2059,
D3DDECLTYPE_USHORT4N = 0x1A205A,
D3DDECLTYPE_UINT1 = 0x2C82A1,
D3DDECLTYPE_UDEC3 = 0x2A2287,
D3DDECLTYPE_DEC3N = 0x2A2187,
D3DDECLTYPE_DEC3N_2 = 0x2A2190,
D3DDECLTYPE_DEC3N_3 = 0x2A2390,
D3DDECLTYPE_FLOAT16_2 = 0x2C235F,
D3DDECLTYPE_FLOAT16_4 = 0x1A2360,
D3DDECLTYPE_UNUSED = 0xFFFFFFFF
};
enum GuestDeclUsage
{
D3DDECLUSAGE_POSITION = 0,
D3DDECLUSAGE_BLENDWEIGHT = 1,
D3DDECLUSAGE_BLENDINDICES = 2,
D3DDECLUSAGE_NORMAL = 3,
D3DDECLUSAGE_PSIZE = 4,
D3DDECLUSAGE_TEXCOORD = 5,
D3DDECLUSAGE_TANGENT = 6,
D3DDECLUSAGE_BINORMAL = 7,
D3DDECLUSAGE_TESSFACTOR = 8,
D3DDECLUSAGE_POSITIONT = 9,
D3DDECLUSAGE_COLOR = 10,
D3DDECLUSAGE_FOG = 11,
D3DDECLUSAGE_DEPTH = 12,
D3DDECLUSAGE_SAMPLE = 13
};
struct GuestVertexElement
{
be<uint16_t> stream;
be<uint16_t> offset;
be<uint32_t> type;
uint8_t method;
uint8_t usage;
uint8_t usageIndex;
uint8_t padding;
};
enum InputLayoutFlags
{
INPUT_LAYOUT_FLAG_HAS_R11G11B10_NORMAL = 1 << 0,
INPUT_LAYOUT_FLAG_HAS_BONE_WEIGHTS = 1 << 1
};
struct GuestVertexDeclaration : GuestResource
{
std::unique_ptr<RenderInputElement[]> inputElements;
std::unique_ptr<GuestVertexElement[]> vertexElements;
uint32_t inputElementCount = 0;
uint32_t vertexElementCount = 0;
uint32_t swappedTexcoords = 0;
uint32_t inputLayoutFlags = 0;
uint32_t indexVertexStream = 0;
};
// VertexShader/PixelShader
struct GuestShader : GuestResource
{
std::unique_ptr<RenderShader> shader;
};
struct GuestViewport
{
be<uint32_t> x;
be<uint32_t> y;
be<uint32_t> width;
be<uint32_t> height;
be<float> minZ;
be<float> maxZ;
};
struct GuestRect
{
be<int32_t> left;
be<int32_t> top;
be<int32_t> right;
be<int32_t> bottom;
};
enum GuestRenderState
{
D3DRS_ZENABLE = 40,
D3DRS_ZFUNC = 44,
D3DRS_ZWRITEENABLE = 48,
D3DRS_CULLMODE = 56,
D3DRS_ALPHABLENDENABLE = 60,
D3DRS_SRCBLEND = 72,
D3DRS_DESTBLEND = 76,
D3DRS_BLENDOP = 80,
D3DRS_SRCBLENDALPHA = 84,
D3DRS_DESTBLENDALPHA = 88,
D3DRS_BLENDOPALPHA = 92,
D3DRS_ALPHATESTENABLE = 96,
D3DRS_ALPHAREF = 100,
D3DRS_SCISSORTESTENABLE = 200,
D3DRS_SLOPESCALEDEPTHBIAS = 204,
D3DRS_DEPTHBIAS = 208,
D3DRS_COLORWRITEENABLE = 212
};
enum GuestCullMode
{
D3DCULL_NONE = 0,
D3DCULL_CW = 2,
D3DCULL_NONE_2 = 4,
D3DCULL_CCW = 6
};
enum GuestBlendMode
{
D3DBLEND_ZERO = 0,
D3DBLEND_ONE = 1,
D3DBLEND_SRCCOLOR = 4,
D3DBLEND_INVSRCCOLOR = 5,
D3DBLEND_SRCALPHA = 6,
D3DBLEND_INVSRCALPHA = 7,
D3DBLEND_DESTCOLOR = 8,
D3DBLEND_INVDESTCOLOR = 9,
D3DBLEND_DESTALPHA = 10,
D3DBLEND_INVDESTALPHA = 11
};
enum GuestBlendOp
{
D3DBLENDOP_ADD = 0,
D3DBLENDOP_SUBTRACT = 1,
D3DBLENDOP_MIN = 2,
D3DBLENDOP_MAX = 3,
D3DBLENDOP_REVSUBTRACT = 4
};
enum GuestCmpFunc
{
D3DCMP_NEVER = 0,
D3DCMP_LESS = 1,
D3DCMP_EQUAL = 2,
D3DCMP_LESSEQUAL = 3,
D3DCMP_GREATER = 4,
D3DCMP_NOTEQUAL = 5,
D3DCMP_GREATEREQUAL = 6,
D3DCMP_ALWAYS = 7
};
enum GuestPrimitiveType
{
D3DPT_POINTLIST = 1,
D3DPT_LINELIST = 2,
D3DPT_LINESTRIP = 3,
D3DPT_TRIANGLELIST = 4,
D3DPT_TRIANGLEFAN = 5,
D3DPT_TRIANGLESTRIP = 6,
D3DPT_QUADLIST = 13
};
enum GuestTextureFilterType
{
D3DTEXF_POINT = 0,
D3DTEXF_LINEAR = 1,
D3DTEXF_NONE = 2
};
enum GuestTextureAddress
{
D3DTADDRESS_WRAP = 0,
D3DTADDRESS_MIRROR = 1,
D3DTADDRESS_CLAMP = 2,
D3DTADDRESS_MIRRORONCE = 3,
D3DTADDRESS_BORDER = 6
};

View file

@ -55,6 +55,27 @@ void KiSystemStartup()
// OS mounts game data to D:
XamContentCreateEx(0, "D", &gameContent, OPEN_EXISTING, nullptr, nullptr, 0, 0, nullptr);
WIN32_FIND_DATAA fdata;
const auto findHandle = FindFirstFileA(".\\dlc\\*.*", &fdata);
if (findHandle != INVALID_HANDLE_VALUE)
{
char strBuf[256];
do
{
if (strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0)
{
continue;
}
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
snprintf(strBuf, sizeof(strBuf), ".\\dlc\\%s", fdata.cFileName);
XamRegisterContent(XamMakeContent(XCONTENTTYPE_DLC, fdata.cFileName), strBuf);
}
} while (FindNextFileA(findHandle, &fdata));
FindClose(findHandle);
}
XAudioInitializeSystem();
hid::Init();
}
@ -107,8 +128,6 @@ int main()
uint32_t entry = LdrLoadModule(FileSystem::TransformPath(GAME_XEX_PATH));
VdInitializeSystem();
GuestThread::Start(entry);
return 0;

View file

@ -1,19 +1,6 @@
#include "stdafx.h"
#include <kernel/function.h>
// TODO: Multiplatform support
void CriErrNotify1(const char* message)
{
OutputDebugStringA(message);
OutputDebugStringA("\n");
}
void CriErrNotify2(uint32_t category, const char* message)
{
OutputDebugStringA(message);
OutputDebugStringA("\n");
}
BOOL QueryPerformanceCounterImpl(LARGE_INTEGER* lpPerformanceCount)
{
BOOL result = QueryPerformanceCounter(lpPerformanceCount);
@ -53,13 +40,21 @@ GUEST_FUNCTION_HOOK(sub_831CCAA0, memset);
GUEST_FUNCTION_HOOK(sub_82BD4CA8, OutputDebugStringA);
#ifdef _DEBUG
GUEST_FUNCTION_HOOK(sub_8312EB48, CriErrNotify1);
GUEST_FUNCTION_HOOK(sub_83185B00, CriErrNotify1);
GUEST_FUNCTION_HOOK(sub_831683E0, CriErrNotify2);
#endif
GUEST_FUNCTION_HOOK(sub_82BD4AC8, QueryPerformanceCounterImpl);
GUEST_FUNCTION_HOOK(sub_831CD040, QueryPerformanceFrequencyImpl);
GUEST_FUNCTION_HOOK(sub_82BD4BC0, GlobalMemoryStatusImpl);
// Movie player stubs
GUEST_FUNCTION_STUB(sub_82AE3638);
GUEST_FUNCTION_STUB(sub_82AE2BF8);
// Logo skip
PPC_FUNC(sub_82547DF0)
{
ctx.r4.u64 = 0;
ctx.r5.u64 = 0;
ctx.r6.u64 = 1;
ctx.r7.u64 = 0;
sub_825517C8(ctx, base);
}

View file

@ -77,4 +77,19 @@ invalid_instructions = [
{ data = 0x8324B3BC, size = 8 }, # C Specific Frame Handler
{ data = 0x831C8B50, size = 8 },
{ data = 0x00485645, size = 44 } # End of .text
]
]
[[midasm_hook]]
name = "HalfPixelOffsetMidAsmHook"
address = 0x82E9FD64
registers = ["f9", "f0"]
[[midasm_hook]]
name = "IndexBufferLengthMidAsmHook"
address = 0x82E26244
registers = ["r3"]
[[midasm_hook]]
name = "SetShadowResolutionMidAsmHook"
address = 0x82BAD87C
registers = ["r11"]

View file

@ -9,6 +9,7 @@
#include <xbox.h>
#include <xxhash.h>
#include <ankerl/unordered_dense.h>
#include <ddspp.h>
#include "framework.h"
#include "Mutex.h"

1
thirdparty/D3D12MemoryAllocator vendored Submodule

@ -0,0 +1 @@
Subproject commit e00c4a7c85cf9c28c6f4a6cc75032736f416410f

@ -1 +1 @@
Subproject commit 1f5d7c32e8205ef10dab458394ebc760fb5a0bdc
Subproject commit 516e23f1f7781265a99ee90264c2b1f8f58378b3

1
thirdparty/ddspp vendored Submodule

@ -0,0 +1 @@
Subproject commit 1390499ec9f7b82e7a9cbdeb2e6191808e981f84