Commit 618bebcd by Olli Etuaho Committed by Commit Bot

Pass texture base level to shaders on D3D11

The base level is passed to shaders in an array included in the driver uniform block. This is done on feature levels above 9_3, which treat samplers as indices to sampler arrays in shaders. A separate uniform block couldn't be used for the sampler metadata, since that would bring the number of available uniform blocks down to below minimum level defined by GLES 3.0. BUG=angleproject:596 TEST=angle_end2end_tests Change-Id: Ie040521402f9996d51a978aeeba9222e9dd761ce Reviewed-on: https://chromium-review.googlesource.com/326290Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent d14e3c45
......@@ -512,6 +512,11 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
out << " float2 dx_ViewScale : packoffset(c3);\n";
}
if (mOutputType == SH_HLSL_4_1_OUTPUT)
{
mUniformHLSL->samplerMetadataUniforms(out, "c4");
}
out << "};\n";
}
else
......@@ -614,6 +619,11 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
out << " float2 dx_ViewCoords : packoffset(c2);\n";
out << " float2 dx_ViewScale : packoffset(c3);\n";
if (mOutputType == SH_HLSL_4_1_OUTPUT)
{
mUniformHLSL->samplerMetadataUniforms(out, "c4");
}
out << "};\n"
"\n";
}
......
......@@ -246,6 +246,15 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
}
}
void UniformHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg)
{
// If mSamplerRegister is 0 the shader doesn't use any textures.
if (mSamplerRegister > 0)
{
out << " int samplerMetadata[" << mSamplerRegister << "] : packoffset(" << reg << ");\n";
}
}
TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
{
TString interfaceBlocks;
......
......@@ -31,6 +31,10 @@ class UniformHLSL : angle::NonCopyable
void uniformsHeader(TInfoSinkBase &out,
ShShaderOutput outputType,
const ReferencedSymbols &referencedUniforms);
// Must be called after uniformsHeader
void samplerMetadataUniforms(TInfoSinkBase &out, const char *reg);
TString interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks);
// Used for direct index references
......
......@@ -661,7 +661,7 @@ GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samp
return GL_TEXTURE_2D;
}
GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
GLuint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
{
switch (type)
{
......@@ -671,7 +671,7 @@ GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
return mUsedVertexSamplerRange;
default:
UNREACHABLE();
return 0;
return 0u;
}
}
......
......@@ -145,7 +145,7 @@ class ProgramD3D : public ProgramImpl
unsigned int samplerIndex,
const gl::Caps &caps) const;
GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const;
GLint getUsedSamplerRange(gl::SamplerType type) const;
GLuint getUsedSamplerRange(gl::SamplerType type) const;
void updateSamplerMapping();
bool usesPointSize() const { return mUsesPointSize; }
......
......@@ -282,7 +282,7 @@ gl::Error RendererD3D::generateSwizzles(const gl::Data &data, gl::SamplerType ty
{
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
unsigned int samplerRange = static_cast<unsigned int>(programD3D->getUsedSamplerRange(type));
unsigned int samplerRange = programD3D->getUsedSamplerRange(type);
for (unsigned int i = 0; i < samplerRange; i++)
{
......
......@@ -806,9 +806,11 @@ void Renderer11::initializeDevice()
mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
mSamplerMetadataVS.initData(rendererCaps.maxVertexTextureImageUnits);
mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
mSamplerMetadataPS.initData(rendererCaps.maxTextureImageUnits);
mStateManager.initialize(rendererCaps);
......@@ -1154,6 +1156,11 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type,
// Storage should exist, texture should be complete
ASSERT(storage);
// Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the
// sampler state since having it in contiguous memory makes it possible to memcpy to a constant
// buffer, and it doesn't affect the state set by PSSetSamplers/VSSetSamplers.
SamplerMetadataD3D11 *metadata = nullptr;
if (type == gl::SAMPLER_PIXEL)
{
ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits);
......@@ -1175,6 +1182,8 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type,
}
mForceSetPixelSamplerStates[index] = false;
metadata = &mSamplerMetadataPS;
}
else if (type == gl::SAMPLER_VERTEX)
{
......@@ -1197,9 +1206,14 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type,
}
mForceSetVertexSamplerStates[index] = false;
metadata = &mSamplerMetadataVS;
}
else UNREACHABLE();
ASSERT(metadata != nullptr);
metadata->update(index, texture->getBaseLevel());
return gl::Error(GL_NO_ERROR);
}
......@@ -2185,78 +2199,63 @@ gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
if (mCurrentVertexConstantBuffer != vertexConstantBuffer)
{
mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer);
mDeviceContext->VSSetConstantBuffers(
d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, &vertexConstantBuffer);
mCurrentVertexConstantBuffer = vertexConstantBuffer;
}
if (mCurrentPixelConstantBuffer != pixelConstantBuffer)
{
mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer);
mDeviceContext->PSSetConstantBuffers(
d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, &pixelConstantBuffer);
mCurrentPixelConstantBuffer = pixelConstantBuffer;
}
// Driver uniforms
if (!mDriverConstantBufferVS)
{
D3D11_BUFFER_DESC constantBufferDescription = {0};
constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants11);
constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constantBufferDescription.CPUAccessFlags = 0;
constantBufferDescription.MiscFlags = 0;
constantBufferDescription.StructureByteStride = 0;
HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS);
d3d11::InitConstantBufferDesc(
&constantBufferDescription,
sizeof(dx_VertexConstants11) + mSamplerMetadataVS.sizeBytes());
HRESULT result =
mDevice->CreateBuffer(&constantBufferDescription, nullptr, &mDriverConstantBufferVS);
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader constant buffer, result: 0x%X.", result);
}
mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS);
mDeviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
&mDriverConstantBufferVS);
}
if (!mDriverConstantBufferPS)
{
D3D11_BUFFER_DESC constantBufferDescription = {0};
constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants11);
constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constantBufferDescription.CPUAccessFlags = 0;
constantBufferDescription.MiscFlags = 0;
constantBufferDescription.StructureByteStride = 0;
HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS);
d3d11::InitConstantBufferDesc(&constantBufferDescription,
sizeof(dx_PixelConstants11) + mSamplerMetadataPS.sizeBytes());
HRESULT result =
mDevice->CreateBuffer(&constantBufferDescription, nullptr, &mDriverConstantBufferPS);
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader constant buffer, result: 0x%X.", result);
}
mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS);
mDeviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
&mDriverConstantBufferPS);
}
// Sampler metadata and driver constants need to coexist in the same constant buffer to conserve
// constant buffer slots. We update both in the constant buffer if needed.
const dx_VertexConstants11 &vertexConstants = mStateManager.getVertexConstants();
if (memcmp(&vertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants11)) != 0)
{
ASSERT(mDriverConstantBufferVS != nullptr);
if (mDriverConstantBufferVS)
{
mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &vertexConstants,
16, 0);
memcpy(&mAppliedVertexConstants, &vertexConstants, sizeof(dx_VertexConstants11));
}
}
size_t samplerMetadataReferencedBytesVS = sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) *
programD3D.getUsedSamplerRange(gl::SAMPLER_VERTEX);
applyDriverConstantsIfNeeded(&mAppliedVertexConstants, vertexConstants, &mSamplerMetadataVS,
samplerMetadataReferencedBytesVS, mDriverConstantBufferVS);
const dx_PixelConstants11 &pixelConstants = mStateManager.getPixelConstants();
if (memcmp(&pixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants11)) != 0)
{
ASSERT(mDriverConstantBufferPS != nullptr);
if (mDriverConstantBufferPS)
{
mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &pixelConstants, 16,
0);
memcpy(&mAppliedPixelConstants, &pixelConstants, sizeof(dx_PixelConstants11));
}
}
size_t samplerMetadataReferencedBytesPS = sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) *
programD3D.getUsedSamplerRange(gl::SAMPLER_PIXEL);
applyDriverConstantsIfNeeded(&mAppliedPixelConstants, pixelConstants, &mSamplerMetadataPS,
samplerMetadataReferencedBytesPS, mDriverConstantBufferPS);
// GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary
if (programD3D.usesGeometryShader(drawMode))
......@@ -2265,17 +2264,89 @@ gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
{
ASSERT(mDriverConstantBufferPS != nullptr);
if (mDriverConstantBufferPS)
{
mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
}
mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
}
}
return gl::Error(GL_NO_ERROR);
}
// SamplerMetadataD3D11 implementation
Renderer11::SamplerMetadataD3D11::SamplerMetadataD3D11() : mDirty(true)
{
}
Renderer11::SamplerMetadataD3D11::~SamplerMetadataD3D11()
{
}
void Renderer11::SamplerMetadataD3D11::initData(unsigned int samplerCount)
{
mSamplerMetadata.resize(samplerCount);
}
void Renderer11::SamplerMetadataD3D11::update(unsigned int samplerIndex, unsigned int baseLevel)
{
if (mSamplerMetadata[samplerIndex].baseLevel[0] != static_cast<int>(baseLevel))
{
mSamplerMetadata[samplerIndex].baseLevel[0] = static_cast<int>(baseLevel);
mDirty = true;
}
}
const Renderer11::SamplerMetadataD3D11::dx_SamplerMetadata *
Renderer11::SamplerMetadataD3D11::getData() const
{
return mSamplerMetadata.data();
}
size_t Renderer11::SamplerMetadataD3D11::sizeBytes() const
{
return sizeof(SamplerMetadataD3D11::dx_SamplerMetadata) * mSamplerMetadata.size();
}
template <class TShaderConstants>
void Renderer11::applyDriverConstantsIfNeeded(TShaderConstants *appliedConstants,
const TShaderConstants &constants,
SamplerMetadataD3D11 *samplerMetadata,
size_t samplerMetadataReferencedBytes,
ID3D11Buffer *driverConstantBuffer)
{
ASSERT(driverConstantBuffer != nullptr);
if (memcmp(appliedConstants, &constants, sizeof(TShaderConstants)) != 0 ||
samplerMetadata->isDirty())
{
memcpy(appliedConstants, &constants, sizeof(TShaderConstants));
D3D11_MAPPED_SUBRESOURCE mapping = {0};
HRESULT result =
mDeviceContext->Map(driverConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapping);
ASSERT(SUCCEEDED(result));
UNUSED_ASSERTION_VARIABLE(result);
memcpy(mapping.pData, appliedConstants, sizeof(TShaderConstants));
// Previous buffer contents were discarded, so we need to refresh also the area of the
// buffer that isn't used by this program.
memcpy(&reinterpret_cast<uint8_t *>(mapping.pData)[sizeof(TShaderConstants)],
samplerMetadata->getData(), samplerMetadata->sizeBytes());
mDeviceContext->Unmap(driverConstantBuffer, 0);
}
}
template void Renderer11::applyDriverConstantsIfNeeded<dx_VertexConstants11>(
dx_VertexConstants11 *appliedConstants,
const dx_VertexConstants11 &constants,
SamplerMetadataD3D11 *samplerMetadata,
size_t samplerMetadataReferencedBytes,
ID3D11Buffer *driverConstantBuffer);
template void Renderer11::applyDriverConstantsIfNeeded<dx_PixelConstants11>(
dx_PixelConstants11 *appliedConstants,
const dx_PixelConstants11 &constants,
SamplerMetadataD3D11 *samplerMetadata,
size_t samplerMetadataReferencedBytes,
ID3D11Buffer *driverConstantBuffer);
void Renderer11::markAllStateDirty()
{
TRACE_EVENT0("gpu.angle", "Renderer11::markAllStateDirty");
......
......@@ -14,6 +14,7 @@
#include "libANGLE/AttributeMap.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/d3d/HLSLCompiler.h"
#include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h"
......@@ -336,6 +337,36 @@ class Renderer11 : public RendererD3D
void updateHistograms();
class SamplerMetadataD3D11 final : angle::NonCopyable
{
public:
SamplerMetadataD3D11();
~SamplerMetadataD3D11();
struct dx_SamplerMetadata
{
int baseLevel[4];
};
void initData(unsigned int samplerCount);
void update(unsigned int samplerIndex, unsigned int baseLevel);
const dx_SamplerMetadata *getData() const;
size_t sizeBytes() const;
bool isDirty() const { return mDirty; }
private:
std::vector<dx_SamplerMetadata> mSamplerMetadata;
bool mDirty;
};
template <class TShaderConstants>
void applyDriverConstantsIfNeeded(TShaderConstants *appliedConstants,
const TShaderConstants &constants,
SamplerMetadataD3D11 *samplerMetadata,
size_t samplerMetadataReferencedBytes,
ID3D11Buffer *driverConstantBuffer);
HMODULE mD3d11Module;
HMODULE mDxgiModule;
HMODULE mDCompModule;
......@@ -395,6 +426,7 @@ class Renderer11 : public RendererD3D
dx_VertexConstants11 mAppliedVertexConstants;
ID3D11Buffer *mDriverConstantBufferVS;
SamplerMetadataD3D11 mSamplerMetadataVS;
ID3D11Buffer *mCurrentVertexConstantBuffer;
unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
......@@ -402,6 +434,7 @@ class Renderer11 : public RendererD3D
dx_PixelConstants11 mAppliedPixelConstants;
ID3D11Buffer *mDriverConstantBufferPS;
SamplerMetadataD3D11 mSamplerMetadataPS;
ID3D11Buffer *mCurrentPixelConstantBuffer;
unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
GLintptr mCurrentConstantBufferPSOffset[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
......
......@@ -754,21 +754,19 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
}
}
static size_t GetReservedVertexUniformBuffers()
{
// Reserve one buffer for the application uniforms, and one for driver uniforms
return 2;
}
static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
case D3D_FEATURE_LEVEL_11_1:
case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers();
case D3D_FEATURE_LEVEL_11_0:
return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
case D3D_FEATURE_LEVEL_10_1:
case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers();
case D3D_FEATURE_LEVEL_10_0:
return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
// Uniform blocks not supported on D3D11 Feature Level 9
case D3D_FEATURE_LEVEL_9_3:
......@@ -871,21 +869,19 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
}
}
static size_t GetReservedPixelUniformBuffers()
{
// Reserve one buffer for the application uniforms, and one for driver uniforms
return 2;
}
static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
case D3D_FEATURE_LEVEL_11_1:
case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers();
case D3D_FEATURE_LEVEL_11_0:
return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
case D3D_FEATURE_LEVEL_10_1:
case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers();
case D3D_FEATURE_LEVEL_10_0:
return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
// Uniform blocks not supported on D3D11 Feature Level 9
case D3D_FEATURE_LEVEL_9_3:
......@@ -1501,6 +1497,16 @@ WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel)
return workarounds;
}
void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth)
{
constantBufferDescription->ByteWidth = static_cast<UINT>(byteWidth);
constantBufferDescription->Usage = D3D11_USAGE_DYNAMIC;
constantBufferDescription->BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constantBufferDescription->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
constantBufferDescription->MiscFlags = 0;
constantBufferDescription->StructureByteStride = 0;
}
} // namespace d3d11
TextureHelper11::TextureHelper11()
......
......@@ -343,6 +343,16 @@ void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, c
}
WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel);
enum ReservedConstantBufferSlot
{
RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK = 0,
RESERVED_CONSTANT_BUFFER_SLOT_DRIVER = 1,
RESERVED_CONSTANT_BUFFER_SLOT_COUNT = 2
};
void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth);
} // namespace d3d11
// A helper class which wraps a 2D or 3D texture.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment