mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +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(
|
void D3D11DeviceContext::BindShader(
|
||||||
DxbcProgramType ShaderStage,
|
DxbcProgramType ShaderStage,
|
||||||
const D3D11CommonShader* pShaderModule) {
|
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([
|
EmitCs([
|
||||||
|
cSlotId = slotId,
|
||||||
cStage = GetShaderStage(ShaderStage),
|
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) {
|
] (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");
|
Logger::warn("D3D11Device::CreateShaderModule: Class linkage not supported");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
*pShaderModule = m_shaderModules.GetShaderModule(
|
*pShaderModule = m_shaderModules.GetShaderModule(this,
|
||||||
pModuleInfo, pShaderBytecode, BytecodeLength, ProgramType);
|
pModuleInfo, pShaderBytecode, BytecodeLength, ProgramType);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
} catch (const DxvkError& e) {
|
} catch (const DxvkError& e) {
|
||||||
|
@ -39,6 +39,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
D3D11CommonShader::D3D11CommonShader(
|
D3D11CommonShader::D3D11CommonShader(
|
||||||
|
D3D11Device* pDevice,
|
||||||
const D3D11ShaderKey* pShaderKey,
|
const D3D11ShaderKey* pShaderKey,
|
||||||
const DxbcModuleInfo* pDxbcModuleInfo,
|
const DxbcModuleInfo* pDxbcModuleInfo,
|
||||||
const void* pShaderBytecode,
|
const void* pShaderBytecode,
|
||||||
@ -92,6 +93,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
D3D11CommonShader D3D11ShaderModuleSet::GetShaderModule(
|
D3D11CommonShader D3D11ShaderModuleSet::GetShaderModule(
|
||||||
|
D3D11Device* pDevice,
|
||||||
const DxbcModuleInfo* pDxbcModuleInfo,
|
const DxbcModuleInfo* pDxbcModuleInfo,
|
||||||
const void* pShaderBytecode,
|
const void* pShaderBytecode,
|
||||||
size_t BytecodeLength,
|
size_t BytecodeLength,
|
||||||
@ -108,7 +110,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
// This shader has not been compiled yet, so we have to create a
|
// 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.
|
// 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
|
// Insert the new module into the lookup table. If another thread
|
||||||
// has compiled the same shader in the meantime, we should return
|
// has compiled the same shader in the meantime, we should return
|
||||||
|
@ -69,17 +69,20 @@ namespace dxvk {
|
|||||||
|
|
||||||
D3D11CommonShader();
|
D3D11CommonShader();
|
||||||
D3D11CommonShader(
|
D3D11CommonShader(
|
||||||
|
D3D11Device* pDevice,
|
||||||
const D3D11ShaderKey* pShaderKey,
|
const D3D11ShaderKey* pShaderKey,
|
||||||
const DxbcModuleInfo* pDxbcModuleInfo,
|
const DxbcModuleInfo* pDxbcModuleInfo,
|
||||||
const void* pShaderBytecode,
|
const void* pShaderBytecode,
|
||||||
size_t BytecodeLength);
|
size_t BytecodeLength);
|
||||||
~D3D11CommonShader();
|
~D3D11CommonShader();
|
||||||
|
|
||||||
DxbcProgramType GetProgramType() const;
|
|
||||||
|
|
||||||
Rc<DxvkShader> GetShader() const {
|
Rc<DxvkShader> GetShader() const {
|
||||||
return m_shader;
|
return m_shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rc<DxvkBuffer> GetIcb() const {
|
||||||
|
return m_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetName() const {
|
std::string GetName() const {
|
||||||
return m_name;
|
return m_name;
|
||||||
@ -89,6 +92,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
Rc<DxvkShader> m_shader;
|
Rc<DxvkShader> m_shader;
|
||||||
|
Rc<DxvkBuffer> m_buffer;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -163,6 +167,7 @@ namespace dxvk {
|
|||||||
~D3D11ShaderModuleSet();
|
~D3D11ShaderModuleSet();
|
||||||
|
|
||||||
D3D11CommonShader GetShaderModule(
|
D3D11CommonShader GetShaderModule(
|
||||||
|
D3D11Device* pDevice,
|
||||||
const DxbcModuleInfo* pDxbcModuleInfo,
|
const DxbcModuleInfo* pDxbcModuleInfo,
|
||||||
const void* pShaderBytecode,
|
const void* pShaderBytecode,
|
||||||
size_t BytecodeLength,
|
size_t BytecodeLength,
|
||||||
|
@ -205,7 +205,8 @@ namespace dxvk {
|
|||||||
m_resourceSlots.size(),
|
m_resourceSlots.size(),
|
||||||
m_resourceSlots.data(),
|
m_resourceSlots.data(),
|
||||||
m_interfaceSlots,
|
m_interfaceSlots,
|
||||||
m_module.compile());
|
m_module.compile(),
|
||||||
|
DxvkShaderConstData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,7 +190,8 @@ namespace dxvk {
|
|||||||
const DxvkInterfaceSlots& iface,
|
const DxvkInterfaceSlots& iface,
|
||||||
const SpirvCodeBuffer& code) {
|
const SpirvCodeBuffer& code) {
|
||||||
return new DxvkShader(stage,
|
return new DxvkShader(stage,
|
||||||
slotCount, slotInfos, iface, code);
|
slotCount, slotInfos, iface,
|
||||||
|
code, DxvkShaderConstData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,6 +2,42 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
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(
|
DxvkShaderModule::DxvkShaderModule(
|
||||||
const Rc<vk::DeviceFn>& vkd,
|
const Rc<vk::DeviceFn>& vkd,
|
||||||
const Rc<DxvkShader>& shader,
|
const Rc<DxvkShader>& shader,
|
||||||
@ -44,8 +80,10 @@ namespace dxvk {
|
|||||||
uint32_t slotCount,
|
uint32_t slotCount,
|
||||||
const DxvkResourceSlot* slotInfos,
|
const DxvkResourceSlot* slotInfos,
|
||||||
const DxvkInterfaceSlots& iface,
|
const DxvkInterfaceSlots& iface,
|
||||||
const SpirvCodeBuffer& code)
|
const SpirvCodeBuffer& code,
|
||||||
: m_stage(stage), m_code(code), m_interface(iface) {
|
DxvkShaderConstData&& constData)
|
||||||
|
: m_stage(stage), m_code(code), m_interface(iface),
|
||||||
|
m_constData(std::move(constData)) {
|
||||||
// Write back resource slot infos
|
// Write back resource slot infos
|
||||||
for (uint32_t i = 0; i < slotCount; i++)
|
for (uint32_t i = 0; i < slotCount; i++)
|
||||||
m_slots.push_back(slotInfos[i]);
|
m_slots.push_back(slotInfos[i]);
|
||||||
|
@ -38,6 +38,45 @@ namespace dxvk {
|
|||||||
uint32_t inputSlots = 0;
|
uint32_t inputSlots = 0;
|
||||||
uint32_t outputSlots = 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,
|
uint32_t slotCount,
|
||||||
const DxvkResourceSlot* slotInfos,
|
const DxvkResourceSlot* slotInfos,
|
||||||
const DxvkInterfaceSlots& iface,
|
const DxvkInterfaceSlots& iface,
|
||||||
const SpirvCodeBuffer& code);
|
const SpirvCodeBuffer& code,
|
||||||
|
DxvkShaderConstData&& constData);
|
||||||
|
|
||||||
~DxvkShader();
|
~DxvkShader();
|
||||||
|
|
||||||
@ -166,6 +206,18 @@ namespace dxvk {
|
|||||||
DxvkInterfaceSlots interfaceSlots() const {
|
DxvkInterfaceSlots interfaceSlots() const {
|
||||||
return m_interface;
|
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
|
* \brief Dumps SPIR-V shader
|
||||||
@ -210,6 +262,7 @@ namespace dxvk {
|
|||||||
std::vector<DxvkResourceSlot> m_slots;
|
std::vector<DxvkResourceSlot> m_slots;
|
||||||
std::vector<size_t> m_idOffsets;
|
std::vector<size_t> m_idOffsets;
|
||||||
DxvkInterfaceSlots m_interface;
|
DxvkInterfaceSlots m_interface;
|
||||||
|
DxvkShaderConstData m_constData;
|
||||||
std::string m_debugName;
|
std::string m_debugName;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -190,7 +190,7 @@ namespace dxvk::hud {
|
|||||||
{ 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_IMAGE_VIEW_TYPE_MAX_ENUM },
|
{ 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_IMAGE_VIEW_TYPE_MAX_ENUM },
|
||||||
}};
|
}};
|
||||||
|
|
||||||
return new DxvkShader(
|
return device->createShader(
|
||||||
VK_SHADER_STAGE_VERTEX_BIT,
|
VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
resourceSlots.size(),
|
resourceSlots.size(),
|
||||||
resourceSlots.data(),
|
resourceSlots.data(),
|
||||||
@ -208,7 +208,7 @@ namespace dxvk::hud {
|
|||||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_IMAGE_VIEW_TYPE_2D },
|
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_IMAGE_VIEW_TYPE_2D },
|
||||||
}};
|
}};
|
||||||
|
|
||||||
return new DxvkShader(
|
return device->createShader(
|
||||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
resourceSlots.size(),
|
resourceSlots.size(),
|
||||||
resourceSlots.data(),
|
resourceSlots.data(),
|
||||||
@ -220,7 +220,7 @@ namespace dxvk::hud {
|
|||||||
Rc<DxvkShader> HudRenderer::createLineShader(const Rc<DxvkDevice>& device) {
|
Rc<DxvkShader> HudRenderer::createLineShader(const Rc<DxvkDevice>& device) {
|
||||||
const SpirvCodeBuffer codeBuffer(hud_line);
|
const SpirvCodeBuffer codeBuffer(hud_line);
|
||||||
|
|
||||||
return new DxvkShader(
|
return device->createShader(
|
||||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
0, nullptr, { 0x2, 0x1 },
|
0, nullptr, { 0x2, 0x1 },
|
||||||
codeBuffer);
|
codeBuffer);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user