mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-18 22:54:15 +01:00
[dxvk] Introduce concept of shader constants
Large constant arrays should be moved to a uniform buffer instead of being baked directly into the shader code.
This commit is contained in:
parent
a8eb7d343a
commit
c31e646921
@ -2557,11 +2557,24 @@ namespace dxvk {
|
||||
void D3D11DeviceContext::BindShader(
|
||||
DxbcProgramType ShaderStage,
|
||||
const D3D11CommonShader* pShaderModule) {
|
||||
// Bind the shader and the ICB at once
|
||||
const uint32_t slotId = computeResourceSlotId(
|
||||
ShaderStage, DxbcBindingType::ConstantBuffer,
|
||||
D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
|
||||
|
||||
EmitCs([
|
||||
cSlotId = slotId,
|
||||
cStage = GetShaderStage(ShaderStage),
|
||||
cShader = pShaderModule != nullptr ? pShaderModule->GetShader() : nullptr
|
||||
cSlice = pShaderModule != nullptr
|
||||
&& pShaderModule->GetIcb() != nullptr
|
||||
? DxvkBufferSlice(pShaderModule->GetIcb())
|
||||
: DxvkBufferSlice(),
|
||||
cShader = pShaderModule != nullptr
|
||||
? pShaderModule->GetShader()
|
||||
: nullptr
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->bindShader(cStage, cShader);
|
||||
ctx->bindShader (cStage, cShader);
|
||||
ctx->bindResourceBuffer(cSlotId, cSlice);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1862,7 +1862,7 @@ namespace dxvk {
|
||||
Logger::warn("D3D11Device::CreateShaderModule: Class linkage not supported");
|
||||
|
||||
try {
|
||||
*pShaderModule = m_shaderModules.GetShaderModule(
|
||||
*pShaderModule = m_shaderModules.GetShaderModule(this,
|
||||
pModuleInfo, pShaderBytecode, BytecodeLength, ProgramType);
|
||||
return S_OK;
|
||||
} catch (const DxvkError& e) {
|
||||
|
@ -39,6 +39,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
D3D11CommonShader::D3D11CommonShader(
|
||||
D3D11Device* pDevice,
|
||||
const D3D11ShaderKey* pShaderKey,
|
||||
const DxbcModuleInfo* pDxbcModuleInfo,
|
||||
const void* pShaderBytecode,
|
||||
@ -92,6 +93,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
D3D11CommonShader D3D11ShaderModuleSet::GetShaderModule(
|
||||
D3D11Device* pDevice,
|
||||
const DxbcModuleInfo* pDxbcModuleInfo,
|
||||
const void* pShaderBytecode,
|
||||
size_t BytecodeLength,
|
||||
@ -108,7 +110,8 @@ namespace dxvk {
|
||||
|
||||
// This shader has not been compiled yet, so we have to create a
|
||||
// new module. This takes a while, so we won't lock the structure.
|
||||
D3D11CommonShader module(&key, pDxbcModuleInfo, pShaderBytecode, BytecodeLength);
|
||||
D3D11CommonShader module(pDevice, &key,
|
||||
pDxbcModuleInfo, pShaderBytecode, BytecodeLength);
|
||||
|
||||
// Insert the new module into the lookup table. If another thread
|
||||
// has compiled the same shader in the meantime, we should return
|
||||
|
@ -69,17 +69,20 @@ namespace dxvk {
|
||||
|
||||
D3D11CommonShader();
|
||||
D3D11CommonShader(
|
||||
D3D11Device* pDevice,
|
||||
const D3D11ShaderKey* pShaderKey,
|
||||
const DxbcModuleInfo* pDxbcModuleInfo,
|
||||
const void* pShaderBytecode,
|
||||
size_t BytecodeLength);
|
||||
~D3D11CommonShader();
|
||||
|
||||
DxbcProgramType GetProgramType() const;
|
||||
|
||||
Rc<DxvkShader> GetShader() const {
|
||||
return m_shader;
|
||||
}
|
||||
|
||||
Rc<DxvkBuffer> GetIcb() const {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
std::string GetName() const {
|
||||
return m_name;
|
||||
@ -89,6 +92,7 @@ namespace dxvk {
|
||||
|
||||
std::string m_name;
|
||||
Rc<DxvkShader> m_shader;
|
||||
Rc<DxvkBuffer> m_buffer;
|
||||
|
||||
};
|
||||
|
||||
@ -163,6 +167,7 @@ namespace dxvk {
|
||||
~D3D11ShaderModuleSet();
|
||||
|
||||
D3D11CommonShader GetShaderModule(
|
||||
D3D11Device* pDevice,
|
||||
const DxbcModuleInfo* pDxbcModuleInfo,
|
||||
const void* pShaderBytecode,
|
||||
size_t BytecodeLength,
|
||||
|
@ -205,7 +205,8 @@ namespace dxvk {
|
||||
m_resourceSlots.size(),
|
||||
m_resourceSlots.data(),
|
||||
m_interfaceSlots,
|
||||
m_module.compile());
|
||||
m_module.compile(),
|
||||
DxvkShaderConstData());
|
||||
}
|
||||
|
||||
|
||||
|
@ -190,7 +190,8 @@ namespace dxvk {
|
||||
const DxvkInterfaceSlots& iface,
|
||||
const SpirvCodeBuffer& code) {
|
||||
return new DxvkShader(stage,
|
||||
slotCount, slotInfos, iface, code);
|
||||
slotCount, slotInfos, iface,
|
||||
code, DxvkShaderConstData());
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,6 +2,42 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkShaderConstData::DxvkShaderConstData() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderConstData::DxvkShaderConstData(
|
||||
size_t dwordCount,
|
||||
const uint32_t* dwordArray)
|
||||
: m_size(dwordCount), m_data(new uint32_t[dwordCount]) {
|
||||
for (size_t i = 0; i < dwordCount; i++)
|
||||
m_data[i] = dwordArray[i];
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderConstData::DxvkShaderConstData(DxvkShaderConstData&& other)
|
||||
: m_size(other.m_size), m_data(other.m_data) {
|
||||
other.m_size = 0;
|
||||
other.m_data = nullptr;
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderConstData& DxvkShaderConstData::operator = (DxvkShaderConstData&& other) {
|
||||
delete[] m_data;
|
||||
this->m_size = other.m_size;
|
||||
this->m_data = other.m_data;
|
||||
other.m_size = 0;
|
||||
other.m_data = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderConstData::~DxvkShaderConstData() {
|
||||
delete[] m_data;
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderModule::DxvkShaderModule(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkShader>& shader,
|
||||
@ -44,8 +80,10 @@ namespace dxvk {
|
||||
uint32_t slotCount,
|
||||
const DxvkResourceSlot* slotInfos,
|
||||
const DxvkInterfaceSlots& iface,
|
||||
const SpirvCodeBuffer& code)
|
||||
: m_stage(stage), m_code(code), m_interface(iface) {
|
||||
const SpirvCodeBuffer& code,
|
||||
DxvkShaderConstData&& constData)
|
||||
: m_stage(stage), m_code(code), m_interface(iface),
|
||||
m_constData(std::move(constData)) {
|
||||
// Write back resource slot infos
|
||||
for (uint32_t i = 0; i < slotCount; i++)
|
||||
m_slots.push_back(slotInfos[i]);
|
||||
|
@ -38,6 +38,45 @@ namespace dxvk {
|
||||
uint32_t inputSlots = 0;
|
||||
uint32_t outputSlots = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Shader constants
|
||||
*
|
||||
* Each shader can have constant data associated
|
||||
* with it, which needs to be copied to a uniform
|
||||
* buffer. The client API must then bind that buffer
|
||||
* to an API-specific buffer binding when using the
|
||||
* shader for rendering.
|
||||
*/
|
||||
class DxvkShaderConstData {
|
||||
|
||||
public:
|
||||
|
||||
DxvkShaderConstData();
|
||||
DxvkShaderConstData(
|
||||
size_t dwordCount,
|
||||
const uint32_t* dwordArray);
|
||||
|
||||
DxvkShaderConstData (DxvkShaderConstData&& other);
|
||||
DxvkShaderConstData& operator = (DxvkShaderConstData&& other);
|
||||
|
||||
~DxvkShaderConstData();
|
||||
|
||||
const uint32_t* data() const {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
size_t sizeInBytes() const {
|
||||
return m_size * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
size_t m_size = 0;
|
||||
uint32_t* m_data = nullptr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@ -110,7 +149,8 @@ namespace dxvk {
|
||||
uint32_t slotCount,
|
||||
const DxvkResourceSlot* slotInfos,
|
||||
const DxvkInterfaceSlots& iface,
|
||||
const SpirvCodeBuffer& code);
|
||||
const SpirvCodeBuffer& code,
|
||||
DxvkShaderConstData&& constData);
|
||||
|
||||
~DxvkShader();
|
||||
|
||||
@ -166,6 +206,18 @@ namespace dxvk {
|
||||
DxvkInterfaceSlots interfaceSlots() const {
|
||||
return m_interface;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Shader constant data
|
||||
*
|
||||
* Returns a read-only reference to the
|
||||
* constant data associated with this
|
||||
* shader object.
|
||||
* \returns Shader constant data
|
||||
*/
|
||||
const DxvkShaderConstData& shaderConstants() const {
|
||||
return m_constData;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Dumps SPIR-V shader
|
||||
@ -210,6 +262,7 @@ namespace dxvk {
|
||||
std::vector<DxvkResourceSlot> m_slots;
|
||||
std::vector<size_t> m_idOffsets;
|
||||
DxvkInterfaceSlots m_interface;
|
||||
DxvkShaderConstData m_constData;
|
||||
std::string m_debugName;
|
||||
|
||||
};
|
||||
|
@ -190,7 +190,7 @@ namespace dxvk::hud {
|
||||
{ 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_IMAGE_VIEW_TYPE_MAX_ENUM },
|
||||
}};
|
||||
|
||||
return new DxvkShader(
|
||||
return device->createShader(
|
||||
VK_SHADER_STAGE_VERTEX_BIT,
|
||||
resourceSlots.size(),
|
||||
resourceSlots.data(),
|
||||
@ -208,7 +208,7 @@ namespace dxvk::hud {
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_IMAGE_VIEW_TYPE_2D },
|
||||
}};
|
||||
|
||||
return new DxvkShader(
|
||||
return device->createShader(
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
resourceSlots.size(),
|
||||
resourceSlots.data(),
|
||||
@ -220,7 +220,7 @@ namespace dxvk::hud {
|
||||
Rc<DxvkShader> HudRenderer::createLineShader(const Rc<DxvkDevice>& device) {
|
||||
const SpirvCodeBuffer codeBuffer(hud_line);
|
||||
|
||||
return new DxvkShader(
|
||||
return device->createShader(
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
0, nullptr, { 0x2, 0x1 },
|
||||
codeBuffer);
|
||||
|
Loading…
x
Reference in New Issue
Block a user