mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-04-28 13:27:58 +03:00
Implement Vulkan.
This commit is contained in:
parent
51df78e5c9
commit
c07b827a5e
12 changed files with 4716 additions and 50 deletions
9
.gitmodules
vendored
9
.gitmodules
vendored
|
@ -14,3 +14,12 @@
|
|||
[submodule "thirdparty/ddspp"]
|
||||
path = thirdparty/ddspp
|
||||
url = https://github.com/redorav/ddspp.git
|
||||
[submodule "thirdparty/Vulkan-Headers"]
|
||||
path = thirdparty/Vulkan-Headers
|
||||
url = https://github.com/KhronosGroup/Vulkan-Headers
|
||||
[submodule "thirdparty/VulkanMemoryAllocator"]
|
||||
path = thirdparty/VulkanMemoryAllocator
|
||||
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
|
||||
[submodule "thirdparty/volk"]
|
||||
path = thirdparty/volk
|
||||
url = https://github.com/zeux/volk.git
|
||||
|
|
|
@ -43,6 +43,7 @@ set(SWA_GPU_CXX_SOURCES
|
|||
"gpu/window.cpp"
|
||||
"gpu/video.cpp"
|
||||
"gpu/rhi/rt64_d3d12.cpp"
|
||||
"gpu/rhi/rt64_vulkan.cpp"
|
||||
)
|
||||
|
||||
set(SWA_APU_CXX_SOURCES
|
||||
|
@ -85,7 +86,12 @@ target_include_directories(UnleashedRecomp PRIVATE
|
|||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SWA_THIRDPARTY_ROOT}/ddspp
|
||||
${SWA_THIRDPARTY_ROOT}/D3D12MemoryAllocator/include
|
||||
${SWA_THIRDPARTY_ROOT}/D3D12MemoryAllocator/src)
|
||||
${SWA_THIRDPARTY_ROOT}/D3D12MemoryAllocator/src
|
||||
${SWA_THIRDPARTY_ROOT}/volk
|
||||
${SWA_THIRDPARTY_ROOT}/Vulkan-Headers/include
|
||||
${SWA_THIRDPARTY_ROOT}/VulkanMemoryAllocator/include
|
||||
${SWA_THIRDPARTY_ROOT}/VulkanMemoryAllocator/src
|
||||
)
|
||||
|
||||
target_precompile_headers(UnleashedRecomp PUBLIC ${SWA_PRECOMPILED_HEADERS})
|
||||
|
||||
|
|
|
@ -1441,10 +1441,6 @@ namespace RT64 {
|
|||
}
|
||||
}
|
||||
|
||||
bool D3D12CommandList::isOpen() {
|
||||
return open;
|
||||
}
|
||||
|
||||
void D3D12CommandList::begin() {
|
||||
assert(!open);
|
||||
|
||||
|
@ -1622,13 +1618,18 @@ namespace RT64 {
|
|||
activeComputePipelineLayout = interfacePipelineLayout;
|
||||
}
|
||||
|
||||
void D3D12CommandList::setComputePushConstants(uint32_t rangeIndex, const void *data) {
|
||||
void D3D12CommandList::setComputePushConstants(uint32_t rangeIndex, const void *data, uint32_t offset, uint32_t size) {
|
||||
assert(activeComputePipelineLayout != nullptr);
|
||||
assert(rangeIndex < activeComputePipelineLayout->pushConstantRanges.size());
|
||||
|
||||
const RenderPushConstantRange &range = activeComputePipelineLayout->pushConstantRanges[rangeIndex];
|
||||
assert((range.offset == 0) && "Offset behavior should be verified when compared to Vulkan.");
|
||||
d3d->SetComputeRoot32BitConstants(rangeIndex, (range.size + sizeof(uint32_t) - 1) / sizeof(uint32_t), data, 0);
|
||||
|
||||
if (size == 0) {
|
||||
size = range.size;
|
||||
}
|
||||
|
||||
d3d->SetComputeRoot32BitConstants(rangeIndex, (size + sizeof(uint32_t) - 1) / sizeof(uint32_t), data, (offset + sizeof(uint32_t) - 1) / sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void D3D12CommandList::setComputeDescriptorSet(RenderDescriptorSet *descriptorSet, uint32_t setIndex) {
|
||||
|
@ -1643,13 +1644,18 @@ namespace RT64 {
|
|||
activeGraphicsPipelineLayout = interfacePipelineLayout;
|
||||
}
|
||||
|
||||
void D3D12CommandList::setGraphicsPushConstants(uint32_t rangeIndex, const void *data) {
|
||||
void D3D12CommandList::setGraphicsPushConstants(uint32_t rangeIndex, const void *data, uint32_t offset, uint32_t size) {
|
||||
assert(activeGraphicsPipelineLayout != nullptr);
|
||||
assert(rangeIndex < activeGraphicsPipelineLayout->pushConstantRanges.size());
|
||||
|
||||
const RenderPushConstantRange &range = activeGraphicsPipelineLayout->pushConstantRanges[rangeIndex];
|
||||
assert((range.offset == 0) && "Offset behavior should be verified when compared to Vulkan.");
|
||||
d3d->SetGraphicsRoot32BitConstants(rangeIndex, (range.size + sizeof(uint32_t) - 1) / sizeof(uint32_t), data, 0);
|
||||
|
||||
if (size == 0) {
|
||||
size = range.size;
|
||||
}
|
||||
|
||||
d3d->SetGraphicsRoot32BitConstants(rangeIndex, (size + sizeof(uint32_t) - 1) / sizeof(uint32_t), data, (offset + sizeof(uint32_t) - 1) / sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void D3D12CommandList::setGraphicsDescriptorSet(RenderDescriptorSet *descriptorSet, uint32_t setIndex) {
|
||||
|
@ -1664,8 +1670,8 @@ namespace RT64 {
|
|||
setComputePipelineLayout(pipelineLayout);
|
||||
}
|
||||
|
||||
void D3D12CommandList::setRaytracingPushConstants(uint32_t rangeIndex, const void *data) {
|
||||
setComputePushConstants(rangeIndex, data);
|
||||
void D3D12CommandList::setRaytracingPushConstants(uint32_t rangeIndex, const void *data, uint32_t offset, uint32_t size) {
|
||||
setComputePushConstants(rangeIndex, data, offset, size);
|
||||
}
|
||||
|
||||
void D3D12CommandList::setRaytracingDescriptorSet(RenderDescriptorSet *descriptorSet, uint32_t setIndex) {
|
||||
|
@ -2302,6 +2308,10 @@ namespace RT64 {
|
|||
setObjectName(d3d, name);
|
||||
}
|
||||
|
||||
uint64_t D3D12Buffer::getDeviceAddress() const {
|
||||
return d3d->GetGPUVirtualAddress();
|
||||
}
|
||||
|
||||
// D3D12BufferFormattedView
|
||||
|
||||
D3D12BufferFormattedView::D3D12BufferFormattedView(D3D12Buffer *buffer, RenderFormat format) {
|
||||
|
@ -2675,7 +2685,9 @@ namespace RT64 {
|
|||
psoDesc.PS.BytecodeLength = (pixelShader != nullptr) ? pixelShader->d3d.size() : 0;
|
||||
psoDesc.SampleMask = UINT_MAX;
|
||||
psoDesc.SampleDesc.Count = desc.multisampling.sampleCount;
|
||||
psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF;
|
||||
if (desc.primitiveTopology == RenderPrimitiveTopology::LINE_STRIP || desc.primitiveTopology == RenderPrimitiveTopology::TRIANGLE_STRIP) {
|
||||
psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF;
|
||||
}
|
||||
psoDesc.PrimitiveTopologyType = toTopologyType(desc.primitiveTopology);
|
||||
psoDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
||||
psoDesc.RasterizerState.DepthClipEnable = desc.depthClipEnabled;
|
||||
|
|
|
@ -159,7 +159,6 @@ namespace RT64 {
|
|||
|
||||
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;
|
||||
|
@ -169,14 +168,14 @@ namespace RT64 {
|
|||
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 setComputePushConstants(uint32_t rangeIndex, const void *data, uint32_t offset = 0, uint32_t size = 0) 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 setGraphicsPushConstants(uint32_t rangeIndex, const void *data, uint32_t offset = 0, uint32_t size = 0) 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 setRaytracingPushConstants(uint32_t rangeIndex, const void *data, uint32_t offset = 0, uint32_t size = 0) 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;
|
||||
|
@ -250,6 +249,7 @@ namespace RT64 {
|
|||
void unmap(uint32_t subresource, const RenderRange *writtenRange) override;
|
||||
std::unique_ptr<RenderBufferFormattedView> createBufferFormattedView(RenderFormat format) override;
|
||||
void setName(const std::string &name) override;
|
||||
uint64_t getDeviceAddress() const override;
|
||||
};
|
||||
|
||||
struct D3D12BufferFormattedView : RenderBufferFormattedView {
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace RT64 {
|
|||
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;
|
||||
virtual uint64_t getDeviceAddress() const = 0;
|
||||
|
||||
// Concrete implementation shortcuts.
|
||||
inline RenderBufferReference at(uint64_t offset) const {
|
||||
|
@ -104,7 +105,6 @@ namespace RT64 {
|
|||
|
||||
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;
|
||||
|
@ -114,14 +114,14 @@ namespace RT64 {
|
|||
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 setComputePushConstants(uint32_t rangeIndex, const void *data, uint32_t offset = 0, uint32_t size = 0) = 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 setGraphicsPushConstants(uint32_t rangeIndex, const void *data, uint32_t offset = 0, uint32_t size = 0) = 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 setRaytracingPushConstants(uint32_t rangeIndex, const void *data, uint32_t offset = 0, uint32_t size = 0) = 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;
|
||||
|
|
|
@ -405,7 +405,8 @@ namespace RT64 {
|
|||
RENDER_TARGET = 1U << 0,
|
||||
DEPTH_TARGET = 1U << 1,
|
||||
STORAGE = 1U << 2,
|
||||
UNORDERED_ACCESS = 1U << 3
|
||||
UNORDERED_ACCESS = 1U << 3,
|
||||
CUBE = 1U << 4
|
||||
};
|
||||
};
|
||||
|
||||
|
|
4105
UnleashedRecomp/gpu/rhi/rt64_vulkan.cpp
Normal file
4105
UnleashedRecomp/gpu/rhi/rt64_vulkan.cpp
Normal file
File diff suppressed because it is too large
Load diff
409
UnleashedRecomp/gpu/rhi/rt64_vulkan.h
Normal file
409
UnleashedRecomp/gpu/rhi/rt64_vulkan.h
Normal file
|
@ -0,0 +1,409 @@
|
|||
//
|
||||
// RT64
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rt64_render_interface.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#if defined(_WIN64)
|
||||
#define VK_USE_PLATFORM_WIN32_KHR
|
||||
#elif defined(__ANDROID__)
|
||||
#define VK_USE_PLATFORM_ANDROID_KHR
|
||||
#elif defined(__linux__)
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#endif
|
||||
|
||||
#include "volk.h"
|
||||
|
||||
#include "vk_mem_alloc.h"
|
||||
|
||||
namespace RT64 {
|
||||
struct VulkanCommandQueue;
|
||||
struct VulkanDevice;
|
||||
struct VulkanInterface;
|
||||
struct VulkanPool;
|
||||
struct VulkanQueue;
|
||||
|
||||
struct VulkanBuffer : RenderBuffer {
|
||||
VkBuffer vk = VK_NULL_HANDLE;
|
||||
VulkanDevice *device = nullptr;
|
||||
VulkanPool *pool = nullptr;
|
||||
VmaAllocation allocation = VK_NULL_HANDLE;
|
||||
VmaAllocationInfo allocationInfo = {};
|
||||
RenderBufferDesc desc;
|
||||
RenderBarrierStages barrierStages = RenderBarrierStage::NONE;
|
||||
|
||||
VulkanBuffer() = default;
|
||||
VulkanBuffer(VulkanDevice *device, VulkanPool *pool, const RenderBufferDesc &desc);
|
||||
~VulkanBuffer() 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;
|
||||
uint64_t getDeviceAddress() const override;
|
||||
};
|
||||
|
||||
struct VulkanBufferFormattedView : RenderBufferFormattedView {
|
||||
VkBufferView vk = VK_NULL_HANDLE;
|
||||
VulkanBuffer *buffer = nullptr;
|
||||
|
||||
VulkanBufferFormattedView(VulkanBuffer *buffer, RenderFormat format);
|
||||
~VulkanBufferFormattedView() override;
|
||||
};
|
||||
|
||||
struct VulkanTexture : RenderTexture {
|
||||
VkImage vk = VK_NULL_HANDLE;
|
||||
VkImageView imageView = VK_NULL_HANDLE;
|
||||
VkFormat imageFormat = VK_FORMAT_UNDEFINED;
|
||||
VkImageSubresourceRange imageSubresourceRange = {};
|
||||
VulkanDevice *device = nullptr;
|
||||
VulkanPool *pool = nullptr;
|
||||
VmaAllocation allocation = VK_NULL_HANDLE;
|
||||
VmaAllocationInfo allocationInfo = {};
|
||||
RenderTextureLayout textureLayout = RenderTextureLayout::UNKNOWN;
|
||||
RenderBarrierStages barrierStages = RenderBarrierStage::NONE;
|
||||
bool ownership = false;
|
||||
RenderTextureDesc desc;
|
||||
|
||||
VulkanTexture() = default;
|
||||
VulkanTexture(VulkanDevice *device, VulkanPool *pool, const RenderTextureDesc &desc);
|
||||
VulkanTexture(VulkanDevice *device, VkImage image);
|
||||
~VulkanTexture() override;
|
||||
void createImageView(VkFormat format);
|
||||
std::unique_ptr<RenderTextureView> createTextureView(const RenderTextureViewDesc &desc) override;
|
||||
void setName(const std::string &name) override;
|
||||
void fillSubresourceRange();
|
||||
};
|
||||
|
||||
struct VulkanTextureView : RenderTextureView {
|
||||
VkImageView vk = VK_NULL_HANDLE;
|
||||
VulkanTexture *texture = nullptr;
|
||||
|
||||
VulkanTextureView(VulkanTexture *texture, const RenderTextureViewDesc &desc);
|
||||
~VulkanTextureView() override;
|
||||
};
|
||||
|
||||
struct VulkanAccelerationStructure : RenderAccelerationStructure {
|
||||
VkAccelerationStructureKHR vk = VK_NULL_HANDLE;
|
||||
VulkanDevice *device = nullptr;
|
||||
RenderAccelerationStructureType type = RenderAccelerationStructureType::UNKNOWN;
|
||||
|
||||
VulkanAccelerationStructure(VulkanDevice *device, const RenderAccelerationStructureDesc &desc);
|
||||
~VulkanAccelerationStructure() override;
|
||||
};
|
||||
|
||||
struct VulkanDescriptorSetLayout {
|
||||
VkDescriptorSetLayout vk = VK_NULL_HANDLE;
|
||||
std::vector<VkDescriptorSetLayoutBinding> setBindings;
|
||||
std::vector<uint32_t> descriptorIndexBases;
|
||||
std::vector<uint32_t> descriptorBindingIndices;
|
||||
VulkanDevice *device = nullptr;
|
||||
|
||||
VulkanDescriptorSetLayout(VulkanDevice *device, const RenderDescriptorSetDesc &descriptorSetDesc);
|
||||
~VulkanDescriptorSetLayout();
|
||||
};
|
||||
|
||||
struct VulkanPipelineLayout : RenderPipelineLayout {
|
||||
VkPipelineLayout vk = VK_NULL_HANDLE;
|
||||
std::vector<VkPushConstantRange> pushConstantRanges;
|
||||
std::vector<VulkanDescriptorSetLayout *> descriptorSetLayouts;
|
||||
VulkanDevice *device = nullptr;
|
||||
|
||||
VulkanPipelineLayout(VulkanDevice *device, const RenderPipelineLayoutDesc &desc);
|
||||
~VulkanPipelineLayout() override;
|
||||
};
|
||||
|
||||
struct VulkanShader : RenderShader {
|
||||
VkShaderModule vk = VK_NULL_HANDLE;
|
||||
std::string entryPointName;
|
||||
VulkanDevice *device = nullptr;
|
||||
RenderShaderFormat format = RenderShaderFormat::UNKNOWN;
|
||||
|
||||
VulkanShader(VulkanDevice *device, const void *data, uint64_t size, const char *entryPointName, RenderShaderFormat format);
|
||||
~VulkanShader() override;
|
||||
};
|
||||
|
||||
struct VulkanSampler : RenderSampler {
|
||||
VkSampler vk = VK_NULL_HANDLE;
|
||||
VulkanDevice *device = nullptr;
|
||||
|
||||
VulkanSampler(VulkanDevice *device, const RenderSamplerDesc &desc);
|
||||
~VulkanSampler();
|
||||
};
|
||||
|
||||
struct VulkanPipeline : RenderPipeline {
|
||||
enum class Type {
|
||||
Unknown,
|
||||
Compute,
|
||||
Graphics,
|
||||
Raytracing
|
||||
};
|
||||
|
||||
VulkanDevice *device = nullptr;
|
||||
Type type = Type::Unknown;
|
||||
|
||||
VulkanPipeline(VulkanDevice *device, Type type);
|
||||
virtual ~VulkanPipeline() override;
|
||||
};
|
||||
|
||||
struct VulkanComputePipeline : VulkanPipeline {
|
||||
VkPipeline vk = VK_NULL_HANDLE;
|
||||
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
|
||||
|
||||
VulkanComputePipeline(VulkanDevice *device, const RenderComputePipelineDesc &desc);
|
||||
~VulkanComputePipeline() override;
|
||||
RenderPipelineProgram getProgram(const std::string &name) const override;
|
||||
};
|
||||
|
||||
struct VulkanGraphicsPipeline : VulkanPipeline {
|
||||
VkPipeline vk = VK_NULL_HANDLE;
|
||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||
|
||||
VulkanGraphicsPipeline(VulkanDevice *device, const RenderGraphicsPipelineDesc &desc);
|
||||
~VulkanGraphicsPipeline() override;
|
||||
RenderPipelineProgram getProgram(const std::string &name) const override;
|
||||
static VkRenderPass createRenderPass(VulkanDevice *device, const VkFormat *renderTargetFormat, uint32_t renderTargetCount, VkFormat depthTargetFormat, VkSampleCountFlagBits sampleCount);
|
||||
};
|
||||
|
||||
struct VulkanRaytracingPipeline : VulkanPipeline {
|
||||
VkPipeline vk = VK_NULL_HANDLE;
|
||||
std::unordered_map<std::string, RenderPipelineProgram> nameProgramMap;
|
||||
uint32_t groupCount = 0;
|
||||
uint32_t descriptorSetCount = 0;
|
||||
|
||||
VulkanRaytracingPipeline(VulkanDevice *device, const RenderRaytracingPipelineDesc &desc, const RenderPipeline *previousPipeline);
|
||||
~VulkanRaytracingPipeline() override;
|
||||
RenderPipelineProgram getProgram(const std::string &name) const override;
|
||||
};
|
||||
|
||||
struct VulkanDescriptorSet : RenderDescriptorSet {
|
||||
VkDescriptorSet vk = VK_NULL_HANDLE;
|
||||
VulkanDescriptorSetLayout *setLayout = nullptr;
|
||||
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
|
||||
VulkanDevice *device = nullptr;
|
||||
|
||||
VulkanDescriptorSet(VulkanDevice *device, const RenderDescriptorSetDesc &desc);
|
||||
~VulkanDescriptorSet() 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 setDescriptor(uint32_t descriptorIndex, const VkDescriptorBufferInfo *bufferInfo, const VkDescriptorImageInfo *imageInfo, const VkBufferView *texelBufferView, void *pNext);
|
||||
static VkDescriptorPool createDescriptorPool(VulkanDevice *device, const std::unordered_map<VkDescriptorType, uint32_t> &typeCounts, bool lastRangeIsBoundless);
|
||||
};
|
||||
|
||||
struct VulkanSwapChain : RenderSwapChain {
|
||||
VkSwapchainKHR vk = VK_NULL_HANDLE;
|
||||
VulkanCommandQueue *commandQueue = nullptr;
|
||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||
RenderWindow renderWindow = {};
|
||||
uint32_t textureCount = 0;
|
||||
uint64_t presentCount = 0;
|
||||
RenderFormat format = RenderFormat::UNKNOWN;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
VkSwapchainCreateInfoKHR createInfo = {};
|
||||
VkSurfaceFormatKHR pickedSurfaceFormat = {};
|
||||
VkPresentModeKHR pickedPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
VkCompositeAlphaFlagBitsKHR pickedAlphaFlag = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
std::vector<VulkanTexture> textures;
|
||||
|
||||
VulkanSwapChain(VulkanCommandQueue *commandQueue, RenderWindow renderWindow, uint32_t textureCount, RenderFormat format);
|
||||
~VulkanSwapChain() 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 releaseSwapChain();
|
||||
void releaseImageViews();
|
||||
};
|
||||
|
||||
struct VulkanFramebuffer : RenderFramebuffer {
|
||||
VulkanDevice *device = nullptr;
|
||||
VkFramebuffer vk = VK_NULL_HANDLE;
|
||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||
std::vector<const VulkanTexture *> colorAttachments;
|
||||
const VulkanTexture *depthAttachment = nullptr;
|
||||
bool depthAttachmentReadOnly = false;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
|
||||
VulkanFramebuffer(VulkanDevice *device, const RenderFramebufferDesc &desc);
|
||||
~VulkanFramebuffer() override;
|
||||
uint32_t getWidth() const override;
|
||||
uint32_t getHeight() const override;
|
||||
bool contains(const VulkanTexture *attachment) const;
|
||||
};
|
||||
|
||||
struct VulkanCommandList : RenderCommandList {
|
||||
VkCommandBuffer vk = VK_NULL_HANDLE;
|
||||
VkCommandPool commandPool = VK_NULL_HANDLE;
|
||||
VulkanDevice *device = nullptr;
|
||||
RenderCommandListType type = RenderCommandListType::UNKNOWN;
|
||||
const VulkanFramebuffer *targetFramebuffer = nullptr;
|
||||
const VulkanPipelineLayout *activeComputePipelineLayout = nullptr;
|
||||
const VulkanPipelineLayout *activeGraphicsPipelineLayout = nullptr;
|
||||
const VulkanPipelineLayout *activeRaytracingPipelineLayout = nullptr;
|
||||
VkRenderPass activeRenderPass = VK_NULL_HANDLE;
|
||||
|
||||
VulkanCommandList(VulkanDevice *device, RenderCommandListType type);
|
||||
~VulkanCommandList() 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, uint32_t offset = 0, uint32_t size = 0) override;
|
||||
void setComputeDescriptorSet(RenderDescriptorSet *descriptorSet, uint32_t setIndex) override;
|
||||
void setGraphicsPipelineLayout(const RenderPipelineLayout *pipelineLayout) override;
|
||||
void setGraphicsPushConstants(uint32_t rangeIndex, const void *data, uint32_t offset = 0, uint32_t size = 0) 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, uint32_t offset = 0, uint32_t size = 0) 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 checkActiveRenderPass();
|
||||
void endActiveRenderPass();
|
||||
void setDescriptorSet(VkPipelineBindPoint bindPoint, const VulkanPipelineLayout *pipelineLayout, const RenderDescriptorSet *descriptorSet, uint32_t setIndex);
|
||||
};
|
||||
|
||||
struct VulkanCommandFence : RenderCommandFence {
|
||||
VkFence vk = VK_NULL_HANDLE;
|
||||
VulkanDevice *device = nullptr;
|
||||
|
||||
VulkanCommandFence(VulkanDevice *device);
|
||||
~VulkanCommandFence() override;
|
||||
};
|
||||
|
||||
struct VulkanCommandSemaphore : RenderCommandSemaphore {
|
||||
VkSemaphore vk = VK_NULL_HANDLE;
|
||||
VulkanDevice *device = nullptr;
|
||||
|
||||
VulkanCommandSemaphore(VulkanDevice *device);
|
||||
~VulkanCommandSemaphore() override;
|
||||
};
|
||||
|
||||
struct VulkanCommandQueue : RenderCommandQueue {
|
||||
VulkanQueue *queue = nullptr;
|
||||
VulkanDevice *device = nullptr;
|
||||
uint32_t familyIndex = 0;
|
||||
uint32_t queueIndex = 0;
|
||||
std::unordered_set<VulkanSwapChain *> swapChains;
|
||||
|
||||
VulkanCommandQueue(VulkanDevice *device, RenderCommandListType commandListType);
|
||||
~VulkanCommandQueue() override;
|
||||
std::unique_ptr<RenderSwapChain> createSwapChain(RenderWindow renderWindow, uint32_t bufferCount, 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 VulkanPool : RenderPool {
|
||||
VmaPool vk = VK_NULL_HANDLE;
|
||||
VulkanDevice *device = nullptr;
|
||||
|
||||
VulkanPool(VulkanDevice *device, const RenderPoolDesc &desc);
|
||||
~VulkanPool() override;
|
||||
std::unique_ptr<RenderBuffer> createBuffer(const RenderBufferDesc &desc) override;
|
||||
std::unique_ptr<RenderTexture> createTexture(const RenderTextureDesc &desc) override;
|
||||
};
|
||||
|
||||
struct VulkanQueue {
|
||||
VkQueue vk;
|
||||
std::unique_ptr<std::mutex> mutex;
|
||||
std::unordered_set<const VulkanCommandQueue *> virtualQueues;
|
||||
};
|
||||
|
||||
struct VulkanQueueFamily {
|
||||
std::vector<VulkanQueue> queues;
|
||||
|
||||
void add(VulkanCommandQueue *virtualQueue);
|
||||
void remove(VulkanCommandQueue *virtualQueue);
|
||||
};
|
||||
|
||||
struct VulkanDevice : RenderDevice {
|
||||
VkDevice vk = VK_NULL_HANDLE;
|
||||
VulkanInterface *renderInterface = nullptr;
|
||||
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
||||
VkPhysicalDeviceProperties physicalDeviceProperties = {};
|
||||
VmaAllocator allocator = VK_NULL_HANDLE;
|
||||
uint32_t queueFamilyIndices[3] = {};
|
||||
std::vector<VulkanQueueFamily> queueFamilies;
|
||||
RenderDeviceCapabilities capabilities;
|
||||
RenderDeviceDescription description;
|
||||
VkPhysicalDeviceRayTracingPipelinePropertiesKHR rtPipelineProperties = {};
|
||||
VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationProperties = {};
|
||||
bool loadStoreOpNoneSupported = false;
|
||||
|
||||
VulkanDevice(VulkanInterface *renderInterface);
|
||||
~VulkanDevice() 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 VulkanInterface : RenderInterface {
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkApplicationInfo appInfo = {};
|
||||
RenderInterfaceCapabilities capabilities;
|
||||
|
||||
VulkanInterface();
|
||||
~VulkanInterface() override;
|
||||
std::unique_ptr<RenderDevice> createDevice() override;
|
||||
const RenderInterfaceCapabilities &getCapabilities() const override;
|
||||
bool isValid() const;
|
||||
};
|
||||
};
|
|
@ -62,7 +62,7 @@ static bool g_scissorTestEnable = false;
|
|||
static RenderRect g_scissorRect;
|
||||
static RenderVertexBufferView g_vertexBufferViews[16];
|
||||
static RenderInputSlot g_inputSlots[16];
|
||||
static RenderIndexBufferView g_indexBufferView;
|
||||
static RenderIndexBufferView g_indexBufferView({}, 0, RenderFormat::R16_UINT);
|
||||
|
||||
struct DirtyStates
|
||||
{
|
||||
|
@ -104,6 +104,7 @@ static void SetDirtyValue(bool& dirtyState, T& dest, const T& src)
|
|||
}
|
||||
}
|
||||
|
||||
static bool g_vulkan = false;
|
||||
static std::unique_ptr<RenderInterface> g_interface;
|
||||
static std::unique_ptr<RenderDevice> g_device;
|
||||
|
||||
|
@ -122,6 +123,8 @@ static std::unique_ptr<RenderCommandList> g_copyCommandList;
|
|||
static std::unique_ptr<RenderCommandFence> g_copyCommandFence;
|
||||
|
||||
static std::unique_ptr<RenderSwapChain> g_swapChain;
|
||||
static std::unique_ptr<RenderCommandSemaphore> g_acquireSemaphores[NUM_FRAMES];
|
||||
static uint32_t g_backBufferIndex;
|
||||
static GuestSurface* g_backBuffer;
|
||||
|
||||
struct std::unique_ptr<RenderDescriptorSet> g_textureDescriptorSet;
|
||||
|
@ -201,7 +204,7 @@ struct UploadAllocator
|
|||
auto& buffer = buffers[index];
|
||||
if (buffer.buffer == nullptr)
|
||||
{
|
||||
buffer.buffer = g_device->createBuffer(RenderBufferDesc::UploadBuffer(UploadBuffer::SIZE));
|
||||
buffer.buffer = g_device->createBuffer(RenderBufferDesc::UploadBuffer(UploadBuffer::SIZE, RenderBufferFlag::CONSTANT | RenderBufferFlag::VERTEX | RenderBufferFlag::INDEX));
|
||||
buffer.memory = reinterpret_cast<uint8_t*>(buffer.buffer->map());
|
||||
}
|
||||
|
||||
|
@ -472,7 +475,7 @@ static void CreateHostDevice()
|
|||
|
||||
Window::Init();
|
||||
|
||||
g_interface = CreateD3D12Interface();
|
||||
g_interface = g_vulkan ? CreateVulkanInterface() : CreateD3D12Interface();
|
||||
g_device = g_interface->createDevice();
|
||||
|
||||
g_queue = g_device->createCommandQueue(RenderCommandListType::DIRECT);
|
||||
|
@ -488,6 +491,13 @@ static void CreateHostDevice()
|
|||
g_copyCommandFence = g_device->createCommandFence();
|
||||
|
||||
g_swapChain = g_queue->createSwapChain(Window::s_windowHandle, 2, RenderFormat::R8G8B8A8_UNORM);
|
||||
g_swapChain->resize();
|
||||
|
||||
if (g_vulkan)
|
||||
{
|
||||
for (auto& acquireSemaphore : g_acquireSemaphores)
|
||||
acquireSemaphore = g_device->createCommandSemaphore();
|
||||
}
|
||||
|
||||
RenderPipelineLayoutBuilder pipelineLayoutBuilder;
|
||||
pipelineLayoutBuilder.begin(false, true);
|
||||
|
@ -512,9 +522,16 @@ static void CreateHostDevice()
|
|||
g_samplerDescriptorSet = descriptorSetBuilder.create(g_device.get());
|
||||
pipelineLayoutBuilder.addDescriptorSet(descriptorSetBuilder);
|
||||
|
||||
pipelineLayoutBuilder.addRootDescriptor(0, 4, RenderRootDescriptorType::CONSTANT_BUFFER);
|
||||
pipelineLayoutBuilder.addRootDescriptor(1, 4, RenderRootDescriptorType::CONSTANT_BUFFER);
|
||||
pipelineLayoutBuilder.addRootDescriptor(2, 4, RenderRootDescriptorType::CONSTANT_BUFFER);
|
||||
if (g_vulkan)
|
||||
{
|
||||
pipelineLayoutBuilder.addPushConstant(0, 4, 24, RenderShaderStageFlag::VERTEX | RenderShaderStageFlag::PIXEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
pipelineLayoutBuilder.addRootDescriptor(0, 4, RenderRootDescriptorType::CONSTANT_BUFFER);
|
||||
pipelineLayoutBuilder.addRootDescriptor(1, 4, RenderRootDescriptorType::CONSTANT_BUFFER);
|
||||
pipelineLayoutBuilder.addRootDescriptor(2, 4, RenderRootDescriptorType::CONSTANT_BUFFER);
|
||||
}
|
||||
pipelineLayoutBuilder.end();
|
||||
|
||||
g_pipelineLayout = pipelineLayoutBuilder.create(g_device.get());
|
||||
|
@ -528,9 +545,9 @@ static void BeginCommandList()
|
|||
g_pipelineState.renderTargetFormat = g_backBuffer->format;
|
||||
g_pipelineState.depthStencilFormat = RenderFormat::UNKNOWN;
|
||||
|
||||
uint32_t textureIndex = 0;
|
||||
g_swapChain->acquireTexture(nullptr, &textureIndex);
|
||||
g_backBuffer->texture = g_swapChain->getTexture(textureIndex);
|
||||
bool acquired = g_swapChain->acquireTexture(g_acquireSemaphores[g_frame].get(), &g_backBufferIndex);
|
||||
assert(acquired);
|
||||
g_backBuffer->texture = g_swapChain->getTexture(g_backBufferIndex);
|
||||
|
||||
auto& commandList = g_commandLists[g_frame];
|
||||
|
||||
|
@ -779,9 +796,22 @@ static void Present()
|
|||
auto& commandList = g_commandLists[g_frame];
|
||||
commandList->barriers(RenderBarrierStage::GRAPHICS, RenderTextureBarrier(g_backBuffer->texture, RenderTextureLayout::PRESENT));
|
||||
commandList->end();
|
||||
|
||||
g_queue->executeCommandLists(commandList.get(), g_commandFences[g_frame].get());
|
||||
g_swapChain->present(0, nullptr, 0);
|
||||
|
||||
if (g_vulkan)
|
||||
{
|
||||
const RenderCommandList* commandLists[] = { commandList.get() };
|
||||
RenderCommandSemaphore* waitSemaphores[] = { g_acquireSemaphores[g_frame].get()};
|
||||
g_queue->executeCommandLists(
|
||||
commandLists, std::size(commandLists),
|
||||
waitSemaphores, std::size(waitSemaphores),
|
||||
nullptr, 0,
|
||||
g_commandFences[g_frame].get());
|
||||
}
|
||||
else
|
||||
{
|
||||
g_queue->executeCommandLists(commandList.get(), g_commandFences[g_frame].get());
|
||||
}
|
||||
g_swapChain->present(g_backBufferIndex, nullptr, 0);
|
||||
|
||||
g_frame = g_nextFrame;
|
||||
g_nextFrame = (g_frame + 1) % NUM_FRAMES;
|
||||
|
@ -856,10 +886,11 @@ static GuestTexture* CreateTexture(uint32_t width, uint32_t height, uint32_t dep
|
|||
desc.mipLevels = levels;
|
||||
desc.arraySize = 1;
|
||||
desc.format = ConvertFormat(format);
|
||||
desc.flags = (desc.format == RenderFormat::D32_FLOAT) ? RenderTextureFlag::DEPTH_TARGET : RenderTextureFlag::NONE;
|
||||
texture->texture = g_device->createTexture(desc);
|
||||
|
||||
RenderTextureViewDesc viewDesc;
|
||||
viewDesc.format = desc.format == RenderFormat::D32_FLOAT ? RenderFormat::R32_FLOAT : desc.format;
|
||||
viewDesc.format = desc.format;
|
||||
viewDesc.dimension = texture->type == ResourceType::VolumeTexture ? RenderTextureViewDimension::TEXTURE_3D : RenderTextureViewDimension::TEXTURE_2D;
|
||||
viewDesc.mipLevels = levels;
|
||||
texture->textureView = texture->texture->createTextureView(viewDesc);
|
||||
|
@ -878,7 +909,7 @@ static GuestTexture* CreateTexture(uint32_t width, uint32_t height, uint32_t dep
|
|||
static GuestBuffer* CreateVertexBuffer(uint32_t length)
|
||||
{
|
||||
auto buffer = g_userHeap.AllocPhysical<GuestBuffer>(ResourceType::VertexBuffer);
|
||||
buffer->buffer = g_device->createBuffer(RenderBufferDesc::VertexBuffer(length, RenderHeapType::DEFAULT));
|
||||
buffer->buffer = g_device->createBuffer(RenderBufferDesc::VertexBuffer(length, RenderHeapType::DEFAULT, RenderBufferFlag::INDEX));
|
||||
buffer->dataSize = length;
|
||||
#ifdef _DEBUG
|
||||
buffer->buffer->setName(std::format("Vertex Buffer {:X}", g_memory.MapVirtual(buffer)));
|
||||
|
@ -1204,7 +1235,7 @@ static void FlushRenderState(GuestDevice* device)
|
|||
constexpr size_t BOOL_MASK = 0x100000000000000ull;
|
||||
if ((device->dirtyFlags[4].get() & BOOL_MASK) != 0)
|
||||
{
|
||||
uint32_t booleans = device->vertexShaderBoolConstants [0].get() & 0xFF;
|
||||
uint32_t booleans = device->vertexShaderBoolConstants[0].get() & 0xFF;
|
||||
booleans |= (device->pixelShaderBoolConstants[0].get() & 0xFF) << 16;
|
||||
|
||||
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.booleans, booleans);
|
||||
|
@ -1250,15 +1281,30 @@ static void FlushRenderState(GuestDevice* device)
|
|||
|
||||
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.samplerIndices[i], descriptorIndex);
|
||||
}
|
||||
|
||||
device->dirtyFlags[3] = device->dirtyFlags[3].get() & ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
auto& uploadAllocator = g_uploadAllocators[g_frame];
|
||||
|
||||
auto setRootDescriptor = [&](RenderBufferReference reference, size_t index)
|
||||
{
|
||||
if (g_vulkan)
|
||||
{
|
||||
uint64_t address = reference.ref->getDeviceAddress() + reference.offset;
|
||||
commandList->setGraphicsPushConstants(0, &address, 8 * index, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
commandList->setGraphicsRootDescriptor(reference, index);
|
||||
}
|
||||
};
|
||||
|
||||
if (g_dirtyStates.sharedConstants)
|
||||
{
|
||||
auto sharedConstants = uploadAllocator.allocate<false>(&g_sharedConstants, sizeof(g_sharedConstants), 0x100);
|
||||
commandList->setGraphicsRootDescriptor(sharedConstants, 2);
|
||||
setRootDescriptor(sharedConstants, 2);
|
||||
}
|
||||
|
||||
if (g_dirtyStates.scissorRect)
|
||||
|
@ -1275,8 +1321,7 @@ static void FlushRenderState(GuestDevice* device)
|
|||
if (g_dirtyStates.vertexShaderConstants || device->dirtyFlags[0] != 0)
|
||||
{
|
||||
auto vertexShaderConstants = uploadAllocator.allocate<true>(device->vertexShaderFloatConstants, 0x1000, 0x100);
|
||||
commandList->setGraphicsRootDescriptor(vertexShaderConstants, 0);
|
||||
|
||||
setRootDescriptor(vertexShaderConstants, 0);
|
||||
device->dirtyFlags[0] = 0;
|
||||
}
|
||||
|
||||
|
@ -1289,14 +1334,13 @@ static void FlushRenderState(GuestDevice* device)
|
|||
g_inputSlots + g_dirtyStates.vertexStreamFirst);
|
||||
}
|
||||
|
||||
if (g_dirtyStates.indices)
|
||||
if (g_dirtyStates.indices && (!g_vulkan || g_indexBufferView.buffer.ref != nullptr))
|
||||
commandList->setIndexBuffer(&g_indexBufferView);
|
||||
|
||||
if (g_dirtyStates.pixelShaderConstants || device->dirtyFlags[1] != 0)
|
||||
{
|
||||
auto pixelShaderConstants = uploadAllocator.allocate<true>(device->pixelShaderFloatConstants, 0xE00, 0x100);
|
||||
commandList->setGraphicsRootDescriptor(pixelShaderConstants, 1);
|
||||
|
||||
setRootDescriptor(pixelShaderConstants, 1);
|
||||
device->dirtyFlags[1] = 0;
|
||||
}
|
||||
|
||||
|
@ -1555,14 +1599,60 @@ static GuestVertexDeclaration* CreateVertexDeclaration(GuestVertexElement* verte
|
|||
static std::vector<RenderInputElement> inputElements;
|
||||
inputElements.clear();
|
||||
|
||||
struct Location
|
||||
{
|
||||
uint32_t usage;
|
||||
uint32_t usageIndex;
|
||||
uint32_t location;
|
||||
};
|
||||
|
||||
constexpr Location locations[] =
|
||||
{
|
||||
{ D3DDECLUSAGE_POSITION, 0, 0 },
|
||||
{ D3DDECLUSAGE_NORMAL, 0, 1 },
|
||||
{ D3DDECLUSAGE_TANGENT, 0, 2 },
|
||||
{ D3DDECLUSAGE_BINORMAL, 0, 3 },
|
||||
{ D3DDECLUSAGE_TEXCOORD, 0, 4 },
|
||||
{ D3DDECLUSAGE_TEXCOORD, 1, 5 },
|
||||
{ D3DDECLUSAGE_TEXCOORD, 2, 6 },
|
||||
{ D3DDECLUSAGE_TEXCOORD, 3, 7 },
|
||||
{ D3DDECLUSAGE_COLOR, 0, 8 },
|
||||
{ D3DDECLUSAGE_BLENDINDICES, 0, 9 },
|
||||
{ D3DDECLUSAGE_BLENDWEIGHT, 0, 10 },
|
||||
{ D3DDECLUSAGE_COLOR, 1, 11 },
|
||||
{ D3DDECLUSAGE_TEXCOORD, 4, 12 },
|
||||
{ D3DDECLUSAGE_TEXCOORD, 5, 13 },
|
||||
{ D3DDECLUSAGE_TEXCOORD, 6, 14 },
|
||||
{ D3DDECLUSAGE_TEXCOORD, 7, 15 },
|
||||
{ D3DDECLUSAGE_POSITION, 1, 15 }
|
||||
};
|
||||
|
||||
vertexElement = vertexElements;
|
||||
while (vertexElement->stream != 0xFF && vertexElement->type != D3DDECLTYPE_UNUSED)
|
||||
{
|
||||
if (vertexElement->usage == D3DDECLUSAGE_POSITION && vertexElement->usageIndex == 2)
|
||||
{
|
||||
++vertexElement;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& inputElement = inputElements.emplace_back();
|
||||
|
||||
inputElement.semanticName = ConvertDeclUsage(vertexElement->usage);
|
||||
inputElement.semanticIndex = vertexElement->usageIndex;
|
||||
inputElement.location = (vertexElement->usage * 4) + vertexElement->usageIndex;
|
||||
inputElement.location = ~0;
|
||||
|
||||
for (auto& location : locations)
|
||||
{
|
||||
if (location.usage == vertexElement->usage && location.usageIndex == vertexElement->usageIndex)
|
||||
{
|
||||
inputElement.location = location.location;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(inputElement.location != ~0);
|
||||
|
||||
inputElement.format = ConvertDeclType(vertexElement->type);
|
||||
inputElement.slotIndex = vertexElement->stream;
|
||||
inputElement.alignedByteOffset = vertexElement->offset;
|
||||
|
@ -1611,7 +1701,18 @@ static GuestVertexDeclaration* CreateVertexDeclaration(GuestVertexElement* verte
|
|||
|
||||
auto addInputElement = [&](uint32_t usage, uint32_t usageIndex)
|
||||
{
|
||||
uint32_t location = (usage * 4) + usageIndex;
|
||||
uint32_t location = ~0;
|
||||
|
||||
for (auto& alsoLocation : locations)
|
||||
{
|
||||
if (alsoLocation.usage == usage && alsoLocation.usageIndex == usageIndex)
|
||||
{
|
||||
location = alsoLocation.location;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(location != ~0);
|
||||
|
||||
for (auto& inputElement : inputElements)
|
||||
{
|
||||
|
@ -1642,7 +1743,6 @@ static GuestVertexDeclaration* CreateVertexDeclaration(GuestVertexElement* verte
|
|||
addInputElement(D3DDECLUSAGE_TEXCOORD, 2);
|
||||
addInputElement(D3DDECLUSAGE_TEXCOORD, 3);
|
||||
addInputElement(D3DDECLUSAGE_COLOR, 0);
|
||||
addInputElement(D3DDECLUSAGE_COLOR, 1);
|
||||
addInputElement(D3DDECLUSAGE_BLENDWEIGHT, 0);
|
||||
addInputElement(D3DDECLUSAGE_BLENDINDICES, 0);
|
||||
|
||||
|
@ -1671,11 +1771,30 @@ static void SetVertexDeclaration(GuestDevice* device, GuestVertexDeclaration* ve
|
|||
device->vertexDeclaration = vertexDeclaration;
|
||||
}
|
||||
|
||||
static std::unique_ptr<RenderShader> CreateShader(const uint32_t* function)
|
||||
{
|
||||
if (*function == 0)
|
||||
{
|
||||
const uint32_t dxilSize = *(function + 1);
|
||||
const uint32_t spirvSize = *(function + 2);
|
||||
|
||||
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(function + 3);
|
||||
if (g_vulkan)
|
||||
{
|
||||
return g_device->createShader(bytes + dxilSize, spirvSize, "main", RenderShaderFormat::SPIRV);
|
||||
}
|
||||
else
|
||||
{
|
||||
return g_device->createShader(bytes, dxilSize, "main", RenderShaderFormat::DXIL);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static GuestShader* CreateVertexShader(const uint32_t* function)
|
||||
{
|
||||
auto vertexShader = g_userHeap.AllocPhysical<GuestShader>(ResourceType::VertexShader);
|
||||
if (*function == 0x43425844)
|
||||
vertexShader->shader = g_device->createShader(function, function[6], "main", RenderShaderFormat::DXIL);
|
||||
vertexShader->shader = CreateShader(function);
|
||||
|
||||
return vertexShader;
|
||||
}
|
||||
|
@ -1705,15 +1824,14 @@ static void SetStreamSource(GuestDevice* device, uint32_t index, GuestBuffer* bu
|
|||
static void SetIndices(GuestDevice* device, GuestBuffer* buffer)
|
||||
{
|
||||
SetDirtyValue(g_dirtyStates.indices, g_indexBufferView.buffer, buffer != nullptr ? buffer->buffer->at(0) : RenderBufferReference{});
|
||||
SetDirtyValue(g_dirtyStates.indices, g_indexBufferView.format, buffer != nullptr ? buffer->format : RenderFormat::UNKNOWN);
|
||||
SetDirtyValue(g_dirtyStates.indices, g_indexBufferView.format, buffer != nullptr ? buffer->format : RenderFormat::R16_UINT);
|
||||
SetDirtyValue(g_dirtyStates.indices, g_indexBufferView.size, buffer != nullptr ? buffer->dataSize : 0u);
|
||||
}
|
||||
|
||||
static GuestShader* CreatePixelShader(const uint32_t* function)
|
||||
{
|
||||
auto pixelShader = g_userHeap.AllocPhysical<GuestShader>(ResourceType::PixelShader);
|
||||
if (*function == 0x43425844)
|
||||
pixelShader->shader = g_device->createShader(function, function[6], "main", RenderShaderFormat::DXIL);
|
||||
pixelShader->shader = CreateShader(function);
|
||||
|
||||
return pixelShader;
|
||||
}
|
||||
|
@ -2031,6 +2149,7 @@ static void MakePictureData(GuestPictureData* pictureData, uint8_t* data, uint32
|
|||
desc.mipLevels = ddsDesc.numMips;
|
||||
desc.arraySize = ddsDesc.type == ddspp::TextureType::Cubemap ? ddsDesc.arraySize * 6 : ddsDesc.arraySize;
|
||||
desc.format = ConvertDXGIFormat(ddsDesc.format);
|
||||
desc.flags = ddsDesc.type == ddspp::TextureType::Cubemap ? RenderTextureFlag::CUBE : RenderTextureFlag::NONE;
|
||||
texture->texture = g_device->createTexture(desc);
|
||||
#ifdef _DEBUG
|
||||
texture->texture->setName(reinterpret_cast<char*>(g_memory.Translate(pictureData->name + 2)));
|
||||
|
@ -2108,6 +2227,8 @@ static void MakePictureData(GuestPictureData* pictureData, uint8_t* data, uint32
|
|||
|
||||
ExecuteCopyCommandList([&]
|
||||
{
|
||||
g_copyCommandList->barriers(RenderBarrierStage::COPY, RenderTextureBarrier(texture->texture.get(), RenderTextureLayout::COPY_DEST));
|
||||
|
||||
for (size_t i = 0; i < slices.size(); i++)
|
||||
{
|
||||
auto& slice = slices[i];
|
||||
|
|
1
thirdparty/Vulkan-Headers
vendored
Submodule
1
thirdparty/Vulkan-Headers
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 14345dab231912ee9601136e96ca67a6e1f632e7
|
1
thirdparty/VulkanMemoryAllocator
vendored
Submodule
1
thirdparty/VulkanMemoryAllocator
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 1c35ba99ce775f8342d87a83a3f0f696f99c2a39
|
1
thirdparty/volk
vendored
Submodule
1
thirdparty/volk
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 447e21b5d92ed8d5271b0d39b071f938fcfa875f
|
Loading…
Add table
Add a link
Reference in a new issue