[dxbc] Initial support for sample instruction

This commit is contained in:
Philip Rebohle 2017-12-10 12:08:20 +01:00
parent 7c03495d74
commit b4493d90d8
4 changed files with 95 additions and 25 deletions

View File

@ -65,6 +65,9 @@ namespace dxvk {
case DxbcOpcode::Ret:
return this->opRet(ins);
case DxbcOpcode::Sample:
return this->opSample(ins);
default:
Logger::err(str::format(
"DxbcCompiler::processInstruction: Unhandled opcode: ",
@ -275,6 +278,33 @@ namespace dxvk {
}
void DxbcCompiler::opSample(const DxbcInstruction& ins) {
// TODO support address offset
// TODO support more sample ops
auto dstOp = ins.operand(0);
auto coordOp = ins.operand(dstOp.length());
auto texture = ins.operand(dstOp.length() + coordOp.length());
auto sampler = ins.operand(dstOp.length() + coordOp.length() + texture.length());
if ((texture.token().indexDimension() != 1)
|| (sampler.token().indexDimension() != 1))
throw DxvkError("DXBC: opSample: Invalid operand index dimensions");
uint32_t textureId = texture.index(0).immPart();
uint32_t samplerId = sampler.index(0).immPart();
DxbcValue coord = this->loadOperand(coordOp,
DxbcComponentMask(true, true, true, true),
DxbcScalarType::Float32);
DxbcComponentMask mask = this->getDstOperandMask(dstOp);
DxbcValue value = m_gen->texSample(textureId, samplerId, coord);
value = this->selectOperandComponents(texture.token(), value, mask);
this->storeOperand(dstOp, value, mask);
}
DxbcValue DxbcCompiler::getDynamicIndexValue(const DxbcOperandIndex& index) {
DxbcValue immPart;
DxbcValue relPart;

View File

@ -63,6 +63,9 @@ namespace dxvk {
void opRet(
const DxbcInstruction& ins);
void opSample(
const DxbcInstruction& ins);
DxbcValue getDynamicIndexValue(
const DxbcOperandIndex& index);

View File

@ -93,7 +93,7 @@ namespace dxvk {
case DxbcResourceReturnType::Uint: sampledTypeId = m_module.defIntType (32, 0); break;
}
uint32_t resourceTypeId = 0;
uint32_t textureTypeId = 0;
switch (resourceType) {
default:
@ -102,50 +102,50 @@ namespace dxvk {
resourceType));
case DxbcResourceDim::Texture1D:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::Dim1D, 2, 0, 0, 1,
textureTypeId = m_module.defImageType(
sampledTypeId, spv::Dim1D, 0, 0, 0, 1,
spv::ImageFormatUnknown);
break;
case DxbcResourceDim::Texture1DArr:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::Dim1D, 2, 1, 0, 1,
textureTypeId = m_module.defImageType(
sampledTypeId, spv::Dim1D, 0, 1, 0, 1,
spv::ImageFormatUnknown);
break;
case DxbcResourceDim::Texture2D:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::Dim2D, 2, 0, 0, 1,
textureTypeId = m_module.defImageType(
sampledTypeId, spv::Dim2D, 0, 0, 0, 1,
spv::ImageFormatUnknown);
break;
case DxbcResourceDim::Texture2DArr:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::Dim2D, 2, 1, 0, 1,
textureTypeId = m_module.defImageType(
sampledTypeId, spv::Dim2D, 0, 1, 0, 1,
spv::ImageFormatUnknown);
break;
case DxbcResourceDim::Texture3D:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::Dim3D, 2, 0, 0, 1,
textureTypeId = m_module.defImageType(
sampledTypeId, spv::Dim3D, 0, 0, 0, 1,
spv::ImageFormatUnknown);
break;
case DxbcResourceDim::TextureCube:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::DimCube, 2, 0, 0, 1,
textureTypeId = m_module.defImageType(
sampledTypeId, spv::DimCube, 0, 0, 0, 1,
spv::ImageFormatUnknown);
break;
case DxbcResourceDim::TextureCubeArr:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::DimCube, 2, 1, 0, 1,
textureTypeId = m_module.defImageType(
sampledTypeId, spv::DimCube, 0, 1, 0, 1,
spv::ImageFormatUnknown);
break;
}
uint32_t resourcePtrType = m_module.defPointerType(
resourceTypeId, spv::StorageClassUniformConstant);
textureTypeId, spv::StorageClassUniformConstant);
uint32_t varId = m_module.newVar(resourcePtrType,
spv::StorageClassUniformConstant);
@ -153,9 +153,9 @@ namespace dxvk {
m_module.setDebugName(varId,
str::format("t", registerId).c_str());
m_resources.at(registerId).varId = varId;
m_resources.at(registerId).sampledTypeId = sampledTypeId;
m_resources.at(registerId).resourceTypeId = resourceTypeId;
m_textures.at(registerId).varId = varId;
m_textures.at(registerId).sampledTypeId = sampledTypeId;
m_textures.at(registerId).textureTypeId = textureTypeId;
// Compute the DXVK binding slot index for the resource.
// D3D11 needs to bind the actual resource to this slot.
@ -187,7 +187,8 @@ namespace dxvk {
m_module.setDebugName(varId,
str::format("s", samplerId).c_str());
m_samplers.at(samplerId).varId = varId;
m_samplers.at(samplerId).varId = varId;
m_samplers.at(samplerId).typeId = samplerType;
// Compute binding slot index for the sampler
uint32_t bindingId = computeResourceSlotId(m_shaderStage,
@ -552,6 +553,36 @@ namespace dxvk {
}
DxbcValue DxbcCodeGen::texSample(
const uint32_t textureId,
const uint32_t samplerId,
const DxbcValue& coordinates) {
// Combine the texture and the sampler into a sampled image
uint32_t sampledImageType = m_module.defSampledImageType(
m_textures.at(textureId).textureTypeId);
uint32_t sampledImageId = m_module.opSampledImage(
sampledImageType,
m_module.opLoad(
m_textures.at(textureId).textureTypeId,
m_textures.at(textureId).varId),
m_module.opLoad(
m_samplers.at(samplerId).typeId,
m_samplers.at(samplerId).varId));
// Sampling an image in SPIR-V always returns a four-component
// vector, so we need to declare the corresponding type here
// TODO infer sampled type properly
DxbcValue result;
result.type = DxbcValueType(DxbcScalarType::Float32, 4);
result.valueId = m_module.opImageSampleImplicitLod(
this->defValueType(result.type),
sampledImageId,
this->regExtract(coordinates, DxbcComponentMask(true, true, false, false)).valueId);
return result;
}
Rc<DxbcCodeGen> DxbcCodeGen::create(
const DxbcProgramVersion& version,
const Rc<DxbcIsgn>& isgn,

View File

@ -41,7 +41,8 @@ namespace dxvk {
* Stores a sampler variable.
*/
struct DxbcSampler {
uint32_t varId = 0;
uint32_t varId = 0;
uint32_t typeId = 0;
};
@ -51,9 +52,9 @@ namespace dxvk {
* Stores the sampler variable as well as
*/
struct DxbcShaderResource {
uint32_t varId = 0;
uint32_t sampledTypeId = 0;
uint32_t resourceTypeId = 0;
uint32_t varId = 0;
uint32_t sampledTypeId = 0;
uint32_t textureTypeId = 0;
};
@ -149,6 +150,11 @@ namespace dxvk {
const DxbcValue& val,
DxbcComponentMask mask);
DxbcValue texSample(
const uint32_t textureId,
const uint32_t samplerId,
const DxbcValue& coordinates);
virtual void dclInterfaceVar(
DxbcOperandType regType,
uint32_t regId,
@ -191,7 +197,7 @@ namespace dxvk {
std::array<DxbcConstantBuffer, 16> m_constantBuffers;
std::array<DxbcSampler, 16> m_samplers;
std::array<DxbcShaderResource, 128> m_resources;
std::array<DxbcShaderResource, 128> m_textures;
std::vector<DxvkResourceSlot> m_resourceSlots;