mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-19 05:52:11 +01:00
[dxbc] Implemented proper resource slot mapping
This commit is contained in:
parent
feab720ddb
commit
c90bc3e946
@ -3,6 +3,8 @@
|
||||
#include "d3d11_context.h"
|
||||
#include "d3d11_device.h"
|
||||
|
||||
#include "../dxbc/dxbc_util.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
D3D11DeviceContext::D3D11DeviceContext(
|
||||
@ -638,6 +640,7 @@ namespace dxvk {
|
||||
switch (binding.format) {
|
||||
case DXGI_FORMAT_R16_UINT: indexType = VK_INDEX_TYPE_UINT16; break;
|
||||
case DXGI_FORMAT_R32_UINT: indexType = VK_INDEX_TYPE_UINT32; break;
|
||||
default: Logger::err(str::format("D3D11: Invalid index format: ", binding.format));
|
||||
}
|
||||
|
||||
m_context->bindIndexBuffer(
|
||||
@ -696,7 +699,7 @@ namespace dxvk {
|
||||
UINT NumBuffers,
|
||||
ID3D11Buffer* const* ppConstantBuffers) {
|
||||
this->BindConstantBuffers(
|
||||
D3D11ShaderStage::VertexShader,
|
||||
DxbcProgramType::VertexShader,
|
||||
&m_state.vs.constantBuffers,
|
||||
StartSlot, NumBuffers,
|
||||
ppConstantBuffers);
|
||||
@ -966,7 +969,7 @@ namespace dxvk {
|
||||
UINT NumBuffers,
|
||||
ID3D11Buffer* const* ppConstantBuffers) {
|
||||
this->BindConstantBuffers(
|
||||
D3D11ShaderStage::PixelShader,
|
||||
DxbcProgramType::PixelShader,
|
||||
&m_state.vs.constantBuffers,
|
||||
StartSlot, NumBuffers,
|
||||
ppConstantBuffers);
|
||||
@ -1329,7 +1332,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
void D3D11DeviceContext::BindConstantBuffers(
|
||||
D3D11ShaderStage ShaderStage,
|
||||
DxbcProgramType ShaderStage,
|
||||
D3D11ConstantBufferBindings* pBindings,
|
||||
UINT StartSlot,
|
||||
UINT NumBuffers,
|
||||
@ -1343,18 +1346,25 @@ namespace dxvk {
|
||||
if (pBindings->at(StartSlot + i) != buffer) {
|
||||
pBindings->at(StartSlot + i) = buffer;
|
||||
|
||||
DxvkBufferBinding dxvkBinding;
|
||||
DxvkBufferBinding bindingInfo;
|
||||
|
||||
if (buffer != nullptr) {
|
||||
dxvkBinding = DxvkBufferBinding(
|
||||
bindingInfo = DxvkBufferBinding(
|
||||
buffer->GetDXVKBuffer(),
|
||||
0, VK_WHOLE_SIZE);
|
||||
}
|
||||
|
||||
// TODO compute actual slot index
|
||||
VkPipelineBindPoint bindPoint
|
||||
= ShaderStage == DxbcProgramType::ComputeShader
|
||||
? VK_PIPELINE_BIND_POINT_COMPUTE
|
||||
: VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
|
||||
uint32_t slotId = computeResourceSlotId(
|
||||
ShaderStage, DxbcBindingType::ConstantBuffer,
|
||||
StartSlot + i);
|
||||
|
||||
m_context->bindResourceBuffer(
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS, 0,
|
||||
dxvkBinding);
|
||||
bindPoint, slotId, bindingInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1369,8 +1379,9 @@ namespace dxvk {
|
||||
std::array<VkViewport, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> viewports;
|
||||
std::array<VkRect2D, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> scissors;
|
||||
|
||||
// FIXME compute proper viewport coordinates (vertical origin).
|
||||
// D3D11's coordinate system has its origin in the bottom left.
|
||||
// D3D11's coordinate system has its origin in the bottom left,
|
||||
// but the viewport coordinates are aligned to the top-left
|
||||
// corner so we can get away with flipping the viewport.
|
||||
for (uint32_t i = 0; i < m_state.rs.numViewports; i++) {
|
||||
const D3D11_VIEWPORT& vp = m_state.rs.viewports.at(i);
|
||||
|
||||
@ -1396,7 +1407,6 @@ namespace dxvk {
|
||||
// TODO D3D11 docs aren't clear about what should happen
|
||||
// when there are undefined scissor rects for a viewport.
|
||||
// Figure out what it does on Windows.
|
||||
// FIXME Compute correct vertical position
|
||||
if (enableScissorTest && (i < m_state.rs.numScissors)) {
|
||||
const D3D11_RECT& sr = m_state.rs.scissors.at(i);
|
||||
|
||||
|
@ -555,7 +555,7 @@ namespace dxvk {
|
||||
D3D11ContextState m_state;
|
||||
|
||||
void BindConstantBuffers(
|
||||
D3D11ShaderStage ShaderStage,
|
||||
DxbcProgramType ShaderStage,
|
||||
D3D11ConstantBufferBindings* pBindings,
|
||||
UINT StartSlot,
|
||||
UINT NumBuffers,
|
||||
|
@ -10,15 +10,6 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
enum class D3D11ShaderStage {
|
||||
VertexShader = 0,
|
||||
HullShader = 1,
|
||||
DomainShader = 2,
|
||||
GeometryShader = 3,
|
||||
PixelShader = 4,
|
||||
ComputeShader = 5,
|
||||
};
|
||||
|
||||
using D3D11ConstantBufferBindings = std::array<
|
||||
Com<D3D11Buffer>, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT>;
|
||||
|
||||
|
44
src/dxbc/dxbc_util.cpp
Normal file
44
src/dxbc/dxbc_util.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "dxbc_util.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
uint32_t computeResourceSlotId(
|
||||
DxbcProgramType shaderStage,
|
||||
DxbcBindingType bindingType,
|
||||
uint32_t bindingIndex) {
|
||||
if (shaderStage == DxbcProgramType::ComputeShader) {
|
||||
// 0 - 13: Constant buffers
|
||||
// 14 - 29: Samplers
|
||||
// 30 - 157: Shader resources
|
||||
// 158 - 221: Uniform access views
|
||||
switch (bindingType) {
|
||||
case DxbcBindingType::ConstantBuffer: return bindingIndex + 0;
|
||||
case DxbcBindingType::ImageSampler: return bindingIndex + 14;
|
||||
case DxbcBindingType::ShaderResource: return bindingIndex + 30;
|
||||
case DxbcBindingType::UnorderedAccessView:return bindingIndex + 158;
|
||||
default: Logger::err("computeResourceSlotId: Invalid resource type");
|
||||
}
|
||||
} else {
|
||||
// Global resource slots
|
||||
// 0 - 7: Uniform access views
|
||||
// 8 - 11: Stream output buffers
|
||||
// Per-stage resource slots:
|
||||
// 0 - 13: Constant buffers
|
||||
// 14 - 29: Samplers
|
||||
// 30 - 157: Shader resources
|
||||
const uint32_t stageOffset = 12 + 158 * static_cast<uint32_t>(shaderStage);
|
||||
|
||||
switch (bindingType) {
|
||||
case DxbcBindingType::UnorderedAccessView:return bindingIndex + 0;
|
||||
case DxbcBindingType::StreamOutputBuffer: return bindingIndex + 8;
|
||||
case DxbcBindingType::ConstantBuffer: return bindingIndex + stageOffset + 0;
|
||||
case DxbcBindingType::ImageSampler: return bindingIndex + stageOffset + 14;
|
||||
case DxbcBindingType::ShaderResource: return bindingIndex + stageOffset + 30;
|
||||
default: Logger::err("computeResourceSlotId: Invalid resource type");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
35
src/dxbc/dxbc_util.h
Normal file
35
src/dxbc/dxbc_util.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxbc_common.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Resource type
|
||||
*
|
||||
* The type of a shader resource. Used
|
||||
* to determine the DXVK resource slot.
|
||||
*/
|
||||
enum DxbcBindingType : uint32_t {
|
||||
ConstantBuffer = 0,
|
||||
ShaderResource = 1,
|
||||
ImageSampler = 2,
|
||||
UnorderedAccessView = 3,
|
||||
StreamOutputBuffer = 4,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Computes the DXVK resource slot for a binding
|
||||
*
|
||||
* \param [in] shaderStage The target shader stage
|
||||
* \param [in] bindingType Type of the resource
|
||||
* \param [in] bindingIndex Resource binding index
|
||||
* \returns DXVK resource slot index
|
||||
*/
|
||||
uint32_t computeResourceSlotId(
|
||||
DxbcProgramType shaderStage,
|
||||
DxbcBindingType bindingType,
|
||||
uint32_t bindingIndex);
|
||||
|
||||
}
|
@ -6,7 +6,8 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxbcCodeGen::DxbcCodeGen() {
|
||||
DxbcCodeGen::DxbcCodeGen(DxbcProgramType shaderStage)
|
||||
: m_shaderStage(shaderStage) {
|
||||
m_module.setMemoryModel(
|
||||
spv::AddressingModelLogical,
|
||||
spv::MemoryModelGLSL450);
|
||||
@ -52,14 +53,20 @@ namespace dxvk {
|
||||
m_module.defPointerType(structType, spv::StorageClassUniform),
|
||||
spv::StorageClassUniform);
|
||||
|
||||
uint32_t bindingId = computeResourceSlotId(m_shaderStage,
|
||||
DxbcBindingType::ConstantBuffer, bufferId);
|
||||
|
||||
m_module.setDebugName(varIndex, str::format("cb", bufferId).c_str());
|
||||
m_module.decorateDescriptorSet(varIndex, 0);
|
||||
m_module.decorateBinding(varIndex, 0);
|
||||
m_module.decorateBinding(varIndex, bindingId);
|
||||
m_constantBuffers.at(bufferId).varId = varIndex;
|
||||
m_constantBuffers.at(bufferId).size = elementCount;
|
||||
|
||||
// TODO compute resource slot index
|
||||
m_resourceSlots.push_back({ 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER });
|
||||
DxvkResourceSlot resource;
|
||||
resource.slot = bindingId;
|
||||
resource.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
m_resourceSlots.push_back(resource);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "../dxbc_common.h"
|
||||
#include "../dxbc_decoder.h"
|
||||
#include "../dxbc_type.h"
|
||||
#include "../dxbc_util.h"
|
||||
|
||||
#include "../../spirv/spirv_module.h"
|
||||
|
||||
@ -46,7 +47,7 @@ namespace dxvk {
|
||||
|
||||
public:
|
||||
|
||||
DxbcCodeGen();
|
||||
DxbcCodeGen(DxbcProgramType shaderStage);
|
||||
|
||||
virtual ~DxbcCodeGen();
|
||||
|
||||
@ -149,6 +150,8 @@ namespace dxvk {
|
||||
constexpr static uint32_t PerVertex_CullDist = 2;
|
||||
constexpr static uint32_t PerVertex_ClipDist = 3;
|
||||
|
||||
const DxbcProgramType m_shaderStage;
|
||||
|
||||
SpirvModule m_module;
|
||||
|
||||
std::vector<uint32_t> m_entryPointInterfaces;
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxbcPsCodeGen::DxbcPsCodeGen(
|
||||
const Rc<DxbcIsgn>& osgn) {
|
||||
DxbcPsCodeGen::DxbcPsCodeGen(const Rc<DxbcIsgn>& osgn)
|
||||
: DxbcCodeGen(DxbcProgramType::PixelShader) {
|
||||
m_module.enableCapability(spv::CapabilityShader);
|
||||
m_module.enableCapability(spv::CapabilityCullDistance);
|
||||
m_module.enableCapability(spv::CapabilityClipDistance);
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxbcVsCodeGen::DxbcVsCodeGen(const Rc<DxbcIsgn>& isgn) {
|
||||
DxbcVsCodeGen::DxbcVsCodeGen(const Rc<DxbcIsgn>& isgn)
|
||||
: DxbcCodeGen(DxbcProgramType::VertexShader) {
|
||||
m_module.enableCapability(spv::CapabilityShader);
|
||||
m_module.enableCapability(spv::CapabilityCullDistance);
|
||||
m_module.enableCapability(spv::CapabilityClipDistance);
|
||||
|
@ -9,6 +9,7 @@ dxbc_src = files([
|
||||
'dxbc_names.cpp',
|
||||
'dxbc_reader.cpp',
|
||||
'dxbc_type.cpp',
|
||||
'dxbc_util.cpp',
|
||||
|
||||
'gen/dxbc_gen_common.cpp',
|
||||
'gen/dxbc_gen_pixel.cpp',
|
||||
|
@ -330,8 +330,8 @@ namespace dxvk {
|
||||
DxvkContextState m_state;
|
||||
DxvkBarrierSet m_barriers;
|
||||
|
||||
DxvkShaderResourceSlots m_cResources = { 1024 };
|
||||
DxvkShaderResourceSlots m_gResources = { 4096 };
|
||||
DxvkShaderResourceSlots m_cResources = { 256 };
|
||||
DxvkShaderResourceSlots m_gResources = { 1024 };
|
||||
|
||||
void renderPassBegin();
|
||||
void renderPassEnd();
|
||||
|
@ -26,7 +26,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
uint32_t DxvkDescriptorSlotMapping::getBindingId(uint32_t slot) {
|
||||
uint32_t DxvkDescriptorSlotMapping::getBindingId(uint32_t slot) const {
|
||||
// This won't win a performance competition, but the number
|
||||
// of bindings used by a shader is usually much smaller than
|
||||
// the number of resource slots available to the system.
|
||||
|
@ -74,7 +74,7 @@ namespace dxvk {
|
||||
* \returns Binding index, or \c InvalidBinding
|
||||
*/
|
||||
uint32_t getBindingId(
|
||||
uint32_t slot);
|
||||
uint32_t slot) const;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -66,8 +66,21 @@ namespace dxvk {
|
||||
Rc<DxvkShaderModule> DxvkShader::createShaderModule(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const DxvkDescriptorSlotMapping& mapping) const {
|
||||
// TODO apply mapping
|
||||
return new DxvkShaderModule(vkd, m_stage, m_code);
|
||||
// Iterate over the code and replace every resource slot
|
||||
// index with the corresponding mapped binding index.
|
||||
SpirvCodeBuffer spirvCode = m_code;
|
||||
|
||||
for (auto ins : spirvCode) {
|
||||
if (ins.opCode() == spv::OpDecorate
|
||||
&& ins.arg(2) == spv::DecorationBinding) {
|
||||
|
||||
const uint32_t oldBinding = ins.arg(3);
|
||||
const uint32_t newBinding = mapping.getBindingId(oldBinding);
|
||||
ins.setArg(3, newBinding);
|
||||
}
|
||||
}
|
||||
|
||||
return new DxvkShaderModule(vkd, m_stage, spirvCode);
|
||||
}
|
||||
|
||||
|
||||
|
@ -48,7 +48,7 @@ namespace dxvk {
|
||||
* block. The header, if any, will be skipped over.
|
||||
* \returns Instruction iterator
|
||||
*/
|
||||
SpirvInstructionIterator begin() const {
|
||||
SpirvInstructionIterator begin() {
|
||||
return SpirvInstructionIterator(m_code.data(), m_code.size());
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ namespace dxvk {
|
||||
* Points to the end of the instruction block.
|
||||
* \returns Instruction iterator
|
||||
*/
|
||||
SpirvInstructionIterator end() const {
|
||||
SpirvInstructionIterator end() {
|
||||
return SpirvInstructionIterator(nullptr, 0);
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,7 @@ namespace dxvk {
|
||||
public:
|
||||
|
||||
SpirvInstruction() { }
|
||||
SpirvInstruction(
|
||||
const uint32_t* code, uint32_t size)
|
||||
SpirvInstruction(uint32_t* code, uint32_t size)
|
||||
: m_code(code), m_size(size) { }
|
||||
|
||||
/**
|
||||
@ -54,10 +53,21 @@ namespace dxvk {
|
||||
return id < m_size ? m_code[id] : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes the value of an argument
|
||||
*
|
||||
* \param [in] id Argument index, starting at 1
|
||||
* \param [in] word New argument word
|
||||
*/
|
||||
void setArg(uint32_t id, uint32_t word) const {
|
||||
if (id < m_size)
|
||||
m_code[id] = word;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t const* m_code = nullptr;
|
||||
uint32_t m_size = 0;
|
||||
uint32_t* m_code = nullptr;
|
||||
uint32_t m_size = 0;
|
||||
|
||||
};
|
||||
|
||||
@ -73,7 +83,7 @@ namespace dxvk {
|
||||
public:
|
||||
|
||||
SpirvInstructionIterator() { }
|
||||
SpirvInstructionIterator(const uint32_t* code, uint32_t size)
|
||||
SpirvInstructionIterator(uint32_t* code, uint32_t size)
|
||||
: m_code(size != 0 ? code : nullptr), m_size(size) {
|
||||
if ((size >= 5) && (m_code[0] == spv::MagicNumber))
|
||||
this->advance(5);
|
||||
@ -100,8 +110,8 @@ namespace dxvk {
|
||||
|
||||
private:
|
||||
|
||||
uint32_t const* m_code = nullptr;
|
||||
uint32_t m_size = 0;
|
||||
uint32_t* m_code = nullptr;
|
||||
uint32_t m_size = 0;
|
||||
|
||||
void advance(uint32_t n) {
|
||||
if (n < m_size) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user