mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-30 11:52:11 +01:00
[dxvk] Implementing unbound resource handling (4/4)
The shader compiler now queries whether a constant buffer or texture is bound before trying to access it for reading. This is not yet implemented for image fetch operations, atomic operations, or buffer load/store ops.
This commit is contained in:
parent
fe02c5d6b9
commit
74722fa693
@ -1878,6 +1878,7 @@ namespace dxvk {
|
|||||||
// bufinfo takes two arguments
|
// bufinfo takes two arguments
|
||||||
// (dst0) The destination register
|
// (dst0) The destination register
|
||||||
// (src0) The buffer register to query
|
// (src0) The buffer register to query
|
||||||
|
// TODO Check if resource is bound
|
||||||
const DxbcBufferInfo bufferInfo = getBufferInfo(ins.src[0]);
|
const DxbcBufferInfo bufferInfo = getBufferInfo(ins.src[0]);
|
||||||
|
|
||||||
// We'll store this as a scalar unsigned integer
|
// We'll store this as a scalar unsigned integer
|
||||||
@ -1912,6 +1913,7 @@ namespace dxvk {
|
|||||||
// (src0) Structure index
|
// (src0) Structure index
|
||||||
// (src1) Byte offset
|
// (src1) Byte offset
|
||||||
// (src2) Source register
|
// (src2) Source register
|
||||||
|
// TODO Check if resource is bound
|
||||||
const bool isStructured = ins.op == DxbcOpcode::LdStructured;
|
const bool isStructured = ins.op == DxbcOpcode::LdStructured;
|
||||||
|
|
||||||
// Source register. The exact way we access
|
// Source register. The exact way we access
|
||||||
@ -1946,6 +1948,7 @@ namespace dxvk {
|
|||||||
// (src0) Structure index
|
// (src0) Structure index
|
||||||
// (src1) Byte offset
|
// (src1) Byte offset
|
||||||
// (src2) Source register
|
// (src2) Source register
|
||||||
|
// TODO Check if resource is bound
|
||||||
const bool isStructured = ins.op == DxbcOpcode::StoreStructured;
|
const bool isStructured = ins.op == DxbcOpcode::StoreStructured;
|
||||||
|
|
||||||
// Source register. The exact way we access
|
// Source register. The exact way we access
|
||||||
@ -2033,6 +2036,7 @@ namespace dxvk {
|
|||||||
// (dst0) The destination register
|
// (dst0) The destination register
|
||||||
// (src0) Resource LOD to query
|
// (src0) Resource LOD to query
|
||||||
// (src1) Resource to query
|
// (src1) Resource to query
|
||||||
|
// TODO Check if resource is bound
|
||||||
const DxbcResinfoType resinfoType = ins.controls.resinfoType;
|
const DxbcResinfoType resinfoType = ins.controls.resinfoType;
|
||||||
|
|
||||||
if (ins.src[1].type != DxbcOperandType::Resource) {
|
if (ins.src[1].type != DxbcOperandType::Resource) {
|
||||||
@ -2162,6 +2166,7 @@ namespace dxvk {
|
|||||||
// (dst0) The destination register
|
// (dst0) The destination register
|
||||||
// (src0) Source address
|
// (src0) Source address
|
||||||
// (src1) Source texture
|
// (src1) Source texture
|
||||||
|
// TODO Check if resource is bound
|
||||||
const uint32_t textureId = ins.src[1].idx[0].offset;
|
const uint32_t textureId = ins.src[1].idx[0].offset;
|
||||||
|
|
||||||
// Image type, which stores the image dimensions etc.
|
// Image type, which stores the image dimensions etc.
|
||||||
@ -2209,12 +2214,21 @@ namespace dxvk {
|
|||||||
const DxbcRegisterValue coord =
|
const DxbcRegisterValue coord =
|
||||||
emitRegisterExtract(address, coordArrayMask);
|
emitRegisterExtract(address, coordArrayMask);
|
||||||
|
|
||||||
|
// Fetch texels only if the resource is actually bound
|
||||||
|
const uint32_t labelMerge = m_module.allocateId();
|
||||||
|
const uint32_t labelBound = m_module.allocateId();
|
||||||
|
const uint32_t labelUnbound = m_module.allocateId();
|
||||||
|
|
||||||
|
m_module.opSelectionMerge(labelMerge, spv::SelectionControlMaskNone);
|
||||||
|
m_module.opBranchConditional(m_textures.at(textureId).specId, labelBound, labelUnbound);
|
||||||
|
m_module.opLabel(labelBound);
|
||||||
|
|
||||||
|
// Reading a typed image or buffer view
|
||||||
|
// always returns a four-component vector.
|
||||||
const uint32_t imageId = m_module.opLoad(
|
const uint32_t imageId = m_module.opLoad(
|
||||||
m_textures.at(textureId).imageTypeId,
|
m_textures.at(textureId).imageTypeId,
|
||||||
m_textures.at(textureId).varId);
|
m_textures.at(textureId).varId);
|
||||||
|
|
||||||
// Reading a typed image or buffer view
|
|
||||||
// always returns a four-component vector.
|
|
||||||
DxbcRegisterValue result;
|
DxbcRegisterValue result;
|
||||||
result.type.ctype = m_textures.at(textureId).sampledType;
|
result.type.ctype = m_textures.at(textureId).sampledType;
|
||||||
result.type.ccount = 4;
|
result.type.ccount = 4;
|
||||||
@ -2226,7 +2240,36 @@ namespace dxvk {
|
|||||||
// and the destination operand's write mask
|
// and the destination operand's write mask
|
||||||
result = emitRegisterSwizzle(result,
|
result = emitRegisterSwizzle(result,
|
||||||
ins.src[1].swizzle, ins.dst[0].mask);
|
ins.src[1].swizzle, ins.dst[0].mask);
|
||||||
emitRegisterStore(ins.dst[0], result);
|
|
||||||
|
// If the texture is not bound, return zeroes
|
||||||
|
m_module.opBranch(labelMerge);
|
||||||
|
m_module.opLabel(labelUnbound);
|
||||||
|
|
||||||
|
DxbcRegisterValue zeroes = [&] {
|
||||||
|
switch (result.type.ctype) {
|
||||||
|
case DxbcScalarType::Float32: return emitBuildConstVecf32(0.0f, 0.0f, 0.0f, 0.0f, ins.dst[0].mask);
|
||||||
|
case DxbcScalarType::Uint32: return emitBuildConstVecu32(0u, 0u, 0u, 0u, ins.dst[0].mask);
|
||||||
|
case DxbcScalarType::Sint32: return emitBuildConstVeci32(0, 0, 0, 0, ins.dst[0].mask);
|
||||||
|
default: throw DxvkError("DxbcCompiler: Invalid scalar type");
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
m_module.opBranch(labelMerge);
|
||||||
|
m_module.opLabel(labelMerge);
|
||||||
|
|
||||||
|
// Merge the result with a phi function
|
||||||
|
const std::array<SpirvPhiLabel, 2> phiLabels = {{
|
||||||
|
{ result.id, labelBound },
|
||||||
|
{ zeroes.id, labelUnbound },
|
||||||
|
}};
|
||||||
|
|
||||||
|
DxbcRegisterValue mergedResult;
|
||||||
|
mergedResult.type = result.type;
|
||||||
|
mergedResult.id = m_module.opPhi(
|
||||||
|
getVectorTypeId(mergedResult.type),
|
||||||
|
phiLabels.size(), phiLabels.data());
|
||||||
|
|
||||||
|
emitRegisterStore(ins.dst[0], mergedResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2312,16 +2355,6 @@ namespace dxvk {
|
|||||||
? m_module.defSampledImageType(m_textures.at(textureId).depthTypeId)
|
? m_module.defSampledImageType(m_textures.at(textureId).depthTypeId)
|
||||||
: m_module.defSampledImageType(m_textures.at(textureId).colorTypeId);
|
: m_module.defSampledImageType(m_textures.at(textureId).colorTypeId);
|
||||||
|
|
||||||
// Combine the texture and the sampler into a sampled image
|
|
||||||
const uint32_t sampledImageId = m_module.opSampledImage(
|
|
||||||
sampledImageType,
|
|
||||||
m_module.opLoad(
|
|
||||||
m_textures.at(textureId).imageTypeId,
|
|
||||||
m_textures.at(textureId).varId),
|
|
||||||
m_module.opLoad(
|
|
||||||
m_samplers.at(samplerId).typeId,
|
|
||||||
m_samplers.at(samplerId).varId));
|
|
||||||
|
|
||||||
// Accumulate additional image operands. These are
|
// Accumulate additional image operands. These are
|
||||||
// not part of the actual operand token in SPIR-V.
|
// not part of the actual operand token in SPIR-V.
|
||||||
SpirvImageOperands imageOperands;
|
SpirvImageOperands imageOperands;
|
||||||
@ -2339,6 +2372,25 @@ namespace dxvk {
|
|||||||
imageLayerDim, offsetIds.data());
|
imageLayerDim, offsetIds.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only execute the sample operation if the resource is bound
|
||||||
|
const uint32_t labelMerge = m_module.allocateId();
|
||||||
|
const uint32_t labelBound = m_module.allocateId();
|
||||||
|
const uint32_t labelUnbound = m_module.allocateId();
|
||||||
|
|
||||||
|
m_module.opSelectionMerge(labelMerge, spv::SelectionControlMaskNone);
|
||||||
|
m_module.opBranchConditional(m_textures.at(textureId).specId, labelBound, labelUnbound);
|
||||||
|
m_module.opLabel(labelBound);
|
||||||
|
|
||||||
|
// Combine the texture and the sampler into a sampled image
|
||||||
|
const uint32_t sampledImageId = m_module.opSampledImage(
|
||||||
|
sampledImageType,
|
||||||
|
m_module.opLoad(
|
||||||
|
m_textures.at(textureId).imageTypeId,
|
||||||
|
m_textures.at(textureId).varId),
|
||||||
|
m_module.opLoad(
|
||||||
|
m_samplers.at(samplerId).typeId,
|
||||||
|
m_samplers.at(samplerId).varId));
|
||||||
|
|
||||||
// Sampling an image always returns a four-component
|
// Sampling an image always returns a four-component
|
||||||
// vector, whereas depth-compare ops return a scalar.
|
// vector, whereas depth-compare ops return a scalar.
|
||||||
DxbcRegisterValue result;
|
DxbcRegisterValue result;
|
||||||
@ -2384,7 +2436,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
// Sample operation with explicit LOD
|
// Sample operation with explicit LOD
|
||||||
case DxbcOpcode::SampleL: {
|
case DxbcOpcode::SampleL: {
|
||||||
|
|
||||||
imageOperands.flags |= spv::ImageOperandsLodMask;
|
imageOperands.flags |= spv::ImageOperandsLodMask;
|
||||||
imageOperands.sLod = explicitLod.id;
|
imageOperands.sLod = explicitLod.id;
|
||||||
|
|
||||||
@ -2407,7 +2458,35 @@ namespace dxvk {
|
|||||||
textureReg.swizzle, ins.dst[0].mask);
|
textureReg.swizzle, ins.dst[0].mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
emitRegisterStore(ins.dst[0], result);
|
// If the texture is not bound, return zeroes
|
||||||
|
m_module.opBranch(labelMerge);
|
||||||
|
m_module.opLabel(labelUnbound);
|
||||||
|
|
||||||
|
DxbcRegisterValue zeroes = [&] {
|
||||||
|
switch (result.type.ctype) {
|
||||||
|
case DxbcScalarType::Float32: return emitBuildConstVecf32(0.0f, 0.0f, 0.0f, 0.0f, ins.dst[0].mask);
|
||||||
|
case DxbcScalarType::Uint32: return emitBuildConstVecu32(0u, 0u, 0u, 0u, ins.dst[0].mask);
|
||||||
|
case DxbcScalarType::Sint32: return emitBuildConstVeci32(0, 0, 0, 0, ins.dst[0].mask);
|
||||||
|
default: throw DxvkError("DxbcCompiler: Invalid scalar type");
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
m_module.opBranch(labelMerge);
|
||||||
|
m_module.opLabel(labelMerge);
|
||||||
|
|
||||||
|
// Merge the result with a phi function
|
||||||
|
const std::array<SpirvPhiLabel, 2> phiLabels = {{
|
||||||
|
{ result.id, labelBound },
|
||||||
|
{ zeroes.id, labelUnbound },
|
||||||
|
}};
|
||||||
|
|
||||||
|
DxbcRegisterValue mergedResult;
|
||||||
|
mergedResult.type = result.type;
|
||||||
|
mergedResult.id = m_module.opPhi(
|
||||||
|
getVectorTypeId(mergedResult.type),
|
||||||
|
phiLabels.size(), phiLabels.data());
|
||||||
|
|
||||||
|
emitRegisterStore(ins.dst[0], mergedResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2850,6 +2929,7 @@ namespace dxvk {
|
|||||||
float z,
|
float z,
|
||||||
float w,
|
float w,
|
||||||
const DxbcRegMask& writeMask) {
|
const DxbcRegMask& writeMask) {
|
||||||
|
// TODO refactor these functions into one single template
|
||||||
std::array<uint32_t, 4> ids = { 0, 0, 0, 0 };
|
std::array<uint32_t, 4> ids = { 0, 0, 0, 0 };
|
||||||
uint32_t componentIndex = 0;
|
uint32_t componentIndex = 0;
|
||||||
|
|
||||||
@ -2870,6 +2950,58 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxbcRegisterValue DxbcCompiler::emitBuildConstVecu32(
|
||||||
|
uint32_t x,
|
||||||
|
uint32_t y,
|
||||||
|
uint32_t z,
|
||||||
|
uint32_t w,
|
||||||
|
const DxbcRegMask& writeMask) {
|
||||||
|
std::array<uint32_t, 4> ids = { 0, 0, 0, 0 };
|
||||||
|
uint32_t componentIndex = 0;
|
||||||
|
|
||||||
|
if (writeMask[0]) ids[componentIndex++] = m_module.constu32(x);
|
||||||
|
if (writeMask[1]) ids[componentIndex++] = m_module.constu32(y);
|
||||||
|
if (writeMask[2]) ids[componentIndex++] = m_module.constu32(z);
|
||||||
|
if (writeMask[3]) ids[componentIndex++] = m_module.constu32(w);
|
||||||
|
|
||||||
|
DxbcRegisterValue result;
|
||||||
|
result.type.ctype = DxbcScalarType::Uint32;
|
||||||
|
result.type.ccount = componentIndex;
|
||||||
|
result.id = componentIndex > 1
|
||||||
|
? m_module.constComposite(
|
||||||
|
getVectorTypeId(result.type),
|
||||||
|
componentIndex, ids.data())
|
||||||
|
: ids[0];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxbcRegisterValue DxbcCompiler::emitBuildConstVeci32(
|
||||||
|
int32_t x,
|
||||||
|
int32_t y,
|
||||||
|
int32_t z,
|
||||||
|
int32_t w,
|
||||||
|
const DxbcRegMask& writeMask) {
|
||||||
|
std::array<uint32_t, 4> ids = { 0, 0, 0, 0 };
|
||||||
|
uint32_t componentIndex = 0;
|
||||||
|
|
||||||
|
if (writeMask[0]) ids[componentIndex++] = m_module.consti32(x);
|
||||||
|
if (writeMask[1]) ids[componentIndex++] = m_module.consti32(y);
|
||||||
|
if (writeMask[2]) ids[componentIndex++] = m_module.consti32(z);
|
||||||
|
if (writeMask[3]) ids[componentIndex++] = m_module.consti32(w);
|
||||||
|
|
||||||
|
DxbcRegisterValue result;
|
||||||
|
result.type.ctype = DxbcScalarType::Sint32;
|
||||||
|
result.type.ccount = componentIndex;
|
||||||
|
result.id = componentIndex > 1
|
||||||
|
? m_module.constComposite(
|
||||||
|
getVectorTypeId(result.type),
|
||||||
|
componentIndex, ids.data())
|
||||||
|
: ids[0];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DxbcRegisterValue DxbcCompiler::emitBuildZero(
|
DxbcRegisterValue DxbcCompiler::emitBuildZero(
|
||||||
DxbcScalarType type) {
|
DxbcScalarType type) {
|
||||||
DxbcRegisterValue result;
|
DxbcRegisterValue result;
|
||||||
@ -3668,6 +3800,58 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxbcRegisterValue DxbcCompiler::emitRegisterLoadRaw(
|
||||||
|
const DxbcRegister& reg) {
|
||||||
|
if (reg.type == DxbcOperandType::ConstantBuffer) {
|
||||||
|
// Constant buffer require special care if they are not bound
|
||||||
|
const uint32_t registerId = reg.idx[0].offset;
|
||||||
|
|
||||||
|
const uint32_t labelMerge = m_module.allocateId();
|
||||||
|
const uint32_t labelBound = m_module.allocateId();
|
||||||
|
const uint32_t labelUnbound = m_module.allocateId();
|
||||||
|
|
||||||
|
m_module.opSelectionMerge(labelMerge, spv::SelectionControlMaskNone);
|
||||||
|
m_module.opBranchConditional(
|
||||||
|
m_constantBuffers.at(registerId).specId,
|
||||||
|
labelBound, labelUnbound);
|
||||||
|
|
||||||
|
// Case 1: Constant buffer is bound.
|
||||||
|
// Load the register value normally.
|
||||||
|
m_module.opLabel(labelBound);
|
||||||
|
DxbcRegisterValue ifBound = emitValueLoad(emitGetOperandPtr(reg));
|
||||||
|
m_module.opBranch(labelMerge);
|
||||||
|
|
||||||
|
// Case 2: Constant buffer is not bound.
|
||||||
|
// Return zeroes unconditionally.
|
||||||
|
m_module.opLabel(labelUnbound);
|
||||||
|
DxbcRegisterValue ifUnbound = emitBuildConstVecf32(
|
||||||
|
0.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
DxbcRegMask(true, true, true, true));
|
||||||
|
m_module.opBranch(labelMerge);
|
||||||
|
|
||||||
|
// Merge the results with a phi function
|
||||||
|
m_module.opLabel(labelMerge);
|
||||||
|
|
||||||
|
const std::array<SpirvPhiLabel, 2> phiLabels = {{
|
||||||
|
{ ifBound.id, labelBound },
|
||||||
|
{ ifUnbound.id, labelUnbound },
|
||||||
|
}};
|
||||||
|
|
||||||
|
DxbcRegisterValue result;
|
||||||
|
result.type.ctype = DxbcScalarType::Float32;
|
||||||
|
result.type.ccount = 4;
|
||||||
|
result.id = m_module.opPhi(
|
||||||
|
getVectorTypeId(result.type),
|
||||||
|
phiLabels.size(),
|
||||||
|
phiLabels.data());
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
// All other operand types can be accessed directly
|
||||||
|
return emitValueLoad(emitGetOperandPtr(reg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DxbcRegisterValue DxbcCompiler::emitRegisterLoad(
|
DxbcRegisterValue DxbcCompiler::emitRegisterLoad(
|
||||||
const DxbcRegister& reg,
|
const DxbcRegister& reg,
|
||||||
DxbcRegMask writeMask) {
|
DxbcRegMask writeMask) {
|
||||||
@ -3710,8 +3894,7 @@ namespace dxvk {
|
|||||||
return emitRegisterBitcast(result, reg.dataType);
|
return emitRegisterBitcast(result, reg.dataType);
|
||||||
} else {
|
} else {
|
||||||
// Load operand from the operand pointer
|
// Load operand from the operand pointer
|
||||||
DxbcRegisterPointer ptr = emitGetOperandPtr(reg);
|
DxbcRegisterValue result = emitRegisterLoadRaw(reg);
|
||||||
DxbcRegisterValue result = emitValueLoad(ptr);
|
|
||||||
|
|
||||||
// Apply operand swizzle to the operand value
|
// Apply operand swizzle to the operand value
|
||||||
result = emitRegisterSwizzle(result, reg.swizzle, writeMask);
|
result = emitRegisterSwizzle(result, reg.swizzle, writeMask);
|
||||||
|
@ -505,6 +505,20 @@ namespace dxvk {
|
|||||||
float w,
|
float w,
|
||||||
const DxbcRegMask& writeMask);
|
const DxbcRegMask& writeMask);
|
||||||
|
|
||||||
|
DxbcRegisterValue emitBuildConstVecu32(
|
||||||
|
uint32_t x,
|
||||||
|
uint32_t y,
|
||||||
|
uint32_t z,
|
||||||
|
uint32_t w,
|
||||||
|
const DxbcRegMask& writeMask);
|
||||||
|
|
||||||
|
DxbcRegisterValue emitBuildConstVeci32(
|
||||||
|
int32_t x,
|
||||||
|
int32_t y,
|
||||||
|
int32_t z,
|
||||||
|
int32_t w,
|
||||||
|
const DxbcRegMask& writeMask);
|
||||||
|
|
||||||
DxbcRegisterValue emitBuildZero(
|
DxbcRegisterValue emitBuildZero(
|
||||||
DxbcScalarType type);
|
DxbcScalarType type);
|
||||||
|
|
||||||
@ -627,6 +641,9 @@ namespace dxvk {
|
|||||||
DxbcRegisterValue value,
|
DxbcRegisterValue value,
|
||||||
DxbcRegMask writeMask);
|
DxbcRegMask writeMask);
|
||||||
|
|
||||||
|
DxbcRegisterValue emitRegisterLoadRaw(
|
||||||
|
const DxbcRegister& reg);
|
||||||
|
|
||||||
DxbcRegisterValue emitRegisterLoad(
|
DxbcRegisterValue emitRegisterLoad(
|
||||||
const DxbcRegister& reg,
|
const DxbcRegister& reg,
|
||||||
DxbcRegMask writeMask);
|
DxbcRegMask writeMask);
|
||||||
|
@ -1086,10 +1086,6 @@ namespace dxvk {
|
|||||||
m_cmd->trackResource(res.sampler);
|
m_cmd->trackResource(res.sampler);
|
||||||
} else {
|
} else {
|
||||||
updatePipelineState |= bs.setUnbound(i);
|
updatePipelineState |= bs.setUnbound(i);
|
||||||
|
|
||||||
m_descriptors[i].image.sampler = VK_NULL_HANDLE;
|
|
||||||
m_descriptors[i].image.imageView = VK_NULL_HANDLE;
|
|
||||||
m_descriptors[i].image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||||
@ -1105,10 +1101,6 @@ namespace dxvk {
|
|||||||
m_cmd->trackResource(res.imageView->image());
|
m_cmd->trackResource(res.imageView->image());
|
||||||
} else {
|
} else {
|
||||||
updatePipelineState |= bs.setUnbound(i);
|
updatePipelineState |= bs.setUnbound(i);
|
||||||
|
|
||||||
m_descriptors[i].image.sampler = VK_NULL_HANDLE;
|
|
||||||
m_descriptors[i].image.imageView = VK_NULL_HANDLE;
|
|
||||||
m_descriptors[i].image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
||||||
@ -1122,8 +1114,6 @@ namespace dxvk {
|
|||||||
m_cmd->trackResource(res.bufferView->buffer()->resource());
|
m_cmd->trackResource(res.bufferView->buffer()->resource());
|
||||||
} else {
|
} else {
|
||||||
updatePipelineState |= bs.setUnbound(i);
|
updatePipelineState |= bs.setUnbound(i);
|
||||||
|
|
||||||
m_descriptors[i].texelBuffer = VK_NULL_HANDLE;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||||
@ -1135,10 +1125,6 @@ namespace dxvk {
|
|||||||
m_cmd->trackResource(res.bufferSlice.resource());
|
m_cmd->trackResource(res.bufferSlice.resource());
|
||||||
} else {
|
} else {
|
||||||
updatePipelineState |= bs.setUnbound(i);
|
updatePipelineState |= bs.setUnbound(i);
|
||||||
|
|
||||||
m_descriptors[i].buffer.buffer = VK_NULL_HANDLE;
|
|
||||||
m_descriptors[i].buffer.offset = 0;
|
|
||||||
m_descriptors[i].buffer.range = 0;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user