1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-20 19:54:19 +01:00

[d3d9] Introduce D3D9ConstantBuffer

This commit is contained in:
Philip Rebohle 2022-07-14 13:52:29 +02:00 committed by Philip Rebohle
parent bcd2be0698
commit e8d5ce94ea
4 changed files with 201 additions and 0 deletions

View File

@ -0,0 +1,121 @@
#include "d3d9_constant_buffer.h"
#include "d3d9_device.h"
namespace dxvk {
D3D9ConstantBuffer::D3D9ConstantBuffer() {
}
D3D9ConstantBuffer::D3D9ConstantBuffer(
D3D9DeviceEx* pDevice,
DxsoProgramType ShaderStage,
DxsoConstantBuffers BufferType,
VkDeviceSize Size)
: m_device (pDevice)
, m_binding (computeResourceSlotId(ShaderStage, DxsoBindingType::ConstantBuffer, BufferType))
, m_stages (GetShaderStage(ShaderStage))
, m_size (Size)
, m_align (getAlignment(pDevice->GetDXVKDevice())) {
}
D3D9ConstantBuffer::~D3D9ConstantBuffer() {
}
void* D3D9ConstantBuffer::Alloc(VkDeviceSize size) {
if (unlikely(m_buffer == nullptr)) {
this->createBuffer();
m_slice = m_buffer->getSliceHandle();
}
size = align(size, m_align);
if (unlikely(m_offset + size > m_size)) {
m_slice = m_buffer->allocSlice();
m_offset = 0;
m_device->EmitCs([
cBuffer = m_buffer,
cSlice = m_slice
] (DxvkContext* ctx) {
ctx->invalidateBuffer(cBuffer, cSlice);
});
}
m_device->EmitCs([
cStages = m_stages,
cBinding = m_binding,
cOffset = m_offset,
cLength = size
] (DxvkContext* ctx) {
ctx->bindResourceBufferRange(cStages, cBinding, cOffset, cLength);
});
void* mapPtr = reinterpret_cast<char*>(m_slice.mapPtr) + m_offset;
m_offset += size;
return mapPtr;
}
void* D3D9ConstantBuffer::AllocSlice() {
if (unlikely(m_buffer == nullptr))
this->createBuffer();
m_slice = m_buffer->allocSlice();
m_device->EmitCs([
cBuffer = m_buffer,
cSlice = m_slice
] (DxvkContext* ctx) {
ctx->invalidateBuffer(cBuffer, cSlice);
});
return m_slice.mapPtr;
}
void D3D9ConstantBuffer::createBuffer() {
auto options = m_device->GetOptions();
// Buffer usage and access flags don't make much of a difference
// in the backend, so set both STORAGE and UNIFORM usage/access.
DxvkBufferCreateInfo bufferInfo;
bufferInfo.size = align(m_size, m_align);
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
bufferInfo.access = VK_ACCESS_UNIFORM_READ_BIT
| VK_ACCESS_SHADER_READ_BIT;
bufferInfo.stages = util::pipelineStages(m_stages);
VkMemoryPropertyFlags memoryFlags
= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
if (options->deviceLocalConstantBuffers)
memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
m_buffer = m_device->GetDXVKDevice()->createBuffer(bufferInfo, memoryFlags);
m_device->EmitCs([
cStages = m_stages,
cBinding = m_binding,
cSlice = DxvkBufferSlice(m_buffer)
] (DxvkContext* ctx) {
ctx->bindResourceBuffer(cStages, cBinding, cSlice);
});
}
VkDeviceSize D3D9ConstantBuffer::getAlignment(const Rc<DxvkDevice>& device) const {
return std::max(std::max(
device->properties().core.properties.limits.minUniformBufferOffsetAlignment,
device->properties().core.properties.limits.minStorageBufferOffsetAlignment),
device->properties().extRobustness2.robustUniformBufferAccessSizeAlignment);
}
}

View File

@ -0,0 +1,77 @@
#pragma once
#include "../dxvk/dxvk_buffer.h"
#include "../dxso/dxso_util.h"
#include "../util/util_math.h"
#include "d3d9_include.h"
namespace dxvk {
class D3D9DeviceEx;
/**
* \brief Constant buffer
*/
class D3D9ConstantBuffer {
public:
D3D9ConstantBuffer();
D3D9ConstantBuffer(
D3D9DeviceEx* pDevice,
DxsoProgramType ShaderStage,
DxsoConstantBuffers BufferType,
VkDeviceSize Size);
~D3D9ConstantBuffer();
/**
* \brief Queries alignment
*
* Useful to pad copies with initialized data.
* \returns Data alignment
*/
VkDeviceSize GetAlignment() const {
return m_align;
}
/**
* \brief Allocates a given amount of memory
*
* \param [in] size Number of bytes to allocate
* \returns Map pointer of the allocated region
*/
void* Alloc(VkDeviceSize size);
/**
* \brief Allocates a full buffer slice
*
* This must not be called if \ref Alloc is used.
* \returns Map pointer of the allocated region
*/
void* AllocSlice();
private:
D3D9DeviceEx* m_device = nullptr;
uint32_t m_binding = 0u;
VkShaderStageFlags m_stages = 0u;
VkDeviceSize m_size = 0ull;
VkDeviceSize m_align = 0ull;
VkDeviceSize m_offset = 0ull;
Rc<DxvkBuffer> m_buffer = nullptr;
DxvkBufferSliceHandle m_slice = { };
void createBuffer();
VkDeviceSize getAlignment(const Rc<DxvkDevice>& device) const;
};
}

View File

@ -8,6 +8,7 @@
#include "d3d9_format.h"
#include "d3d9_multithread.h"
#include "d3d9_adapter.h"
#include "d3d9_constant_buffer.h"
#include "d3d9_constant_set.h"
#include "d3d9_state.h"
@ -99,6 +100,7 @@ namespace dxvk {
constexpr static uint32_t NullStreamIdx = caps::MaxStreams;
friend class D3D9SwapChainEx;
friend class D3D9ConstantBuffer;
friend class D3D9UserDefinedAnnotation;
public:

View File

@ -20,6 +20,7 @@ d3d9_src = [
'd3d9_swapchain.cpp',
'd3d9_format.cpp',
'd3d9_common_texture.cpp',
'd3d9_constant_buffer.cpp',
'd3d9_texture.cpp',
'd3d9_surface.cpp',
'd3d9_volume.cpp',