1
0
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:
Philip Rebohle 2018-07-30 20:15:19 +02:00
parent a8eb7d343a
commit c31e646921
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
9 changed files with 128 additions and 14 deletions

View File

@ -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);
});
}

View File

@ -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) {

View File

@ -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

View File

@ -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,

View File

@ -205,7 +205,8 @@ namespace dxvk {
m_resourceSlots.size(),
m_resourceSlots.data(),
m_interfaceSlots,
m_module.compile());
m_module.compile(),
DxvkShaderConstData());
}

View File

@ -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());
}

View File

@ -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]);

View File

@ -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;
};

View File

@ -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);